Bug 733599 - mozContacts should use DOMRequestIpcHelper. r=fabrice
authorGregor Wagner <anygregor@gmail.com>
Wed, 07 Mar 2012 13:45:24 -0800
changeset 88465 a26a660d491101eabfaf413824742c3ea0f6008f
parent 88464 69d3ec27878d8873d1c3aa897777708540913854
child 88466 fa2e0bdbf7f52d52bf7e5f3ba7baffe4d610f7e0
push id22199
push userbmo@edmorley.co.uk
push dateThu, 08 Mar 2012 13:15:53 +0000
treeherdermozilla-central@09a8a48476e5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfabrice
bugs733599
milestone13.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 733599 - mozContacts should use DOMRequestIpcHelper. r=fabrice
dom/base/Makefile.in
dom/contacts/ContactManager.js
dom/contacts/fallback/ContactService.jsm
--- a/dom/base/Makefile.in
+++ b/dom/base/Makefile.in
@@ -61,20 +61,22 @@ EXTRA_JS_MODULES = ConsoleAPIStorage.jsm
 
 ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
 EXTRA_COMPONENTS = \
 	        Webapps.js \
 	        Webapps.manifest \
 		$(NULL)
 
 EXTRA_JS_MODULES += Webapps.jsm \
-        DOMRequestHelper.jsm \
 		$(NULL)
 endif
 
+EXTRA_JS_MODULES += DOMRequestHelper.jsm \
+		$(NULL)
+
 XPIDLSRCS = \
   nsIDOMDOMError.idl \
   nsIDOMDOMRequest.idl \
   nsIEntropyCollector.idl \
   nsIScriptChannel.idl \
   $(NULL)
 
 EXPORTS = \
