PageRenderTime 35ms CodeModel.GetById 14ms app.highlight 16ms RepoModel.GetById 2ms app.codeStats 0ms

/services/sync/modules/engines/prefs.js

http://github.com/zpao/v8monkey
JavaScript | 285 lines | 197 code | 40 blank | 48 comment | 29 complexity | d71599c90905b3e9d2308a9635fbb11e MD5 | raw file
  1/* ***** BEGIN LICENSE BLOCK *****
  2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3 *
  4 * The contents of this file are subject to the Mozilla Public License Version
  5 * 1.1 (the "License"); you may not use this file except in compliance with
  6 * the License. You may obtain a copy of the License at
  7 * http://www.mozilla.org/MPL/
  8 *
  9 * Software distributed under the License is distributed on an "AS IS" basis,
 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 11 * for the specific language governing rights and limitations under the
 12 * License.
 13 *
 14 * The Original Code is Bookmarks Sync.
 15 *
 16 * The Initial Developer of the Original Code is Mozilla.
 17 * Portions created by the Initial Developer are Copyright (C) 2008
 18 * the Initial Developer. All Rights Reserved.
 19 *
 20 * Contributor(s):
 21 *  Anant Narayanan <anant@kix.in>
 22 *  Philipp von Weitershausen <philipp@weitershausen.de>
 23 *
 24 * Alternatively, the contents of this file may be used under the terms of
 25 * either the GNU General Public License Version 2 or later (the "GPL"), or
 26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 27 * in which case the provisions of the GPL or the LGPL are applicable instead
 28 * of those above. If you wish to allow use of your version of this file only
 29 * under the terms of either the GPL or the LGPL, and not to allow others to
 30 * use your version of this file under the terms of the MPL, indicate your
 31 * decision by deleting the provisions above and replace them with the notice
 32 * and other provisions required by the GPL or the LGPL. If you do not delete
 33 * the provisions above, a recipient may use your version of this file under
 34 * the terms of any one of the MPL, the GPL or the LGPL.
 35 *
 36 * ***** END LICENSE BLOCK ***** */
 37
 38const EXPORTED_SYMBOLS = ['PrefsEngine', 'PrefRec'];
 39
 40const Cc = Components.classes;
 41const Ci = Components.interfaces;
 42const Cu = Components.utils;
 43
 44const WEAVE_SYNC_PREFS = "services.sync.prefs.sync.";
 45
 46Cu.import("resource://services-sync/engines.js");
 47Cu.import("resource://services-sync/record.js");
 48Cu.import("resource://services-sync/util.js");
 49Cu.import("resource://services-sync/constants.js");
 50Cu.import("resource://services-sync/ext/Preferences.js");
 51Cu.import("resource://gre/modules/LightweightThemeManager.jsm");
 52
 53const PREFS_GUID = Utils.encodeBase64url(Services.appinfo.ID);
 54
 55function PrefRec(collection, id) {
 56  CryptoWrapper.call(this, collection, id);
 57}
 58PrefRec.prototype = {
 59  __proto__: CryptoWrapper.prototype,
 60  _logName: "Sync.Record.Pref",
 61};
 62
 63Utils.deferGetSet(PrefRec, "cleartext", ["value"]);
 64
 65
 66function PrefsEngine() {
 67  SyncEngine.call(this, "Prefs");
 68}
 69PrefsEngine.prototype = {
 70  __proto__: SyncEngine.prototype,
 71  _storeObj: PrefStore,
 72  _trackerObj: PrefTracker,
 73  _recordObj: PrefRec,
 74  version: 2,
 75
 76  getChangedIDs: function getChangedIDs() {
 77    // No need for a proper timestamp (no conflict resolution needed).
 78    let changedIDs = {};
 79    if (this._tracker.modified)
 80      changedIDs[PREFS_GUID] = 0;
 81    return changedIDs;
 82  },
 83
 84  _wipeClient: function _wipeClient() {
 85    SyncEngine.prototype._wipeClient.call(this);
 86    this.justWiped = true;
 87  },
 88
 89  _reconcile: function _reconcile(item) {
 90    // Apply the incoming item if we don't care about the local data
 91    if (this.justWiped) {
 92      this.justWiped = false;
 93      return true;
 94    }
 95    return SyncEngine.prototype._reconcile.call(this, item);
 96  }
 97};
 98
 99
