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

Unified 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: 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/settings/prefs/prefs.js
diff --git a/chrome/browser/resources/settings/prefs/prefs.js b/chrome/browser/resources/settings/prefs/prefs.js
index ddb38be8ee478326abb67fec7a1cc1ffb9c149f1..28cf704be18385f5f001f7078004e59cf0b0ba36 100644
--- a/chrome/browser/resources/settings/prefs/prefs.js
+++ b/chrome/browser/resources/settings/prefs/prefs.js
@@ -4,12 +4,12 @@
/**
* @fileoverview
- * 'cr-settings-prefs' models Chrome settings and preferences, listening for
- * changes to Chrome prefs whitelisted in chrome.settingsPrivate.
- * When changing prefs in this element's 'prefs' property via the UI, this
- * element tries to set those preferences in Chrome. Whether or not the calls to
- * settingsPrivate.setPref succeed, 'prefs' is eventually consistent with the
- * Chrome pref store.
+ * 'cr-settings-prefs' exposes a sinlgeton model of Chrome settings and
+ * preferences, which listens to changes to Chrome prefs whitelisted in
+ * chrome.settingsPrivate. When changing prefs in this element's 'prefs'
+ * property via the UI, the model tries to set those preferences in Chrome.
+ * Whether or not the calls to settingsPrivate.setPref succeed, 'prefs'
+ * is eventually consistent with the Chrome pref store.
*
* Example:
*
@@ -136,6 +136,120 @@
},
/**
+ * Shared private state.
+ * @type {!Element}
+ */
+ prefsPrivate_: {
+ type: Object,
+ value: document.createElement('cr-settings-prefs-private'),
+ },
+ },
+
+ observers: [
+ 'prefsChanged_(prefs.*)',
+ ],
+
+ /** @override */
+ ready: function() {
+ this.startListening_();
+ this.prefsPrivate_.initialize();
Dan Beam 2015/09/21 22:25:20 nit: reverse these if possible
michaelpg 2015/09/22 00:34:07 Done.
+ },
+
+ /**
+ * Binds this.prefs to the cr-settings-prefs-private's shared prefs once
+ * preferences are initialized.
+ * @private
+ */
+ startListening_: function() {
+ CrSettingsPrefs.initialized.then(
+ // Squelch to prevent prefsChanged_ from notifying prefsPrivate_.
+ this.squelching_.bind(this, function() {
+ this.prefs = this.prefsPrivate_.prefs;
+ // Adding multiple listeners would create excessive duplicate work.
+ assert(!this.listening_);
Dan Beam 2015/09/21 22:25:20 there seems to be a graceful fix for this: just un
michaelpg 2015/09/22 00:34:07 Done.
+ this.listening_ = true;
+ this.listen(
+ this.prefsPrivate_, 'prefs-changed', 'prefsPrivateChanged_');
+ }));
Dan Beam 2015/09/21 22:25:20 CrSettingsPrefs.initialized.then(function() { th
michaelpg 2015/09/22 00:34:06 Done.
+ },
+
+ /**
+ * Stops listening for changes to cr-settings-prefs-private's shared prefs.
+ * @private
+ */
+ stopListening_: function() {
+ if (this.listening_) {
Dan Beam 2015/09/21 22:25:20 is this if really necessary?
michaelpg 2015/09/22 00:34:07 Done.
+ this.unlisten(
+ this.prefsPrivate_, 'prefs-changed', 'prefsPrivateChanged_');
+ this.listening_ = false;
+ }
+ },
+
+ /**
+ * Handles changes reported by prefsPrivate_.
+ * @private
+ */
+ prefsPrivateChanged_: function(e) {
+ // Squelch because we've defeated Polymer's internal dirty-checking.
+ this.squelching_(function() {
+ // Forward notification to host.
+ this.fire(e.type, e.detail, {bubbles: false});
+ });
+ },
+
+ /**
+ * Forwards changes to this.prefs to cr-settings-prefs-private.
+ * @private
+ */
+ prefsChanged_: function(info) {
+ // Squelch to avoid informing prefsPrivate_ of changes that came from it
+ // and re-processing changes made in other instances of this element.
+ if (!this.squelch_)
+ this.prefsPrivate_.fire('prefs-changed', info, {bubbles: false});
+ },
+
+ /**
+ * Sets a "squelch" switch before calling the function, so functions can
+ * return early when the switch is active.
+ * @param {!function()} fn
+ * @private
+ */
+ squelching_: function(fn) {
Dan Beam 2015/09/21 22:25:20 runWhileIgnoringChanges_ IMO
michaelpg 2015/09/22 00:34:06 Done.
+ this.squelch_ = true;
Dan Beam 2015/09/21 22:25:20 this.ignoreChanges_ or this.ignorePrefChanges_
michaelpg 2015/09/22 00:34:07 Done.
+ fn.call(this);
+ // We can unset squelch_ now because change notifications are synchronous.
+ this.squelch_ = false;
Dan Beam 2015/09/21 22:25:20 instead of setting a flag, just stop listening dur
michaelpg 2015/09/22 00:34:07 I'm not sure how that would work... the interactio
Dan Beam 2015/09/22 06:12:31 any time I see "listen to events" followed by "but
+ },
+
+ /**
+ * Uninitializes this element to remove it from tests. Also resets
+ * cr-settings-prefs-private, allowing newly created elements to
+ * re-initialize it.
+ */
+ resetForTesting: function() {
+ this.stopListening_();
+ this.prefsPrivate_.resetForTesting();
+ },
+ });
+
+ /**
+ * Privately used element that contains, listens to and updates the shared
+ * prefs state.
+ */
+ Polymer({
+ is: 'cr-settings-prefs-private',
+
+ properties: {
+ /**
+ * Object containing all preferences, for use by Polymer controls.
+ * @type {(Object|undefined)}
+ */
+ prefs: {
+ type: Object,
+ notify: true,
+ },
+
+ /**
* Map of pref keys to values representing the state of the Chrome
* pref store as of the last update from the API.
* @type {Object<*>}
@@ -147,19 +261,23 @@
},
},
- observers: [
- 'prefsChanged_(prefs.*)',
- ],
+ // Listen for the manually fired prefs-changed event.
+ listeners: {
+ 'prefs-changed': 'prefsChanged_',
+ },
settingsApi_: chrome.settingsPrivate,
- /** @override */
- ready: function() {
+ initialize: function() {
+ // Only initialize once (or after resetForTesting() is called).
+ if (this.initialized_)
+ return;
+ this.initialized_ = true;
+
// Set window.mockApi to pass a custom settings API, i.e. for tests.
// TODO(michaelpg): don't use a global.
if (window.mockApi)
this.settingsApi_ = window.mockApi;
- CrSettingsPrefs.isInitialized = false;
this.settingsApi_.onPrefsChanged.addListener(
this.onSettingsPrivatePrefsChanged_.bind(this));
@@ -169,10 +287,11 @@
/**
* Polymer callback for changes to this.prefs.
- * @param {!{path: string, value: *}} change
+ * @param {!CustomEvent} e
+ * @param {!{path: string}} change
* @private
*/
- prefsChanged_: function(change) {
+ prefsChanged_: function(e, change) {
if (!CrSettingsPrefs.isInitialized)
return;
@@ -213,9 +332,8 @@
*/
onSettingsPrivatePrefsFetched_: function(prefs) {
this.updatePrefs_(prefs);
-
- CrSettingsPrefs.isInitialized = true;
- document.dispatchEvent(new Event(CrSettingsPrefs.INITIALIZED));
+ // Prefs are now initialized.
+ CrSettingsPrefs.setInitialized();
},
/**
@@ -248,11 +366,13 @@
// lastPrefValues_ at the pref's key.
this.lastPrefValues_[newPrefObj.key] = deepCopy(newPrefObj.value);
- // Add the pref to |prefs|.
- cr.exportPath(newPrefObj.key, newPrefObj, prefs);
- // If this.prefs already exists, notify listeners of the change.
- if (prefs == this.prefs)
- this.notifyPath('prefs.' + newPrefObj.key, newPrefObj);
+ if (!deepEqual(this.get(newPrefObj.key, prefs), newPrefObj)) {
+ // Add the pref to |prefs|.
+ cr.exportPath(newPrefObj.key, newPrefObj, prefs);
+ // If this.prefs already exists, notify listeners of the change.
+ if (prefs == this.prefs)
+ this.notifyPath('prefs.' + newPrefObj.key, newPrefObj);
+ }
}, this);
if (!this.prefs)
this.prefs = prefs;
@@ -280,5 +400,14 @@
}
return '';
},
+
+ /**
+ * Resets the element so it can be re-initialized with a new prefs state.
+ */
+ resetForTesting: function() {
+ this.prefs = undefined;
+ this.lastPrefValues_ = {};
+ this.initialized_ = false;
+ },
});
})();

Powered by Google App Engine
This is Rietveld 408576698