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

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

Issue 1357183002: MD-Settings: convert cr-settings-prefs to a singleton model (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: closure, typo Created 5 years, 3 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 * 'cr-settings-prefs' models Chrome settings and preferences, listening for 7 * 'cr-settings-prefs' exposes a sinlgeton model of Chrome settings and
8 * changes to Chrome prefs whitelisted in chrome.settingsPrivate. 8 * preferences, which listens to changes to Chrome prefs whitelisted in
9 * When changing prefs in this element's 'prefs' property via the UI, this 9 * chrome.settingsPrivate. When changing prefs in this element's 'prefs'
10 * element tries to set those preferences in Chrome. Whether or not the calls to 10 * property via the UI, the model tries to set those preferences in Chrome.
11 * settingsPrivate.setPref succeed, 'prefs' is eventually consistent with the 11 * Whether or not the calls to settingsPrivate.setPref succeed, 'prefs'
12 * Chrome pref store. 12 * is eventually consistent with the Chrome pref store.
13 * 13 *
14 * Example: 14 * Example:
15 * 15 *
16 * <cr-settings-prefs prefs="{{prefs}}"></cr-settings-prefs> 16 * <cr-settings-prefs prefs="{{prefs}}"></cr-settings-prefs>
17 * <cr-settings-a11y-page prefs="{{prefs}}"></cr-settings-a11y-page> 17 * <cr-settings-a11y-page prefs="{{prefs}}"></cr-settings-a11y-page>
18 * 18 *
19 * @group Chrome Settings Elements 19 * @group Chrome Settings Elements
20 * @element cr-settings-prefs 20 * @element cr-settings-prefs
21 */ 21 */
22 22
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 properties: { 129 properties: {
130 /** 130 /**
131 * Object containing all preferences, for use by Polymer controls. 131 * Object containing all preferences, for use by Polymer controls.
132 */ 132 */
133 prefs: { 133 prefs: {
134 type: Object, 134 type: Object,
135 notify: true, 135 notify: true,
136 }, 136 },
137 137
138 /** 138 /**
139 * Shared private state.
140 * @type {!Element}
141 */
142 prefsPrivate_: {
143 type: Object,
144 value: document.createElement('cr-settings-prefs-private'),
145 },
146 },
147
148 observers: [
149 'prefsChanged_(prefs.*)',
150 ],
151
152 /** @override */
153 ready: function() {
154 this.startListening_();
155 this.prefsPrivate_.initialize();
156 },
157
158 /**
159 * Binds this.prefs to the cr-settings-prefs-private's shared prefs once
160 * preferences are initialized.
161 * @private
162 */
163 startListening_: function() {
164 CrSettingsPrefs.initialized.then(
165 // Squelch to prevent prefsChanged_ from notifying prefsPrivate_.
166 this.squelching_.bind(this, function() {
167 this.prefs = this.prefsPrivate_.prefs;
168 // Adding multiple listeners would create excessive duplicate work.
169 assert(!this.listening_);
170 this.listening_ = true;
171 this.listen(
172 this.prefsPrivate_, 'prefs-changed', 'prefsPrivateChanged_');
173 }));
174 },
175
176 /**
177 * Stops listening for changes to cr-settings-prefs-private's shared prefs.
178 * @private
179 */
180 stopListening_: function() {
181 if (this.listening_) {
182 this.unlisten(
183 this.prefsPrivate_, 'prefs-changed', 'prefsPrivateChanged_');
184 this.listening_ = false;
185 }
186 },
187
188 /**
189 * Handles changes reported by prefsPrivate_.
190 * @private
191 */
192 prefsPrivateChanged_: function(e) {
193 // Squelch because we've defeated Polymer's internal dirty-checking.
194 this.squelching_(function() {
195 // Forward notification to host.
196 this.fire(e.type, e.detail, {bubbles: false});
197 });
198 },
199
200 /**
201 * Forwards changes to this.prefs to cr-settings-prefs-private.
202 * @private
203 */
204 prefsChanged_: function(info) {
205 // Squelch to avoid informing prefsPrivate_ of changes that came from it
206 // and re-processing changes made in other instances of this element.
207 if (!this.squelch_)
208 this.prefsPrivate_.fire('prefs-changed', info, {bubbles: false});
209 },
210
211 /**
212 * Sets a "squelch" switch before calling the function, so functions can
213 * return early when the switch is active.
214 * @param {!function()} fn
215 * @private
216 */
217 squelching_: function(fn) {
218 this.squelch_ = true;
219 fn.call(this);
220 // We can unset squelch_ now because change notifications are synchronous.
221 this.squelch_ = false;
222 },
223
224 /**
225 * Uninitializes this element to remove it from tests. Also resets
226 * cr-settings-prefs-private, allowing newly created elements to
227 * re-initialize it.
228 */
229 resetForTesting: function() {
230 this.stopListening_();
231 this.prefsPrivate_.resetForTesting();
232 },
233 });
234
235 /**
236 * Privately used element that contains, listens to and updates the shared
237 * prefs state.
238 */
239 Polymer({
240 is: 'cr-settings-prefs-private',
241
242 properties: {
243 /**
244 * Object containing all preferences, for use by Polymer controls.
245 * @type {(Object|undefined)}
246 */
247 prefs: {
248 type: Object,
249 notify: true,
250 },
251
252 /**
139 * Map of pref keys to values representing the state of the Chrome 253 * Map of pref keys to values representing the state of the Chrome
140 * pref store as of the last update from the API. 254 * pref store as of the last update from the API.
141 * @type {Object<*>} 255 * @type {Object<*>}
142 * @private 256 * @private
143 */ 257 */
144 lastPrefValues_: { 258 lastPrefValues_: {
145 type: Object, 259 type: Object,
146 value: function() { return {}; }, 260 value: function() { return {}; },
147 }, 261 },
148 }, 262 },
149 263
150 observers: [ 264 // Listen for the manually fired prefs-changed event.
151 'prefsChanged_(prefs.*)', 265 listeners: {
152 ], 266 'prefs-changed': 'prefsChanged_',
267 },
153 268
154 settingsApi_: chrome.settingsPrivate, 269 settingsApi_: chrome.settingsPrivate,
155 270
156 /** @override */ 271 initialize: function() {
157 ready: function() { 272 // Only initialize once (or after resetForTesting() is called).
273 if (this.initialized_)
274 return;
275 this.initialized_ = true;
276
158 // Set window.mockApi to pass a custom settings API, i.e. for tests. 277 // Set window.mockApi to pass a custom settings API, i.e. for tests.
159 // TODO(michaelpg): don't use a global. 278 // TODO(michaelpg): don't use a global.
160 if (window.mockApi) 279 if (window.mockApi)
161 this.settingsApi_ = window.mockApi; 280 this.settingsApi_ = window.mockApi;
162 CrSettingsPrefs.isInitialized = false;
163 281
164 this.settingsApi_.onPrefsChanged.addListener( 282 this.settingsApi_.onPrefsChanged.addListener(
165 this.onSettingsPrivatePrefsChanged_.bind(this)); 283 this.onSettingsPrivatePrefsChanged_.bind(this));
166 this.settingsApi_.getAllPrefs( 284 this.settingsApi_.getAllPrefs(
167 this.onSettingsPrivatePrefsFetched_.bind(this)); 285 this.onSettingsPrivatePrefsFetched_.bind(this));
168 }, 286 },
169 287
170 /** 288 /**
171 * Polymer callback for changes to this.prefs. 289 * Polymer callback for changes to this.prefs.
172 * @param {!{path: string, value: *}} change 290 * @param {!CustomEvent} e
291 * @param {!{path: string}} change
173 * @private 292 * @private
174 */ 293 */
175 prefsChanged_: function(change) { 294 prefsChanged_: function(e, change) {
176 if (!CrSettingsPrefs.isInitialized) 295 if (!CrSettingsPrefs.isInitialized)
177 return; 296 return;
178 297
179 var key = this.getPrefKeyFromPath_(change.path); 298 var key = this.getPrefKeyFromPath_(change.path);
180 var prefStoreValue = this.lastPrefValues_[key]; 299 var prefStoreValue = this.lastPrefValues_[key];
181 300
182 var prefObj = /** @type {chrome.settingsPrivate.PrefObject} */( 301 var prefObj = /** @type {chrome.settingsPrivate.PrefObject} */(
183 this.get(key, this.prefs)); 302 this.get(key, this.prefs));
184 303
185 // If settingsPrivate already has this value, do nothing. (Otherwise, 304 // If settingsPrivate already has this value, do nothing. (Otherwise,
(...skipping 20 matching lines...) Expand all
206 this.updatePrefs_(prefs); 325 this.updatePrefs_(prefs);
207 }, 326 },
208 327
209 /** 328 /**
210 * Called when prefs are fetched from settingsPrivate. 329 * Called when prefs are fetched from settingsPrivate.
211 * @param {!Array<!chrome.settingsPrivate.PrefObject>} prefs 330 * @param {!Array<!chrome.settingsPrivate.PrefObject>} prefs
212 * @private 331 * @private
213 */ 332 */
214 onSettingsPrivatePrefsFetched_: function(prefs) { 333 onSettingsPrivatePrefsFetched_: function(prefs) {
215 this.updatePrefs_(prefs); 334 this.updatePrefs_(prefs);
216 335 // Prefs are now initialized.
217 CrSettingsPrefs.isInitialized = true; 336 CrSettingsPrefs.setInitialized();
218 document.dispatchEvent(new Event(CrSettingsPrefs.INITIALIZED));
219 }, 337 },
220 338
221 /** 339 /**
222 * Checks the result of calling settingsPrivate.setPref. 340 * Checks the result of calling settingsPrivate.setPref.
223 * @param {string} key The key used in the call to setPref. 341 * @param {string} key The key used in the call to setPref.
224 * @param {boolean} success True if setting the pref succeeded. 342 * @param {boolean} success True if setting the pref succeeded.
225 * @private 343 * @private
226 */ 344 */
227 setPrefCallback_: function(key, success) { 345 setPrefCallback_: function(key, success) {
228 if (success) 346 if (success)
(...skipping 12 matching lines...) Expand all
241 * @private 359 * @private
242 */ 360 */
243 updatePrefs_: function(newPrefs) { 361 updatePrefs_: function(newPrefs) {
244 // Use the existing prefs object or create it. 362 // Use the existing prefs object or create it.
245 var prefs = this.prefs || {}; 363 var prefs = this.prefs || {};
246 newPrefs.forEach(function(newPrefObj) { 364 newPrefs.forEach(function(newPrefObj) {
247 // Use the PrefObject from settingsPrivate to create a copy in 365 // Use the PrefObject from settingsPrivate to create a copy in
248 // lastPrefValues_ at the pref's key. 366 // lastPrefValues_ at the pref's key.
249 this.lastPrefValues_[newPrefObj.key] = deepCopy(newPrefObj.value); 367 this.lastPrefValues_[newPrefObj.key] = deepCopy(newPrefObj.value);
250 368
251 // Add the pref to |prefs|. 369 if (!deepEqual(this.get(newPrefObj.key, prefs), newPrefObj)) {
michaelpg 2015/09/20 23:44:43 silly typo, thanks Closure! this doesn't affect co
252 cr.exportPath(newPrefObj.key, newPrefObj, prefs); 370 // Add the pref to |prefs|.
253 // If this.prefs already exists, notify listeners of the change. 371 cr.exportPath(newPrefObj.key, newPrefObj, prefs);
254 if (prefs == this.prefs) 372 // If this.prefs already exists, notify listeners of the change.
255 this.notifyPath('prefs.' + newPrefObj.key, newPrefObj); 373 if (prefs == this.prefs)
374 this.notifyPath('prefs.' + newPrefObj.key, newPrefObj);
375 }
256 }, this); 376 }, this);
257 if (!this.prefs) 377 if (!this.prefs)
258 this.prefs = prefs; 378 this.prefs = prefs;
259 }, 379 },
260 380
261 /** 381 /**
262 * Given a 'property-changed' path, returns the key of the preference the 382 * Given a 'property-changed' path, returns the key of the preference the
263 * path refers to. E.g., if the path of the changed property is 383 * path refers to. E.g., if the path of the changed property is
264 * 'prefs.search.suggest_enabled.value', the key of the pref that changed is 384 * 'prefs.search.suggest_enabled.value', the key of the pref that changed is
265 * 'search.suggest_enabled'. 385 * 'search.suggest_enabled'.
266 * @param {string} path 386 * @param {string} path
267 * @return {string} 387 * @return {string}
268 * @private 388 * @private
269 */ 389 */
270 getPrefKeyFromPath_: function(path) { 390 getPrefKeyFromPath_: function(path) {
271 // Skip the first token, which refers to the member variable (this.prefs). 391 // Skip the first token, which refers to the member variable (this.prefs).
272 var parts = path.split('.'); 392 var parts = path.split('.');
273 assert(parts.shift() == 'prefs'); 393 assert(parts.shift() == 'prefs');
274 394
275 for (let i = 1; i <= parts.length; i++) { 395 for (let i = 1; i <= parts.length; i++) {
276 let key = parts.slice(0, i).join('.'); 396 let key = parts.slice(0, i).join('.');
277 // The lastPrefValues_ keys match the pref keys. 397 // The lastPrefValues_ keys match the pref keys.
278 if (this.lastPrefValues_.hasOwnProperty(key)) 398 if (this.lastPrefValues_.hasOwnProperty(key))
279 return key; 399 return key;
280 } 400 }
281 return ''; 401 return '';
282 }, 402 },
403
404 /**
405 * Resets the element so it can be re-initialized with a new prefs state.
406 */
407 resetForTesting: function() {
408 this.prefs = undefined;
409 this.lastPrefValues_ = {};
410 this.initialized_ = false;
411 },
283 }); 412 });
284 })(); 413 })();
OLDNEW
« no previous file with comments | « chrome/browser/resources/settings/pref_tracker/pref_tracker.js ('k') | chrome/browser/resources/settings/prefs/prefs_types.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698