Bug 753862 - Settings API: electrolysis support. r=fabrice
authorChristoph Kerschbaumer <mozilla@christophkerschbaumer.com>
Mon, 04 Jun 2012 16:12:24 -0700
changeset 95783 a7cbb6716a5b1e555000d4f07076f2e831a63ea8
parent 95782 c9ec02b2b2e2216364471ceb9ae3def66e748d64
child 95784 22a1bfac13d6d1a7fb9dfd0733494daa43b1623e
push id10256
push usergwagner@mozilla.com
push dateMon, 04 Jun 2012 23:13:22 +0000
treeherdermozilla-inbound@a7cbb6716a5b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfabrice
bugs753862
milestone15.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 753862 - Settings API: electrolysis support. r=fabrice
b2g/chrome/content/shell.js
dom/settings/Makefile.in
dom/settings/SettingsChangeNotifier.jsm
dom/settings/SettingsManager.js
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -7,16 +7,17 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/ContactService.jsm');
+Cu.import('resource://gre/modules/SettingsChangeNotifier.jsm');
 Cu.import('resource://gre/modules/Webapps.jsm');
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'env',
                                    '@mozilla.org/process/environment;1',
                                    'nsIEnvironment');
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'ss',
                                    '@mozilla.org/content/style-sheet-service;1',
--- a/dom/settings/Makefile.in
+++ b/dom/settings/Makefile.in
@@ -20,16 +20,17 @@ EXTRA_COMPONENTS =         \
   SettingsManager.manifest \
   SettingsService.js \
   SettingsService.manifest \
   $(NULL)
 
 EXTRA_JS_MODULES =   \
   SettingsQueue.jsm  \
   SettingsDB.jsm     \
+  SettingsChangeNotifier.jsm \
   $(NULL)
 
 ifdef ENABLE_TESTS
 DIRS += tests
 endif
 
 # Add VPATH to LOCAL_INCLUDES so we are going to include the correct backend
 # subdirectory (and the ipc one).
