Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(567)

Side by Side Diff: chrome/browser/resources/settings/prefs/prefs.js

Issue 2946563002: Run clang-format on .js files in c/b/r/settings (Closed)
Patch Set: dschuyler@ review Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* Copyright 2015 The Chromium Authors. All rights reserved. 1 /* Copyright 2015 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 6 * @fileoverview
7 * 'settings-prefs' exposes a singleton model of Chrome settings and 7 * 'settings-prefs' exposes a singleton model of Chrome settings and
8 * preferences, which listens to changes to Chrome prefs whitelisted in 8 * preferences, which listens to changes to Chrome prefs whitelisted in
9 * chrome.settingsPrivate. When changing prefs in this element's 'prefs' 9 * chrome.settingsPrivate. When changing prefs in this element's 'prefs'
10 * property via the UI, the singleton model tries to set those preferences in 10 * property via the UI, the singleton model tries to set those preferences in
11 * Chrome. Whether or not the calls to settingsPrivate.setPref succeed, 'prefs' 11 * Chrome. Whether or not the calls to settingsPrivate.setPref succeed, 'prefs'
12 * is eventually consistent with the Chrome pref store. 12 * is eventually consistent with the Chrome pref store.
13 */ 13 */
14 14
15 (function() { 15 (function() {
16 'use strict'; 16 'use strict';
17 17
18 /** 18 /**
19 * Checks whether two values are recursively equal. Only compares serializable 19 * Checks whether two values are recursively equal. Only compares serializable
20 * data (primitives, serializable arrays and serializable objects). 20 * data (primitives, serializable arrays and serializable objects).
21 * @param {*} val1 Value to compare. 21 * @param {*} val1 Value to compare.
22 * @param {*} val2 Value to compare with val1. 22 * @param {*} val2 Value to compare with val1.
23 * @return {boolean} True if the values are recursively equal. 23 * @return {boolean} True if the values are recursively equal.
24 */ 24 */
25 function deepEqual(val1, val2) { 25 function deepEqual(val1, val2) {
26 if (val1 === val2) 26 if (val1 === val2)
27 return true; 27 return true;
28 28
29 if (Array.isArray(val1) || Array.isArray(val2)) { 29 if (Array.isArray(val1) || Array.isArray(val2)) {
30 if (!Array.isArray(val1) || !Array.isArray(val2)) 30 if (!Array.isArray(val1) || !Array.isArray(val2))
31 return false; 31 return false;
32 return arraysEqual(/** @type {!Array} */(val1), 32 return arraysEqual(
33 /** @type {!Array} */(val2)); 33 /** @type {!Array} */ (val1),
34 } 34 /** @type {!Array} */ (val2));
35 35 }
36 if (val1 instanceof Object && val2 instanceof Object) 36
37 return objectsEqual(val1, val2); 37 if (val1 instanceof Object && val2 instanceof Object)
38 38 return objectsEqual(val1, val2);
39
40 return false;
41 }
42
43 /**
44 * @param {!Array} arr1
45 * @param {!Array} arr2
46 * @return {boolean} True if the arrays are recursively equal.
47 */
48 function arraysEqual(arr1, arr2) {
49 if (arr1.length != arr2.length)
39 return false; 50 return false;
51
52 for (var i = 0; i < arr1.length; i++) {
53 if (!deepEqual(arr1[i], arr2[i]))
54 return false;
40 } 55 }
41 56
42 /** 57 return true;
43 * @param {!Array} arr1 58 }
44 * @param {!Array} arr2 59
45 * @return {boolean} True if the arrays are recursively equal. 60 /**
46 */ 61 * @param {!Object} obj1
47 function arraysEqual(arr1, arr2) { 62 * @param {!Object} obj2
48 if (arr1.length != arr2.length) 63 * @return {boolean} True if the objects are recursively equal.
64 */
65 function objectsEqual(obj1, obj2) {
66 var keys1 = Object.keys(obj1);
67 var keys2 = Object.keys(obj2);
68 if (keys1.length != keys2.length)
69 return false;
70
71 for (var i = 0; i < keys1.length; i++) {
72 var key = keys1[i];
73 if (!deepEqual(obj1[key], obj2[key]))
49 return false; 74 return false;
50
51 for (var i = 0; i < arr1.length; i++) {
52 if (!deepEqual(arr1[i], arr2[i]))
53 return false;
54 }
55
56 return true;
57 } 75 }
58 76
59 /** 77 return true;
60 * @param {!Object} obj1 78 }
61 * @param {!Object} obj2 79
62 * @return {boolean} True if the objects are recursively equal. 80 /**
63 */ 81 * Returns a recursive copy of the value.
64 function objectsEqual(obj1, obj2) { 82 * @param {*} val Value to copy. Should be a primitive or only contain
65 var keys1 = Object.keys(obj1); 83 * serializable data (primitives, serializable arrays and
66 var keys2 = Object.keys(obj2); 84 * serializable objects).
67 if (keys1.length != keys2.length) 85 * @return {*} A deep copy of the value.
68 return false; 86 */
69 87 function deepCopy(val) {
70 for (var i = 0; i < keys1.length; i++) { 88 if (!(val instanceof Object))
71 var key = keys1[i]; 89 return val;
72 if (!deepEqual(obj1[key], obj2[key])) 90 return Array.isArray(val) ? deepCopyArray(/** @type {!Array} */ (val)) :
73 return false; 91 deepCopyObject(val);
74 } 92 }
75 93
76 return true; 94 /**
95 * @param {!Array} arr
96 * @return {!Array} Deep copy of the array.
97 */
98 function deepCopyArray(arr) {
99 var copy = [];
100 for (var i = 0; i < arr.length; i++)
101 copy.push(deepCopy(arr[i]));
102 return copy;
103 }
104
105 /**
106 * @param {!Object} obj
107 * @return {!Object} Deep copy of the object.
108 */
109 function deepCopyObject(obj) {
110 var copy = {};
111 var keys = Object.keys(obj);
112 for (var i = 0; i < keys.length; i++) {
113 var key = keys[i];
114 copy[key] = deepCopy(obj[key]);
77 } 115 }
78 116 return copy;
79 /** 117 }
80 * Returns a recursive copy of the value. 118
81 * @param {*} val Value to copy. Should be a primitive or only contain 119 Polymer({
82 * serializable data (primitives, serializable arrays and 120 is: 'settings-prefs',
83 * serializable objects). 121
84 * @return {*} A deep copy of the value. 122 properties: {
85 */ 123 /**
86 function deepCopy(val) { 124 * Object containing all preferences, for use by Polymer controls.
87 if (!(val instanceof Object)) 125 * @type {Object|undefined}
88 return val; 126 */
89 return Array.isArray(val) ? deepCopyArray(/** @type {!Array} */(val)) : 127 prefs: {
90 deepCopyObject(val); 128 type: Object,
91 } 129 notify: true,
92 130 },
93 /** 131
94 * @param {!Array} arr 132 /**
95 * @return {!Array} Deep copy of the array. 133 * Map of pref keys to values representing the state of the Chrome
96 */ 134 * pref store as of the last update from the API.
97 function deepCopyArray(arr) { 135 * @type {Object<*>}
98 var copy = []; 136 * @private
99 for (var i = 0; i < arr.length; i++) 137 */
100 copy.push(deepCopy(arr[i])); 138 lastPrefValues_: {
101 return copy; 139 type: Object,
102 } 140 value: function() {
103 141 return {};
104 /**
105 * @param {!Object} obj
106 * @return {!Object} Deep copy of the object.
107 */
108 function deepCopyObject(obj) {
109 var copy = {};
110 var keys = Object.keys(obj);
111 for (var i = 0; i < keys.length; i++) {
112 var key = keys[i];
113 copy[key] = deepCopy(obj[key]);
114 }
115 return copy;
116 }
117
118 Polymer({
119 is: 'settings-prefs',
120
121 properties: {
122 /**
123 * Object containing all preferences, for use by Polymer controls.
124 * @type {Object|undefined}
125 */
126 prefs: {
127 type: Object,
128 notify: true,
129 },
130
131 /**
132 * Map of pref keys to values representing the state of the Chrome
133 * pref store as of the last update from the API.
134 * @type {Object<*>}
135 * @private
136 */
137 lastPrefValues_: {
138 type: Object,
139 value: function() { return {}; },
140 }, 142 },
141 }, 143 },
142 144 },
143 observers: [ 145
144 'prefsChanged_(prefs.*)', 146 observers: [
145 ], 147 'prefsChanged_(prefs.*)',
146 148 ],
147 /** @type {SettingsPrivate} */ 149
148 settingsApi_: /** @type {SettingsPrivate} */(chrome.settingsPrivate), 150 /** @type {SettingsPrivate} */
149 151 settingsApi_: /** @type {SettingsPrivate} */ (chrome.settingsPrivate),
150 /** @override */ 152
151 created: function() { 153 /** @override */
152 if (!CrSettingsPrefs.deferInitialization) 154 created: function() {
153 this.initialize(); 155 if (!CrSettingsPrefs.deferInitialization)
154 }, 156 this.initialize();
155 157 },
156 /** @override */ 158
157 detached: function() { 159 /** @override */
158 CrSettingsPrefs.resetForTesting(); 160 detached: function() {
159 }, 161 CrSettingsPrefs.resetForTesting();
160 162 },
161 /** 163
162 * @param {SettingsPrivate=} opt_settingsApi SettingsPrivate implementation 164 /**
163 * to use (chrome.settingsPrivate by default). 165 * @param {SettingsPrivate=} opt_settingsApi SettingsPrivate implementation
164 */ 166 * to use (chrome.settingsPrivate by default).
165 initialize: function(opt_settingsApi) { 167 */
166 // Only initialize once (or after resetForTesting() is called). 168 initialize: function(opt_settingsApi) {
167 if (this.initialized_) 169 // Only initialize once (or after resetForTesting() is called).
168 return; 170 if (this.initialized_)
169 this.initialized_ = true; 171 return;
170 172 this.initialized_ = true;
171 if (opt_settingsApi) 173
172 this.settingsApi_ = opt_settingsApi; 174 if (opt_settingsApi)
173 175 this.settingsApi_ = opt_settingsApi;
174 /** @private {function(!Array<!chrome.settingsPrivate.PrefObject>)} */ 176
175 this.boundPrefsChanged_ = this.onSettingsPrivatePrefsChanged_.bind(this); 177 /** @private {function(!Array<!chrome.settingsPrivate.PrefObject>)} */
176 this.settingsApi_.onPrefsChanged.addListener(this.boundPrefsChanged_); 178 this.boundPrefsChanged_ = this.onSettingsPrivatePrefsChanged_.bind(this);
177 this.settingsApi_.getAllPrefs( 179 this.settingsApi_.onPrefsChanged.addListener(this.boundPrefsChanged_);
178 this.onSettingsPrivatePrefsFetched_.bind(this)); 180 this.settingsApi_.getAllPrefs(
179 }, 181 this.onSettingsPrivatePrefsFetched_.bind(this));
180 182 },
181 /** 183
182 * @param {!{path: string}} e 184 /**
183 * @private 185 * @param {!{path: string}} e
184 */ 186 * @private
185 prefsChanged_: function(e) { 187 */
186 // |prefs| can be directly set or unset in tests. 188 prefsChanged_: function(e) {
187 if (!CrSettingsPrefs.isInitialized || e.path == 'prefs') 189 // |prefs| can be directly set or unset in tests.
188 return; 190 if (!CrSettingsPrefs.isInitialized || e.path == 'prefs')
189 191 return;
190 var key = this.getPrefKeyFromPath_(e.path); 192
191 var prefStoreValue = this.lastPrefValues_[key]; 193 var key = this.getPrefKeyFromPath_(e.path);
192 194 var prefStoreValue = this.lastPrefValues_[key];
193 var prefObj = /** @type {chrome.settingsPrivate.PrefObject} */( 195
194 this.get(key, this.prefs)); 196 var prefObj = /** @type {chrome.settingsPrivate.PrefObject} */ (
195 197 this.get(key, this.prefs));
196 // If settingsPrivate already has this value, ignore it. (Otherwise, 198
197 // a change event from settingsPrivate could make us call 199 // If settingsPrivate already has this value, ignore it. (Otherwise,
198 // settingsPrivate.setPref and potentially trigger an IPC loop.) 200 // a change event from settingsPrivate could make us call
199 if (!deepEqual(prefStoreValue, prefObj.value)) { 201 // settingsPrivate.setPref and potentially trigger an IPC loop.)
200 this.settingsApi_.setPref( 202 if (!deepEqual(prefStoreValue, prefObj.value)) {
201 key, 203 this.settingsApi_.setPref(
202 prefObj.value, 204 key, prefObj.value,
203 /* pageId */ '', 205 /* pageId */ '',
204 /* callback */ this.setPrefCallback_.bind(this, key)); 206 /* callback */ this.setPrefCallback_.bind(this, key));
207 }
208 },
209
210 /**
211 * Called when prefs in the underlying Chrome pref store are changed.
212 * @param {!Array<!chrome.settingsPrivate.PrefObject>} prefs
213 * The prefs that changed.
214 * @private
215 */
216 onSettingsPrivatePrefsChanged_: function(prefs) {
217 if (CrSettingsPrefs.isInitialized)
218 this.updatePrefs_(prefs);
219 },
220
221 /**
222 * Called when prefs are fetched from settingsPrivate.
223 * @param {!Array<!chrome.settingsPrivate.PrefObject>} prefs
224 * @private
225 */
226 onSettingsPrivatePrefsFetched_: function(prefs) {
227 this.updatePrefs_(prefs);
228 CrSettingsPrefs.setInitialized();
229 },
230
231 /**
232 * Checks the result of calling settingsPrivate.setPref.
233 * @param {string} key The key used in the call to setPref.
234 * @param {boolean} success True if setting the pref succeeded.
235 * @private
236 */
237 setPrefCallback_: function(key, success) {
238 if (!success)
239 this.refresh(key);
240 },
241
242 /**
243 * Get the current pref value from chrome.settingsPrivate to ensure the UI
244 * stays up to date.
245 * @param {string} key
246 */
247 refresh: function(key) {
248 this.settingsApi_.getPref(key, function(pref) {
249 this.updatePrefs_([pref]);
250 }.bind(this));
251 },
252
253 /**
254 * Updates the prefs model with the given prefs.
255 * @param {!Array<!chrome.settingsPrivate.PrefObject>} newPrefs
256 * @private
257 */
258 updatePrefs_: function(newPrefs) {
259 // Use the existing prefs object or create it.
260 var prefs = this.prefs || {};
261 newPrefs.forEach(function(newPrefObj) {
262 // Use the PrefObject from settingsPrivate to create a copy in
263 // lastPrefValues_ at the pref's key.
264 this.lastPrefValues_[newPrefObj.key] = deepCopy(newPrefObj.value);
265
266 if (!deepEqual(this.get(newPrefObj.key, prefs), newPrefObj)) {
267 // Add the pref to |prefs|.
268 cr.exportPath(newPrefObj.key, newPrefObj, prefs);
269 // If this.prefs already exists, notify listeners of the change.
270 if (prefs == this.prefs)
271 this.notifyPath('prefs.' + newPrefObj.key, newPrefObj);
205 } 272 }
206 }, 273 }, this);
207 274 if (!this.prefs)
208 /** 275 this.prefs = prefs;
209 * Called when prefs in the underlying Chrome pref store are changed. 276 },
210 * @param {!Array<!chrome.settingsPrivate.PrefObject>} prefs 277
211 * The prefs that changed. 278 /**
212 * @private 279 * Given a 'property-changed' path, returns the key of the preference the
213 */ 280 * path refers to. E.g., if the path of the changed property is
214 onSettingsPrivatePrefsChanged_: function(prefs) { 281 * 'prefs.search.suggest_enabled.value', the key of the pref that changed is
215 if (CrSettingsPrefs.isInitialized) 282 * 'search.suggest_enabled'.
216 this.updatePrefs_(prefs); 283 * @param {string} path
217 }, 284 * @return {string}
218 285 * @private
219 /** 286 */
220 * Called when prefs are fetched from settingsPrivate. 287 getPrefKeyFromPath_: function(path) {
221 * @param {!Array<!chrome.settingsPrivate.PrefObject>} prefs 288 // Skip the first token, which refers to the member variable (this.prefs).
222 * @private 289 var parts = path.split('.');
223 */ 290 assert(parts.shift() == 'prefs', 'Path doesn\'t begin with \'prefs\'');
224 onSettingsPrivatePrefsFetched_: function(prefs) { 291
225 this.updatePrefs_(prefs); 292 for (var i = 1; i <= parts.length; i++) {
226 CrSettingsPrefs.setInitialized(); 293 var key = parts.slice(0, i).join('.');
227 }, 294 // The lastPrefValues_ keys match the pref keys.
228 295 if (this.lastPrefValues_.hasOwnProperty(key))
229 /** 296 return key;
230 * Checks the result of calling settingsPrivate.setPref. 297 }
231 * @param {string} key The key used in the call to setPref. 298 return '';
232 * @param {boolean} success True if setting the pref succeeded. 299 },
233 * @private 300
234 */ 301 /**
235 setPrefCallback_: function(key, success) { 302 * Resets the element so it can be re-initialized with a new prefs state.
236 if (!success) 303 */
237 this.refresh(key); 304 resetForTesting: function() {
238 }, 305 if (!this.initialized_)
239 306 return;
240 /** 307 this.prefs = undefined;
241 * Get the current pref value from chrome.settingsPrivate to ensure the UI 308 this.lastPrefValues_ = {};
242 * stays up to date. 309 this.initialized_ = false;
243 * @param {string} key 310 // Remove the listener added in initialize().
244 */ 311 this.settingsApi_.onPrefsChanged.removeListener(this.boundPrefsChanged_);
245 refresh: function(key) { 312 this.settingsApi_ =
246 this.settingsApi_.getPref(key, function(pref) { 313 /** @type {SettingsPrivate} */ (chrome.settingsPrivate);
247 this.updatePrefs_([pref]); 314 },
248 }.bind(this)); 315 });
249 },
250
251 /**
252 * Updates the prefs model with the given prefs.
253 * @param {!Array<!chrome.settingsPrivate.PrefObject>} newPrefs
254 * @private
255 */
256 updatePrefs_: function(newPrefs) {
257 // Use the existing prefs object or create it.
258 var prefs = this.prefs || {};
259 newPrefs.forEach(function(newPrefObj) {
260 // Use the PrefObject from settingsPrivate to create a copy in
261 // lastPrefValues_ at the pref's key.
262 this.lastPrefValues_[newPrefObj.key] = deepCopy(newPrefObj.value);
263
264 if (!deepEqual(this.get(newPrefObj.key, prefs), newPrefObj)) {
265 // Add the pref to |prefs|.
266 cr.exportPath(newPrefObj.key, newPrefObj, prefs);
267 // If this.prefs already exists, notify listeners of the change.
268 if (prefs == this.prefs)
269 this.notifyPath('prefs.' + newPrefObj.key, newPrefObj);
270 }
271 }, this);
272 if (!this.prefs)
273 this.prefs = prefs;
274 },
275
276 /**
277 * Given a 'property-changed' path, returns the key of the preference the
278 * path refers to. E.g., if the path of the changed property is
279 * 'prefs.search.suggest_enabled.value', the key of the pref that changed is
280 * 'search.suggest_enabled'.
281 * @param {string} path
282 * @return {string}
283 * @private
284 */
285 getPrefKeyFromPath_: function(path) {
286 // Skip the first token, which refers to the member variable (this.prefs).
287 var parts = path.split('.');
288 assert(parts.shift() == 'prefs', "Path doesn't begin with 'prefs'");
289
290 for (var i = 1; i <= parts.length; i++) {
291 var key = parts.slice(0, i).join('.');
292 // The lastPrefValues_ keys match the pref keys.
293 if (this.lastPrefValues_.hasOwnProperty(key))
294 return key;
295 }
296 return '';
297 },
298
299 /**
300 * Resets the element so it can be re-initialized with a new prefs state.
301 */
302 resetForTesting: function() {
303 if (!this.initialized_)
304 return;
305 this.prefs = undefined;
306 this.lastPrefValues_ = {};
307 this.initialized_ = false;
308 // Remove the listener added in initialize().
309 this.settingsApi_.onPrefsChanged.removeListener(this.boundPrefsChanged_);
310 this.settingsApi_ =
311 /** @type {SettingsPrivate} */(chrome.settingsPrivate);
312 },
313 });
314 })(); 316 })();
OLDNEW
« no previous file with comments | « chrome/browser/resources/settings/prefs/pref_util.js ('k') | chrome/browser/resources/settings/prefs/prefs_behavior.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698