OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview Implementation of ScreenContext class: key-value storage for | 6 * @fileoverview Implementation of ScreenContext class: key-value storage for |
7 * values that are shared between C++ and JS sides. | 7 * values that are shared between C++ and JS sides. |
8 */ | 8 */ |
9 cr.define('login', function() { | 9 cr.define('login', function() { |
| 10 'use strict'; |
| 11 |
10 function require(condition, message) { | 12 function require(condition, message) { |
11 if (!condition) { | 13 if (!condition) { |
12 throw Error(message); | 14 throw Error(message); |
13 } | 15 } |
14 } | 16 } |
15 | 17 |
16 function checkKeyIsValid(key) { | 18 function checkKeyIsValid(key) { |
17 var keyType = typeof key; | 19 var keyType = typeof key; |
18 require(keyType === 'string', 'Invalid type of key: "' + keyType + '".'); | 20 require(keyType === 'string', 'Invalid type of key: "' + keyType + '".'); |
19 } | 21 } |
20 | 22 |
21 function checkValueIsValid(value) { | 23 function checkValueIsValid(value) { |
22 var valueType = typeof value; | 24 var valueType = typeof value; |
23 require(['string', 'boolean', 'number'].indexOf(valueType) != -1, | 25 require(['string', 'boolean', 'number'].indexOf(valueType) != -1, |
24 'Invalid type of value: "' + valueType + '".'); | 26 'Invalid type of value: "' + valueType + '".'); |
25 } | 27 } |
26 | 28 |
27 function ScreenContext() { | 29 function ScreenContext() { |
28 this.storage_ = {}; | 30 this.storage_ = {}; |
29 this.changes_ = {}; | 31 this.changes_ = {}; |
| 32 this.observers_ = {}; |
30 } | 33 } |
31 | 34 |
32 ScreenContext.prototype = { | 35 ScreenContext.prototype = { |
33 /** | 36 /** |
34 * Returns stored value for |key| or |defaultValue| if key not found in | 37 * Returns stored value for |key| or |defaultValue| if key not found in |
35 * storage. Throws Error if key not found and |defaultValue| omitted. | 38 * storage. Throws Error if key not found and |defaultValue| omitted. |
36 */ | 39 */ |
37 get: function(key, defaultValue) { | 40 get: function(key, defaultValue) { |
38 checkKeyIsValid(key); | 41 checkKeyIsValid(key); |
39 if (this.hasKey(key)) { | 42 if (this.hasKey(key)) { |
(...skipping 26 matching lines...) Expand all Loading... |
66 | 69 |
67 hasChanges: function() { | 70 hasChanges: function() { |
68 return Object.keys(this.changes_).length > 0; | 71 return Object.keys(this.changes_).length > 0; |
69 }, | 72 }, |
70 | 73 |
71 /** | 74 /** |
72 * Applies |changes| to context. Returns Array of changed keys' names. | 75 * Applies |changes| to context. Returns Array of changed keys' names. |
73 */ | 76 */ |
74 applyChanges: function(changes) { | 77 applyChanges: function(changes) { |
75 require(!this.hasChanges(), 'Context has changes.'); | 78 require(!this.hasChanges(), 'Context has changes.'); |
76 Object.keys(changes).forEach(function(key) { | 79 var oldValues = {}; |
| 80 for (var key in changes) { |
77 checkKeyIsValid(key); | 81 checkKeyIsValid(key); |
78 checkValueIsValid(changes[key]); | 82 checkValueIsValid(changes[key]); |
| 83 oldValues[key] = this.storage_[key]; |
79 this.storage_[key] = changes[key]; | 84 this.storage_[key] = changes[key]; |
80 }, this); | 85 } |
| 86 var observers = this.cloneObservers_(); |
| 87 for (var key in changes) { |
| 88 if (observers.hasOwnProperty(key)) { |
| 89 var keyObservers = observers[key]; |
| 90 for (var observerIndex in keyObservers) |
| 91 keyObservers[observerIndex](changes[key], oldValues[key], key); |
| 92 } |
| 93 } |
81 return Object.keys(changes); | 94 return Object.keys(changes); |
82 }, | 95 }, |
83 | 96 |
84 /** | 97 /** |
85 * Returns changes made on context since previous call. | 98 * Returns changes made on context since previous call. |
86 */ | 99 */ |
87 getChangesAndReset: function() { | 100 getChangesAndReset: function() { |
88 var result = this.changes_; | 101 var result = this.changes_; |
89 this.changes_ = {}; | 102 this.changes_ = {}; |
90 return result; | 103 return result; |
| 104 }, |
| 105 |
| 106 addObserver: function(key, observer) { |
| 107 if (!this.observers_.hasOwnProperty(key)) |
| 108 this.observers_[key] = []; |
| 109 if (this.observers_[key].indexOf(observer) !== -1) { |
| 110 console.warn('Observer already registered.'); |
| 111 return; |
| 112 } |
| 113 this.observers_[key].push(observer); |
| 114 }, |
| 115 |
| 116 removeObserver: function(observer) { |
| 117 for (var key in this.observers_) { |
| 118 var observerIndex = this.observers_[key].indexOf(observer); |
| 119 if (observerIndex != -1) |
| 120 this.observers_[key].splice(observerIndex, 1); |
| 121 } |
| 122 }, |
| 123 |
| 124 /** |
| 125 * Creates deep copy of observers lists. |
| 126 * @private |
| 127 */ |
| 128 cloneObservers_: function() { |
| 129 var result = {}; |
| 130 for (var key in this.observers_) |
| 131 result[key] = this.observers_[key].slice(); |
| 132 return result; |
91 } | 133 } |
92 }; | 134 }; |
93 | 135 |
94 return { | 136 return { |
95 ScreenContext: ScreenContext | 137 ScreenContext: ScreenContext |
96 }; | 138 }; |
97 }); | 139 }); |
OLD | NEW |