new file mode 100644
--- /dev/null
+++ b/dom/settings/SettingsChangeNotifier.jsm
@@ -0,0 +1,56 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict"
+
+function debug(s) {
+//  dump("-*- SettingsChangeNotifier: " + s + "\n");
+}
+
+const Cu = Components.utils; 
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+let EXPORTED_SYMBOLS = ["SettingsChangeNotifier"];
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
+  return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
+});
+
+
+let SettingsChangeNotifier = {
+  init: function() {
+    debug("init");
+    ppmm.addMessageListener("Settings:Changed", this);
+    Services.obs.addObserver(this, "xpcom-shutdown", false);
+  },
+
+  observe: function(aSubject, aTopic, aData) {
+    debug("observe");
+    ppmm.removeMessageListener("Settings:Changed", this);
+    Services.obs.removeObserver(this, "xpcom-shutdown");
+    ppmm = null;
+  },
+
+  receiveMessage: function(aMessage) {
+    debug("receiveMessage");
+    let msg = aMessage.json;
+    switch (aMessage.name) {
+      case "Settings:Changed":
+        ppmm.sendAsyncMessage("Settings:Change:Return:OK", { key: msg.key, value: msg.value });
+        Services.obs.notifyObservers(this, "mozsettings-changed", JSON.stringify({
+          key: msg.key,
+          value: msg.value
+        }));
+        break;
+      default: 
+        debug("Wrong message: " + aMessage.name);
+    }
+  }
+}
+
+SettingsChangeNotifier.init();
--- a/dom/settings/SettingsManager.js
+++ b/dom/settings/SettingsManager.js
@@ -1,30 +1,31 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-/* static functions */
-let DEBUG = false;
-if (DEBUG)
-  debug = function (s) { dump("-*- SettingsManager: " + s + "\n"); };
-else
-  debug = function (s) {};
+function debug(s) {
+//  dump("-*- SettingsManager: " + s + "\n");
+}
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/SettingsQueue.jsm");
 Cu.import("resource://gre/modules/SettingsDB.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
+XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
+  return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
+});
+
 const nsIClassInfo            = Ci.nsIClassInfo;
 const SETTINGSLOCK_CONTRACTID = "@mozilla.org/settingsLock;1";
 const SETTINGSLOCK_CID        = Components.ID("{ef95ddd0-6308-11e1-b86c-0800200c9a66}");
 const nsIDOMSettingsLock      = Ci.nsIDOMSettingsLock;
 
 function SettingsLock(aSettingsManager)
 {
   this._open = true;
@@ -62,20 +63,17 @@ SettingsLock.prototype = {
               //Workaround for cloning issues
               let obj = JSON.parse(JSON.stringify(info.settings[key]));
               req = store.put({settingName: key, settingValue: obj});
             }
 
             req.onsuccess = function() { 
               lock._open = true;
               Services.DOMRequest.fireSuccess(request, 0);
-              Services.obs.notifyObservers(lock, "mozsettings-changed", JSON.stringify({
-                key: key,
-                value: info.settings[key]
-              }));
+              cpmm.sendAsyncMessage("Settings:Changed", { key: key, value: info.settings[key] });
               lock._open = false;
             };
 
             req.onerror = function() { Services.DOMRequest.fireError(request, 0) };
           }
           break;
         case "get":
           if (info.name == "*") {
@@ -222,24 +220,47 @@ SettingsManager.prototype = {
     this._settingsDB.ensureDB(
       function() { lock.createTransactionAndProcess(); },
       function() { dump("ensureDB error cb!\n"); },
       myGlobal );
     this.nextTick(function() { this._open = false; }, lock);
     return lock;
   },
 
+  receiveMessage: function(aMessage) {
+    debug("Settings::receiveMessage: " + aMessage.name);
+    let msg = aMessage.json;
+
+    switch (aMessage.name) {
+      case "Settings:Change:Return:OK":
+        debug("Settings:Change:Return:OK");
+        if (!this._onsettingchange)
+          return;
+
+        debug('key:' + msg.key + ', value:' + msg.value + '\n');
+        let event = new this._window.MozSettingsEvent("settingchanged", {
+          settingName: msg.key,
+          settingValue: msg.value
+        });
+
+        this._onsettingchange.handleEvent(event);
+        break;
+      default: 
+        debug("Wrong message: " + aMessage.name);
+    }
+  },
+
   init: function(aWindow) {
     // Set navigator.mozSettings to null.
     if (!Services.prefs.getBoolPref("dom.mozSettings.enabled"))
       return null;
 
+    cpmm.addMessageListener("Settings:Change:Return:OK", this);
     this._window = aWindow;
     Services.obs.addObserver(this, "inner-window-destroyed", false);
-    Services.obs.addObserver(this, "mozsettings-changed", false);
     let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
     this.innerWindowID = util.currentInnerWindowID;
 
     let principal = aWindow.document.nodePrincipal;
     let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
     let readPerm = principal == secMan.getSystemPrincipal() ? Ci.nsIPermissionManager.ALLOW_ACTION : Services.perms.testExactPermission(principal.URI, "websettings-read");
     let readwritePerm = principal == secMan.getSystemPrincipal() ? Ci.nsIPermissionManager.ALLOW_ACTION : Services.perms.testExactPermission(principal.URI, "websettings-readwrite");
     this.hasReadPrivileges = readPerm == Ci.nsIPermissionManager.ALLOW_ACTION;
@@ -248,36 +269,24 @@ SettingsManager.prototype = {
   },
 
   observe: function(aSubject, aTopic, aData) {
     debug("Topic: " + aTopic);
     if (aTopic == "inner-window-destroyed") {
       let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
       if (wId == this.innerWindowID) {
         Services.obs.removeObserver(this, "inner-window-destroyed");
-        Services.obs.removeObserver(this, "mozsettings-changed");
+        cpmm.removeMessageListener("Settings:Change:Return:OK", this);
         this._requests = null;
         this._window = null;
         this._innerWindowID = null;
         this._onsettingchange = null;
         this._settingsDB.close();
+        cpmm = null;
       }
-    } else if (aTopic == "mozsettings-changed") {
-      if (!this._onsettingchange)
-        return;
-
-      let data = JSON.parse(aData);
-      debug('data:' + data.key + ':' + data.value + '\n');
-
-      let event = new this._window.MozSettingsEvent("settingchanged", {
-        settingName: data.key,
-        settingValue: data.value
-      });
-
-      this._onsettingchange.handleEvent(event);
     }
   },
 
   classID : SETTINGSMANAGER_CID,
   QueryInterface : XPCOMUtils.generateQI([nsIDOMSettingsManager, Ci.nsIDOMGlobalPropertyInitializer]),
 
   classInfo : XPCOMUtils.generateCI({classID: SETTINGSMANAGER_CID,
                                      contractID: SETTINGSMANAGER_CONTRACTID,