100function PrefStore(name) {
101  Store.call(this, name);
102  Svc.Obs.add("profile-before-change", function() {
103    this.__prefs = null;
104  }, this);
105}
106PrefStore.prototype = {
107  __proto__: Store.prototype,
108
109 __prefs: null,
110  get _prefs() {
111    if (!this.__prefs)
112      this.__prefs = new Preferences();
113    return this.__prefs;
114  },
115
116  _getSyncPrefs: function _getSyncPrefs() {
117    let syncPrefs = Cc["@mozilla.org/preferences-service;1"]
118                      .getService(Ci.nsIPrefService)
119                      .getBranch(WEAVE_SYNC_PREFS)
120                      .getChildList("", {});
121    // Also sync preferences that determine which prefs get synced.
122    return syncPrefs.concat(
123      syncPrefs.map(function (pref) { return WEAVE_SYNC_PREFS + pref; }));
124  },
125
126  _isSynced: function _isSyncedPref(pref) {
127    return (pref.indexOf(WEAVE_SYNC_PREFS) == 0)
128            || this._prefs.get(WEAVE_SYNC_PREFS + pref, false);
129  },
130
131  _getAllPrefs: function () {
132    let values = {};
133    for each (let pref in this._getSyncPrefs()) {
134      if (this._isSynced(pref)) {
135        // Missing prefs get the null value.
136        values[pref] = this._prefs.get(pref, null);
137      }
138    }
139    return values;
140  },
141
142  _setAllPrefs: function PrefStore__setAllPrefs(values) {
143    let enabledPref = "lightweightThemes.isThemeSelected";
144    let enabledBefore = this._prefs.get(enabledPref, false);
145    let prevTheme = LightweightThemeManager.currentTheme;
146
147    for (let [pref, value] in Iterator(values)) {
148      if (!this._isSynced(pref))
149        continue;
150
151      // Pref has gone missing, best we can do is reset it.
152      if (value == null) {
153        this._prefs.reset(pref);
154        continue;
155      }
156
157      try {
158        this._prefs.set(pref, value);
159      } catch(ex) {
160        this._log.trace("Failed to set pref: " + pref + ": " + ex);
161      } 
162    }
163
164    // Notify the lightweight theme manager of all the new values
165    let enabledNow = this._prefs.get(enabledPref, false);
166    if (enabledBefore && !enabledNow) {
167      LightweightThemeManager.currentTheme = null;
168    } else if (enabledNow && LightweightThemeManager.usedThemes[0] != prevTheme) {
169      LightweightThemeManager.currentTheme = null;
170      LightweightThemeManager.currentTheme = LightweightThemeManager.usedThemes[0];
171    }
172  },
173
174  getAllIDs: function PrefStore_getAllIDs() {
175    /* We store all prefs in just one WBO, with just one GUID */
176    let allprefs = {};
177    allprefs[PREFS_GUID] = true;
178    return allprefs;
179  },
180
181  changeItemID: function PrefStore_changeItemID(oldID, newID) {
182    this._log.trace("PrefStore GUID is constant!");
183  },
184
185  itemExists: function FormStore_itemExists(id) {
186    return (id === PREFS_GUID);
187  },
188
189  createRecord: function createRecord(id, collection) {
190    let record = new PrefRec(collection, id);
191
192    if (id == PREFS_GUID) {
193      record.value = this._getAllPrefs();
194    } else {
195      record.deleted = true;
196    }
197
198    return record;
199  },
200
201  create: function PrefStore_create(record) {
202    this._log.trace("Ignoring create request");
203  },
204
205  remove: function PrefStore_remove(record) {
206    this._log.trace("Ignoring remove request");
207  },
208
209  update: function PrefStore_update(record) {
210    // Silently ignore pref updates that are for other apps.
211    if (record.id != PREFS_GUID)
212      return;
213
214    this._log.trace("Received pref updates, applying...");
215    this._setAllPrefs(record.value);
216  },
217
218  wipe: function PrefStore_wipe() {
219    this._log.trace("Ignoring wipe request");
220  }
221};
222
223function PrefTracker(name) {
224  Tracker.call(this, name);
225  Svc.Obs.add("profile-before-change", this);
226  Svc.Obs.add("weave:engine:start-tracking", this);
227  Svc.Obs.add("weave:engine:stop-tracking", this);
228}
229PrefTracker.prototype = {
230  __proto__: Tracker.prototype,
231
232  get modified() {
233    return Svc.Prefs.get("engine.prefs.modified", false);
234  },
235  set modified(value) {
236    Svc.Prefs.set("engine.prefs.modified", value);
237  },
238
239  loadChangedIDs: function loadChangedIDs() {
240    // Don't read changed IDs from disk at start up.
241  },
242
243  clearChangedIDs: function clearChangedIDs() {
244    this.modified = false;
245  },
246
247 __prefs: null,
248  get _prefs() {
249    if (!this.__prefs)
250      this.__prefs = new Preferences();
251    return this.__prefs;
252  },
253
254  _enabled: false,
255  observe: function(aSubject, aTopic, aData) {
256    switch (aTopic) {
257      case "weave:engine:start-tracking":
258        if (!this._enabled) {
259          Cc["@mozilla.org/preferences-service;1"]
260            .getService(Ci.nsIPrefBranch).addObserver("", this, false);
261          this._enabled = true;
262        }
263        break;
264      case "weave:engine:stop-tracking":
265        if (this._enabled)
266          this._enabled = false;
267        // Fall through to clean up.
268      case "profile-before-change":
269        this.__prefs = null;
270        Cc["@mozilla.org/preferences-service;1"]
271          .getService(Ci.nsIPrefBranch).removeObserver("", this);
272        break;
273      case "nsPref:changed":
274        // Trigger a sync for MULTI-DEVICE for a change that determines
275        // which prefs are synced or a regular pref change.
276        if (aData.indexOf(WEAVE_SYNC_PREFS) == 0 || 
277            this._prefs.get(WEAVE_SYNC_PREFS + aData, false)) {
278          this.score += SCORE_INCREMENT_XLARGE;
279          this.modified = true;
280          this._log.trace("Preference " + aData + " changed");
281        }
282        break;
283    }
284  }
285};