1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @fileoverview Implementation of ScreenContext class: key-value storage for 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * values that are shared between C++ and JS sides. 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)cr.define('login', function() { 106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 'use strict'; 116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) function require(condition, message) { 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!condition) { 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) throw Error(message); 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) function checkKeyIsValid(key) { 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) var keyType = typeof key; 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) require(keyType === 'string', 'Invalid type of key: "' + keyType + '".'); 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) function checkValueIsValid(value) { 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) var valueType = typeof value; 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch require((['string', 'boolean', 'number'].indexOf(valueType) != -1 || 26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Array.isArray(value)), 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 'Invalid type of value: "' + valueType + '".'); 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) function ScreenContext() { 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) this.storage_ = {}; 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) this.changes_ = {}; 336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) this.observers_ = {}; 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScreenContext.prototype = { 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Returns stored value for |key| or |defaultValue| if key not found in 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * storage. Throws Error if key not found and |defaultValue| omitted. 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) get: function(key, defaultValue) { 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkKeyIsValid(key); 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (this.hasKey(key)) { 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return this.storage_[key]; 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if (typeof defaultValue !== 'undefined') { 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return defaultValue; 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) throw Error('Key "' + key + '" not found.'); 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }, 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Sets |value| for |key|. Returns true if call changes state of context, 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * false otherwise. 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) set: function(key, value) { 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkKeyIsValid(key); 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkValueIsValid(value); 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (this.hasKey(key) && this.storage_[key] === value) 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) this.changes_[key] = value; 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) this.storage_[key] = value; 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }, 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) hasKey: function(key) { 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkKeyIsValid(key); 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return this.storage_.hasOwnProperty(key); 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }, 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) hasChanges: function() { 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Object.keys(this.changes_).length > 0; 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }, 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Applies |changes| to context. Returns Array of changed keys' names. 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) applyChanges: function(changes) { 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) require(!this.hasChanges(), 'Context has changes.'); 806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) var oldValues = {}; 816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (var key in changes) { 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkKeyIsValid(key); 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkValueIsValid(changes[key]); 846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) oldValues[key] = this.storage_[key]; 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) this.storage_[key] = changes[key]; 866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) var observers = this.cloneObservers_(); 886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (var key in changes) { 896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (observers.hasOwnProperty(key)) { 906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) var keyObservers = observers[key]; 916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (var observerIndex in keyObservers) 926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) keyObservers[observerIndex](changes[key], oldValues[key], key); 936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Object.keys(changes); 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }, 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Returns changes made on context since previous call. 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) getChangesAndReset: function() { 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) var result = this.changes_; 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) this.changes_ = {}; 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 1056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) }, 1066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) addObserver: function(key, observer) { 1086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (!this.observers_.hasOwnProperty(key)) 1096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) this.observers_[key] = []; 1106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (this.observers_[key].indexOf(observer) !== -1) { 1116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) console.warn('Observer already registered.'); 1126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return; 1136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) this.observers_[key].push(observer); 1156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) }, 1166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) removeObserver: function(observer) { 1186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (var key in this.observers_) { 1196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) var observerIndex = this.observers_[key].indexOf(observer); 1206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (observerIndex != -1) 1216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) this.observers_[key].splice(observerIndex, 1); 1226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) }, 1246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) /** 1266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) * Creates deep copy of observers lists. 1276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) * @private 1286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) */ 1296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) cloneObservers_: function() { 1306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) var result = {}; 1316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (var key in this.observers_) 1326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) result[key] = this.observers_[key].slice(); 1336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return result; 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return { 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScreenContext: ScreenContext 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}); 141