| 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..cec2f287aee06ff2ef7b018ee08ea94cf9d6ac4b 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,119 @@
|
| },
|
|
|
| /**
|
| + * 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();
|
| + },
|
| +
|
| + /**
|
| + * 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_);
|
| + this.listening_ = true;
|
| + this.listen(
|
| + this.prefsPrivate_, 'prefs-changed', 'prefsPrivateChanged_');
|
| + }));
|
| + },
|
| +
|
| + /**
|
| + * Stops listening for changes to cr-settings-prefs-private's shared prefs.
|
| + * @private
|
| + */
|
| + stopListening_: function() {
|
| + if (this.listening_) {
|
| + 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) {
|
| + this.squelch_ = true;
|
| + fn.call(this);
|
| + // We can unset squelch_ now because change notifications are synchronous.
|
| + this.squelch_ = false;
|
| + },
|
| +
|
| + /**
|
| + * 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.
|
| + */
|
| + 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 +260,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 +286,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 +331,8 @@
|
| */
|
| onSettingsPrivatePrefsFetched_: function(prefs) {
|
| this.updatePrefs_(prefs);
|
| -
|
| - CrSettingsPrefs.isInitialized = true;
|
| - document.dispatchEvent(new Event(CrSettingsPrefs.INITIALIZED));
|
| + // Prefs are now initialized.
|
| + CrSettingsPrefs.setInitialized();
|
| },
|
|
|
| /**
|
| @@ -248,11 +365,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 +399,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;
|
| + },
|
| });
|
| })();
|
|
|