From a0fa18644575f4d6e9b82a315f6d228cb0edf6f3 Mon Sep 17 00:00:00 2001 From: Anant Narayanan Date: Sun, 24 May 2009 02:11:05 +0200 Subject: [PATCH] Preference sync (bug #428370) --- services/sync/modules/engines/prefs.js | 248 ++++++++++++++++++++ services/sync/modules/service.js | 6 +- services/sync/modules/type_records/prefs.js | 67 ++++++ services/sync/services-sync.js | 29 +++ 4 files changed, 348 insertions(+), 2 deletions(-) create mode 100644 services/sync/modules/engines/prefs.js create mode 100644 services/sync/modules/type_records/prefs.js diff --git a/services/sync/modules/engines/prefs.js b/services/sync/modules/engines/prefs.js new file mode 100644 index 000000000000..3c2165e71bad --- /dev/null +++ b/services/sync/modules/engines/prefs.js @@ -0,0 +1,248 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Bookmarks Sync. + * + * The Initial Developer of the Original Code is Mozilla. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Anant Narayanan + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +const EXPORTED_SYMBOLS = ['PrefsEngine']; + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; + +const WEAVE_SYNC_PREFS = "extensions.weave.prefs.sync"; +const WEAVE_PREFS_GUID = "preferences"; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +Cu.import("resource://weave/log4moz.js"); +Cu.import("resource://weave/async.js"); +Cu.import("resource://weave/util.js"); +Cu.import("resource://weave/engines.js"); +Cu.import("resource://weave/stores.js"); +Cu.import("resource://weave/trackers.js"); +Cu.import("resource://weave/type_records/prefs.js"); + +Function.prototype.async = Async.sugar; + +function PrefsEngine() { + this._init(); +} +PrefsEngine.prototype = { + __proto__: SyncEngine.prototype, + name: "prefs", + displayName: "Preferences", + logName: "Prefs", + _storeObj: PrefStore, + _trackerObj: PrefTracker, + _recordObj: PrefRec, + + _recordLike: function SyncEngine__recordLike(a, b) { + if (a.deleted || b.deleted) + return false; + if (a.name == b.name && a.value == b.value) + return true; + return false; + } +}; + + +function PrefStore() { + this._init(); +} +PrefStore.prototype = { + __proto__: Store.prototype, + _logName: "PrefStore", + + get _prefs() { + let prefs = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + + this.__defineGetter__("_prefs", function() prefs); + return prefs; + }, + + get _syncPrefs() { + let service = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefService); + let syncPrefs = service.getBranch(WEAVE_SYNC_PREFS).getChildList("", {}). + map(function(elem) { return elem.substr(1); }); + + this.__defineGetter__("_syncPrefs", function() syncPrefs); + return syncPrefs; + }, + + _getAllPrefs: function PrefStore__getAllPrefs() { + let values = []; + let toSync = this._syncPrefs; + + let pref; + for (let i = 0; i < toSync.length; i++) { + if (!this._prefs.getBoolPref(WEAVE_SYNC_PREFS + "." + toSync[i])) + continue; + + pref = {}; + pref["name"] = toSync[i]; + + switch (this._prefs.getPrefType(toSync[i])) { + case Ci.nsIPrefBranch.PREF_INT: + pref["type"] = "int"; + pref["value"] = this._prefs.getIntPref(toSync[i]); + break; + case Ci.nsIPrefBranch.PREF_STRING: + pref["type"] = "string"; + pref["value"] = this._prefs.getCharPref(toSync[i]); + break; + case Ci.nsIPrefBranch.PREF_BOOL: + pref["type"] = "boolean"; + pref["value"] = this._prefs.getBoolPref(toSync[i]); + break; + default: + this._log.warn("Unsupported pref type for " + toSync[i]); + } + if ("value" in pref) + values[values.length] = pref; + } + + return values; + }, + + _setAllPrefs: function PrefStore__setAllPrefs(values) { + for (let i = 0; i < values.length; i++) { + switch (values[i]["type"]) { + case "int": + this._prefs.setIntPref(values[i]["name"], values[i]["value"]); + break; + case "string": + this._prefs.setCharPref(values[i]["name"], values[i]["value"]); + break; + case "boolean": + this._prefs.setBoolPref(values[i]["name"], values[i]["value"]); + break; + default: + this._log.warn("Unexpected preference type: " + values[i]["type"]); + } + } + }, + + getAllIDs: function PrefStore_getAllIDs() { + /* We store all prefs in just one WBO, with just one GUID */ + let allprefs = {}; + allprefs[WEAVE_PREFS_GUID] = this._getAllPrefs(); + return allprefs; + }, + + changeItemID: function PrefStore_changeItemID(oldID, newID) { + this._log.warn("PrefStore GUID is constant!"); + }, + + itemExists: function FormStore_itemExists(id) { + return (id === WEAVE_PREFS_GUID); + }, + + createRecord: function FormStore_createRecord(guid, cryptoMetaURL) { + let record = new PrefRec(); + record.id = guid; + + if (guid == WEAVE_PREFS_GUID) { + record.encryption = cryptoMetaURL; + record.value = this._getAllPrefs(); + } else { + record.deleted = true; + } + + return record; + }, + + create: function PrefStore_create(record) { + this._log.warn("Ignoring create request"); + }, + + remove: function PrefStore_remove(record) { + this._log.warn("Ignoring remove request") + }, + + update: function PrefStore_update(record) { + this._log.debug("Received pref updates, applying..."); + this._setAllPrefs(record.value); + }, + + wipe: function PrefStore_wipe() { + this._log.warn("Ignoring wipe request"); + } +}; + +function PrefTracker() { + this._init(); +} +PrefTracker.prototype = { + __proto__: Tracker.prototype, + _logName: "PrefTracker", + file: "prefs", + + get _prefs() { + let prefs = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch2); + + this.__defineGetter__("_prefs", function() prefs); + return prefs; + }, + + get _syncPrefs() { + let service = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefService); + let syncPrefs = service.getBranch(WEAVE_SYNC_PREFS).getChildList("", {}). + map(function(elem) { return elem.substr(1); }); + + this.__defineGetter__("_syncPrefs", function() syncPrefs); + return syncPrefs; + }, + + _init: function PrefTracker__init() { + this.__proto__.__proto__._init.call(this); + this._log.debug("PrefTracker initializing!"); + this._prefs.addObserver("", this, false); + }, + + /* 25 points per pref change */ + observe: function(aSubject, aTopic, aData) { + if (aTopic != "nsPref:changed") + return; + + if (this._syncPrefs.indexOf(aData) != -1) { + this._score += 25; + this.addChangedID(WEAVE_PREFS_GUID); + this._log.debug("Preference " + aData + " changed"); + } + } +}; diff --git a/services/sync/modules/service.js b/services/sync/modules/service.js index 44109bd552ee..d5585e3bc0cb 100644 --- a/services/sync/modules/service.js +++ b/services/sync/modules/service.js @@ -103,6 +103,7 @@ Cu.import("resource://weave/engines/extensions.js", Weave); Cu.import("resource://weave/engines/forms.js", Weave); Cu.import("resource://weave/engines/history.js", Weave); Cu.import("resource://weave/engines/input.js", Weave); +Cu.import("resource://weave/engines/prefs.js", Weave); Cu.import("resource://weave/engines/microformats.js", Weave); Cu.import("resource://weave/engines/passwords.js", Weave); Cu.import("resource://weave/engines/plugins.js", Weave); @@ -395,8 +396,9 @@ WeaveSvc.prototype = { break; case FIREFOX_ID: - engines = ["Bookmarks", "Cookie", "Extension", "Form", "History", "Input", - "MicroFormat", "Password", "Plugin", "Tab", "Theme"]; + engines = ["Bookmarks", "Cookie", "Extension", "Form", "History", + "Input", "MicroFormat", "Password", "Plugin", "Prefs", "Tab", + "Theme"]; break; case SEAMONKEY_ID: diff --git a/services/sync/modules/type_records/prefs.js b/services/sync/modules/type_records/prefs.js new file mode 100644 index 000000000000..c67b15456f40 --- /dev/null +++ b/services/sync/modules/type_records/prefs.js @@ -0,0 +1,67 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Weave. + * + * The Initial Developer of the Original Code is Mozilla. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Anant Narayanan + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +const EXPORTED_SYMBOLS = ['PrefRec']; + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cr = Components.results; +const Cu = Components.utils; + +Cu.import("resource://weave/log4moz.js"); +Cu.import("resource://weave/util.js"); +Cu.import("resource://weave/async.js"); +Cu.import("resource://weave/base_records/wbo.js"); +Cu.import("resource://weave/base_records/crypto.js"); +Cu.import("resource://weave/base_records/keys.js"); + +Function.prototype.async = Async.sugar; + +function PrefRec(uri) { + this._PrefRec_init(uri); +} +PrefRec.prototype = { + __proto__: CryptoWrapper.prototype, + _logName: "Record.Pref", + + _PrefRec_init: function PrefRec_init(uri) { + this._CryptoWrap_init(uri); + this.cleartext = { + }; + }, +}; + +Utils.deferGetSet(PrefRec, "cleartext", ["type", "value"]); diff --git a/services/sync/services-sync.js b/services/sync/services-sync.js index 72dbe1932e08..abb3216b4f32 100644 --- a/services/sync/services-sync.js +++ b/services/sync/services-sync.js @@ -20,6 +20,7 @@ pref("extensions.weave.engine.forms", false); pref("extensions.weave.engine.history", true); //pref("extensions.weave.engine.input", false); pref("extensions.weave.engine.passwords", true); +pref("extensions.weave.engine.prefs", false); pref("extensions.weave.engine.tabs", true); pref("extensions.weave.log.appender.console", "Warn"); @@ -43,3 +44,31 @@ pref("extensions.weave.network.numRetries", 2); pref("extensions.weave.tabs.sortMode", "recency"); pref("extensions.weave.openId.enabled", true); pref("extensions.weave.authenticator.enabled", true); + +// Preferences to be synced by default + +pref("extensions.weave.prefs.sync.browser.download.manager.scanWhenDone", true); + +pref("extensions.weave.prefs.sync.browser.search.openintab", true); +pref("extensions.weave.prefs.sync.browser.search.selectedEngine", true); + +pref("extensions.weave.prefs.sync.browser.sessionstore.resume_from_crash", true); +pref("extensions.weave.prefs.sync.browser.sessionstore.resume_session_once", true); +pref("extensions.weave.prefs.sync.browser.sessionstore.interval", true); + +pref("extensions.weave.prefs.sync.browser.startup.homepage", true); +pref("extensions.weave.prefs.sync.startup.homepage_override_url", true); + +pref("extensions.weave.prefs.sync.browser.tabs.tabMinWidth", true); +pref("extensions.weave.prefs.sync.browser.tabs.warnOnClose", true); +pref("extensions.weave.prefs.sync.browser.tabs.closeButtons", true); + +pref("extensions.weave.prefs.sync.browser.urlbar.autoFill", true); +pref("extensions.weave.prefs.sync.browser.urlbar.maxRichResults", true); +pref("extensions.weave.prefs.sync.browser.urlbar.clickSelectsAll", true); +pref("extensions.weave.prefs.sync.browser.urlbar.doubleClickSelectsAll", true); + +pref("extensions.weave.prefs.sync.layout.spellcheckDefault", true); +pref("extensions.weave.prefs.sync.security.dialog_enable_delay", true); +pref("extensions.weave.prefs.sync.signon.rememberSignons", true); +pref("extensions.weave.prefs.sync.spellchecker.dictionary", true);