--- a/dom/contacts/ContactManager.js
+++ b/dom/contacts/ContactManager.js
@@ -12,16 +12,25 @@ else
   debug = function (s) {}
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
+
+XPCOMUtils.defineLazyGetter(Services, "rs", function() {
+  return Cc["@mozilla.org/dom/dom-request-service;1"].getService(Ci.nsIDOMRequestService);
+});
+
+XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
+  return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
+});
 
 const nsIClassInfo            = Ci.nsIClassInfo;
 const CONTACTPROPERTIES_CID   = Components.ID("{53ed7c20-ceda-11e0-9572-0800200c9a66}");
 const nsIDOMContactProperties = Ci.nsIDOMContactProperties;
 
 // ContactProperties is not directly instantiated. It is used as interface.
 
 ContactProperties.prototype = {
@@ -179,16 +188,17 @@ const CONTACTMANAGER_CID        = Compon
 const nsIDOMContactManager      = Components.interfaces.nsIDOMContactManager;
 
 function ContactManager()
 {
   debug("Constructor");
 }
 
 ContactManager.prototype = {
+  __proto__: DOMRequestIpcHelper.prototype,
 
   save: function save(aContact) {
     let request;
     if (this.hasPrivileges) {
       debug("save: " + JSON.stringify(aContact) + " :" + aContact.id);
       let newContact = {};
       newContact.properties = {
         name:            [],
@@ -217,31 +227,31 @@ ContactManager.prototype = {
 
       if (aContact.id == "undefined") {
         debug("Create id!");
         aContact.id = this._getRandomId();
       }
 
       this._setMetaData(newContact, aContact);
       debug("send: " + JSON.stringify(newContact));
-      request = this._rs.createRequest(this._window);
-      this._mm.sendAsyncMessage("Contact:Save", {contact: newContact,
-                                                 requestID: this.getRequestId({ request: request })});
+      request = this.createRequest();
+      cpmm.sendAsyncMessage("Contact:Save", {contact: newContact,
+                                             requestID: this.getRequestId(request)});
       return request;
     } else {
       throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
     }
   },
 
   remove: function removeContact(aRecord) {
     let request;
     if (this.hasPrivileges) {
-      request = this._rs.createRequest(this._window);
-      this._mm.sendAsyncMessage("Contact:Remove", {id: aRecord.id,
-                                                   requestID: this.getRequestId({ request: request })});
+      request = this.createRequest();
+      cpmm.sendAsyncMessage("Contact:Remove", {id: aRecord.id,
+                                               requestID: this.getRequestId(request)});
       return request;
     } else {
       throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
     }
   },
 
   _setMetaData: function(aNewContact, aRecord) {
     aNewContact.id = aRecord.id;
@@ -255,147 +265,102 @@ ContactManager.prototype = {
       let newContact = new Contact();
       newContact.init(aContacts[i].properties);
       this._setMetaData(newContact, aContacts[i]);
       contacts.push(newContact);
     }
     return contacts;
   },
 
-  getRequestId: function(aRequest) {
-    let id = "id" + this._getRandomId();
-    this._requests[id] = aRequest;
-    return id;
-  },
-
-  getRequest: function(aId) {
-    if (this._requests[aId])
-      return this._requests[aId].request;
-  },
-
-  removeRequest: function(aId) {
-    if (this._requests[aId])
-      delete this._requests[aId];
-  },
-  
-  _getRandomId: function() {
-    return Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
-  },
-
   receiveMessage: function(aMessage) {
     debug("Contactmanager::receiveMessage: " + aMessage.name);
     let msg = aMessage.json;
     let contacts = msg.contacts;
 
     switch (aMessage.name) {
       case "Contacts:Find:Return:OK":
         let req = this.getRequest(msg.requestID);
         if (req) {
           let result = this._convertContactsArray(contacts);
           debug("result: " + JSON.stringify(result));
-          this._rs.fireSuccess(req, result);
+          Services.rs.fireSuccess(req, result);
         } else {
           debug("no request stored!" + msg.requestID);
         }
         break;
       case "Contact:Save:Return:OK":
       case "Contacts:Clear:Return:OK":
       case "Contact:Remove:Return:OK":
         req = this.getRequest(msg.requestID);
         if (req)
-          this._rs.fireSuccess(req, 0);
+          Services.rs.fireSuccess(req, null);
         break;
       case "Contacts:Find:Return:KO":
       case "Contact:Save:Return:KO":
       case "Contact:Remove:Return:KO":
       case "Contacts:Clear:Return:KO":
         req = this.getRequest(msg.requestID);
         if (req)
-          this._rs.fireError(req, msg.errorMsg);
+          Services.rs.fireError(req, msg.errorMsg);
         break;
       default: 
         debug("Wrong message: " + aMessage.name);
     }
     this.removeRequest(msg.requestID);
   },
 
   find: function(aOptions) {
     let request;
     if (this.hasPrivileges) {
-      request = this._rs.createRequest(this._window);
-      this._mm.sendAsyncMessage("Contacts:Find", {findOptions: aOptions, 
-                                                  requestID: this.getRequestId({ request: request })});
+      request = this.createRequest();
+      cpmm.sendAsyncMessage("Contacts:Find", {findOptions: aOptions, 
+                                              requestID: this.getRequestId(request)});
       return request;
     } else {
       debug("find not allowed");
       throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
     }
   },
 
   clear: function() {
     let request;
     if (this.hasPrivileges) {
-      request = this._rs.createRequest(this._window);
-      this._mm.sendAsyncMessage("Contacts:Clear", {requestID: this.getRequestId({ request: request })});
+      request = this.createRequest();
+      cpmm.sendAsyncMessage("Contacts:Clear", {requestID: this.getRequestId(request)});
       return request;
     } else {
       debug("clear not allowed");
       throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
     }
   },
 
   init: function(aWindow) {
     // Set navigator.mozContacts to null.
     if (!Services.prefs.getBoolPref("dom.mozContacts.enabled"))
       return null;
 
-    this._window = aWindow;
-    this._messages = ["Contacts:Find:Return:OK", "Contacts:Find:Return:KO",
+    this.initHelper(aWindow, ["Contacts:Find:Return:OK", "Contacts:Find:Return:KO",
                      "Contacts:Clear:Return:OK", "Contacts:Clear:Return:KO",
                      "Contact:Save:Return:OK", "Contact:Save:Return:KO",
-                     "Contact:Remove:Return:OK", "Contact:Remove:Return:KO"];
+                     "Contact:Remove:Return:OK", "Contact:Remove:Return:KO"]);
 
-    this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
-    this._messages.forEach((function(msgName) {
-      this._mm.addMessageListener(msgName, this);
-    }).bind(this));
-
-    this._rs = Cc["@mozilla.org/dom/dom-request-service;1"].getService(Ci.nsIDOMRequestService);
-    this._requests = [];
     Services.obs.addObserver(this, "inner-window-destroyed", false);
-    let util = this._window.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 perm = principal == secMan.getSystemPrincipal() ? 
                  Ci.nsIPermissionManager.ALLOW_ACTION : 
                  Services.perms.testExactPermission(principal.URI, "webcontacts-manage");
  
     //only pages with perm set can use the contacts
     this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
     debug("has privileges :" + this.hasPrivileges);
   },
 
-  observe: function(aSubject, aTopic, aData) {
-    let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
-    if (wId == this.innerWindowID) {
-      Services.obs.removeObserver(this, "inner-window-destroyed");
-      this._messages.forEach((function(msgName) {
-        this._mm.removeMessageListener(msgName, this);
-      }).bind(this));
-      this._mm = null;
-      this._messages = null;
-      this._requests = null;
-      this._window = null;
-      this._innerWindowID = null;
-    }
-  },
-
   classID : CONTACTMANAGER_CID,
   QueryInterface : XPCOMUtils.generateQI([nsIDOMContactManager, Ci.nsIDOMGlobalPropertyInitializer]),
 
   classInfo : XPCOMUtils.generateCI({classID: CONTACTMANAGER_CID,
                                      contractID: CONTACTMANAGER_CONTRACTID,
                                      classDescription: "ContactManager",
                                      interfaces: [nsIDOMContactManager],
                                      flags: nsIClassInfo.DOM_OBJECT})
--- a/dom/contacts/fallback/ContactService.jsm
+++ b/dom/contacts/fallback/ContactService.jsm
@@ -15,26 +15,28 @@ const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 let EXPORTED_SYMBOLS = ["DOMContactManager"];
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/ContactDB.jsm");
 
+XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
+  return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
+});
+
 let myGlobal = this;
 
 let DOMContactManager = {
-
   init: function() {
     debug("Init");
-    this._mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
     this._messages = ["Contacts:Find", "Contacts:Clear", "Contact:Save", "Contact:Remove"];
     this._messages.forEach((function(msgName) {
-      this._mm.addMessageListener(msgName, this);
+      ppmm.addMessageListener(msgName, this);
     }).bind(this));
 
     var idbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"].getService(Ci.nsIIndexedDatabaseManager);
     idbManager.initWindowless(myGlobal);
     this._db = new ContactDB(myGlobal);
 
     Services.obs.addObserver(this, "profile-before-change", false);
 
@@ -47,50 +49,50 @@ let DOMContactManager = {
                              Ci.nsIPermissionManager.ALLOW_ACTION);
       });
     } catch(e) { debug(e); }
   },
 
   observe: function(aSubject, aTopic, aData) {
     myGlobal = null;
     this._messages.forEach((function(msgName) {
-      this._mm.removeMessageListener(msgName, this);
+      ppmm.removeMessageListener(msgName, this);
     }).bind(this));
     Services.obs.removeObserver(this, "profile-before-change");
-    this._mm = null;
+    ppmm = null;
     this._messages = null;
     if (this._db)
       this._db.close();
   },
 
   receiveMessage: function(aMessage) {
     debug("Fallback DOMContactManager::receiveMessage " + aMessage.name);
     let msg = aMessage.json;
     switch (aMessage.name) {
       case "Contacts:Find":
         let result = new Array();
         this._db.find(
           function(contacts) {
             for (let i in contacts)
               result.push(contacts[i]);
             debug("result:" + JSON.stringify(result));
-            this._mm.sendAsyncMessage("Contacts:Find:Return:OK", {requestID: msg.requestID, contacts: result});
+            ppmm.sendAsyncMessage("Contacts:Find:Return:OK", {requestID: msg.requestID, contacts: result});
           }.bind(this),
-          function(aErrorMsg) { this._mm.sendAsyncMessage("Contacts:Find:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }) }.bind(this), 
+          function(aErrorMsg) { ppmm.sendAsyncMessage("Contacts:Find:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }) }.bind(this), 
           msg.findOptions);
         break;
       case "Contact:Save":
-        this._db.saveContact(msg.contact, function() {this._mm.sendAsyncMessage("Contact:Save:Return:OK", { requestID: msg.requestID }); }.bind(this), 
-                             function(aErrorMsg) { this._mm.sendAsyncMessage("Contact:Save:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
+        this._db.saveContact(msg.contact, function() { ppmm.sendAsyncMessage("Contact:Save:Return:OK", { requestID: msg.requestID }); }.bind(this), 
+                             function(aErrorMsg) { ppmm.sendAsyncMessage("Contact:Save:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
         break;
       case "Contact:Remove":
         this._db.removeContact(msg.id, 
-                               function() {this._mm.sendAsyncMessage("Contact:Remove:Return:OK", { requestID: msg.requestID }); }.bind(this), 
-                               function(aErrorMsg) {this._mm.sendAsyncMessage("Contact:Remove:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
+                               function() { ppmm.sendAsyncMessage("Contact:Remove:Return:OK", { requestID: msg.requestID }); }.bind(this), 
+                               function(aErrorMsg) { ppmm.sendAsyncMessage("Contact:Remove:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
         break;
       case "Contacts:Clear":
-        this._db.clear(function() { this._mm.sendAsyncMessage("Contacts:Clear:Return:OK", { requestID: msg.requestID }); }.bind(this),
-                       function(aErrorMsg) { this._mm.sendAsyncMessage("Contacts:Clear:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
+        this._db.clear(function() { ppmm.sendAsyncMessage("Contacts:Clear:Return:OK", { requestID: msg.requestID }); }.bind(this),
+                       function(aErrorMsg) { ppmm.sendAsyncMessage("Contacts:Clear:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
     }
   }
 }
 
 DOMContactManager.init();