Bug 802564 - Can't set window.location in inline disposition web activity when its App frame is opened. r=fabrice, a=blocking-basecamp
authorBenjamin Chen <bechen@mozilla.com>
Wed, 07 Nov 2012 10:32:09 +0800
changeset 114098 782795b933e0ee31d88ff4190bc19dc03acb8fa9
parent 114097 91a6abdf9526f42840b47787d59ef5042ec68378
child 114099 394cf133f6f979e96d54e5e11e9b5ce177cff5fe
push id2643
push userryanvm@gmail.com
push dateSat, 10 Nov 2012 04:34:54 +0000
treeherdermozilla-aurora@34c4f8b76f49 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfabrice, blocking-basecamp
bugs802564
milestone18.0a2
Bug 802564 - Can't set window.location in inline disposition web activity when its App frame is opened. r=fabrice, a=blocking-basecamp 1. SystemMessageInternal: Handle the "_listeners" correctly by using "manifest" and "winID" 2. SystemMessageManager: Remove cpmm message listerners when receiving "inner-window-destroyed"; Add winID for the reg/unreg message. 3. DOMRequestIpcHelper: Check aTopic in observe method
dom/base/DOMRequestHelper.jsm
dom/messages/SystemMessageInternal.js
dom/messages/SystemMessageManager.js
--- a/dom/base/DOMRequestHelper.jsm
+++ b/dom/base/DOMRequestHelper.jsm
@@ -47,16 +47,20 @@ DOMRequestIpcHelper.prototype = {
     return request;
   },
 
   _getRandomId: function() {
     return Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
   },
 
   observe: function(aSubject, aTopic, aData) {
+    if (aTopic !== "inner-window-destroyed") {
+      return;
+    }
+
     let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
     if (wId == this.innerWindowID) {
       Services.obs.removeObserver(this, "inner-window-destroyed");
       this._requests = [];
       this._window = null;
       this.removeMessageListener();
       if(this.uninit)
         this.uninit();
--- a/dom/messages/SystemMessageInternal.js
+++ b/dom/messages/SystemMessageInternal.js
@@ -27,16 +27,17 @@ try {
 } catch(e) {
   // getIntPref throws when the pref is not set.
   kMaxPendingMessages = 5;
 }
 
 const kMessages =["SystemMessageManager:GetPendingMessages",
                   "SystemMessageManager:HasPendingMessages",
                   "SystemMessageManager:Register",
+                  "SystemMessageManager:Unregister",
                   "SystemMessageManager:Message:Return:OK",
                   "SystemMessageManager:AskReadyToRegister",
                   "child-process-shutdown"]
 
 function debug(aMsg) {
   //dump("-- SystemMessageInternal " + Date.now() + " : " + aMsg + "\n");
 }
 
@@ -76,24 +77,25 @@ SystemMessageInternal.prototype = {
 
     // Give this message an ID so that we can identify the message and
     // clean it up from the pending message queue when apps receive it.
     let messageID = gUUIDGenerator.generateUUID().toString();
 
     debug("Sending " + aType + " " + JSON.stringify(aMessage) +
       " for " + aPageURI.spec + " @ " + aManifestURI.spec);
     if (this._listeners[aManifestURI.spec]) {
-      this._listeners[aManifestURI.spec].forEach(function sendMsg(aListener) {
-        aListener.sendAsyncMessage("SystemMessageManager:Message",
-                                   { type: aType,
-                                     msg: aMessage,
-                                     manifest: aManifestURI.spec,
-                                     uri: aPageURI.spec,
-                                     msgID: messageID })
-      });
+      let manifest = this._listeners[aManifestURI.spec];
+      for (let winID in manifest) {
+        manifest[winID].sendAsyncMessage("SystemMessageManager:Message",
+                                         { type: aType,
+                                           msg: aMessage,
+                                           manifest: aManifestURI.spec,
+                                           uri: aPageURI.spec,
+                                           msgID: messageID });
+      }
     }
 
     let pagesToOpen = {};
     this._pages.forEach(function(aPage) {
       if (!this._isPageMatched(aPage, aType, aPageURI.spec, aManifestURI.spec)) {
         return;
       }
 
@@ -125,24 +127,25 @@ SystemMessageInternal.prototype = {
     let messageID = gUUIDGenerator.generateUUID().toString();
 
     debug("Broadcasting " + aType + " " + JSON.stringify(aMessage));
     // Find pages that registered an handler for this type.
     let pagesToOpen = {};
     this._pages.forEach(function(aPage) {
       if (aPage.type == aType) {
         if (this._listeners[aPage.manifest]) {
-          this._listeners[aPage.manifest].forEach(function sendMsg(aListener) {
-            aListener.sendAsyncMessage("SystemMessageManager:Message",
-                                       { type: aType,
-                                         msg: aMessage,
-                                         manifest: aPage.manifest,
-                                         uri: aPage.uri,
-                                         msgID: messageID })
-          });
+          let manifest = this._listeners[aPage.manifest];
+          for (let winID in manifest) {
+            manifest[winID].sendAsyncMessage("SystemMessageManager:Message",
+                                             { type: aType,
+                                               msg: aMessage,
+                                               manifest: aPage.manifest,
+                                               uri: aPage.uri,
+                                               msgID: messageID });
+          }
         }
         // Queue this message in the corresponding pages.
         this._queueMessage(aPage, aMessage, messageID);
 
         // Open app pages to handle their pending messages.
         // Note that we only need to open each app page once.
         let key = this._createKeyForPage(aPage);
         if (!pagesToOpen.hasOwnProperty(key)) {
@@ -167,39 +170,46 @@ SystemMessageInternal.prototype = {
   receiveMessage: function receiveMessage(aMessage) {
     let msg = aMessage.json;
     switch(aMessage.name) {
       case "SystemMessageManager:AskReadyToRegister":
         return true;
         break;
       case "SystemMessageManager:Register":
       {
-        let manifest = msg.manifest;
-        debug("Got Register from " + manifest);
-        if (!this._listeners[manifest]) {
-          this._listeners[manifest] = [];
+        debug("Got Register from " + msg.manifest);
+        if (!this._listeners[msg.manifest]) {
+          this._listeners[msg.manifest] = {};
         }
-        this._listeners[manifest].push(aMessage.target);
-        debug("listeners for " + manifest + " : " + this._listeners[manifest].length);
+        this._listeners[msg.manifest][msg.innerWindowID] = aMessage.target;
+        debug("listeners for " + msg.manifest + " innerWinID " + msg.innerWindowID);
         break;
       }
       case "child-process-shutdown":
       {
-        debug("Got Unregister from " + aMessage.target);
-        let mm = aMessage.target;
+        debug("Got child-process-shutdown from " + aMessage.target);
         for (let manifest in this._listeners) {
-          let index = this._listeners[manifest].indexOf(mm);
-          while (index != -1) {
-            debug("Removing " + mm + " at index " + index);
-            this._listeners[manifest].splice(index, 1);
-            index = this._listeners[manifest].indexOf(mm);
+          for (let winID in this._listeners[manifest]) {
+            if (aMessage.target === this._listeners[manifest][winID]) {
+              debug("remove " + manifest );
+              delete this._listeners[manifest];
+              return;
+            }
           }
         }
         break;
       }
+      case "SystemMessageManager:Unregister":
+      {
+        debug("Got Unregister from " + aMessage.target + "innerWinID " + msg.innerWindowID);
+        delete this._listeners[msg.manifest][msg.innerWindowID];
+        debug("Removing " + aMessage.target + "innerWinID " + msg.innerWindowID );
+
+        break;
+      }
       case "SystemMessageManager:GetPendingMessages":
       {
         debug("received SystemMessageManager:GetPendingMessages " + msg.type +
           " for " + msg.uri + " @ " + msg.manifest);
 
         // This is a sync call used to return the pending messages for a page.
         // Find the right page to get its corresponding pending messages.
         let page = null;
--- a/dom/messages/SystemMessageManager.js
+++ b/dom/messages/SystemMessageManager.js
@@ -119,16 +119,21 @@ SystemMessageManager.prototype = {
 
   uninit: function sysMessMgr_uninit()  {
     this._handlers = null;
     this._pendings = null;
 
     if (this._isParentProcess) {
       Services.obs.removeObserver(this, kSystemMessageInternalReady);
     }
+
+    cpmm.sendAsyncMessage("SystemMessageManager:Unregister",
+                          { manifest: this._manifest,
+                            innerWindowID: this.innerWindowID
+                          });
   },
 
   receiveMessage: function sysMessMgr_receiveMessage(aMessage) {
     debug("receiveMessage " + aMessage.name + " - " +
           aMessage.data.type + " for " + aMessage.data.manifest +
           " (" + this._manifest + ")");
 
     let msg = aMessage.data;
@@ -169,17 +174,16 @@ SystemMessageManager.prototype = {
                               "SystemMessageManager:GetPendingMessages:Return"]);
 
     let principal = aWindow.document.nodePrincipal;
     this._uri = principal.URI.spec;
 
     let appsService = Cc["@mozilla.org/AppsService;1"]
                         .getService(Ci.nsIAppsService);
     this._manifest = appsService.getManifestURLByLocalId(principal.appId);
-    this._window = aWindow;
 
     // Two cases are valid to register the manifest for the current process:
     // 1. This is asked by a child process (parent process must be ready).
     // 2. Parent process has already constructed the |SystemMessageInternal|.
     // Otherwise, delay to do it when the |SystemMessageInternal| is ready.
     let readyToRegister = true;
     if (this._isParentProcess) {
       let ready = cpmm.sendSyncMessage(
@@ -194,22 +198,26 @@ SystemMessageManager.prototype = {
 
     debug("done");
   },
 
   observe: function sysMessMgr_observe(aSubject, aTopic, aData) {
     if (aTopic === kSystemMessageInternalReady) {
       this._registerManifest();
     }
+    //call the DOMRequestIpcHelper.observe method
+    this.__proto__.__proto__.observe.call(this, aSubject, aTopic, aData);
   },
 
   _registerManifest: function sysMessMgr_registerManifest() {
     if (!this._registerManifestReady) {
       cpmm.sendAsyncMessage("SystemMessageManager:Register",
-                            { manifest: this._manifest });
+                            { manifest: this._manifest,
+                              innerWindowID: this.innerWindowID
+                            });
       this._registerManifestReady = true;
     }
   },
 
   classID: Components.ID("{bc076ea0-609b-4d8f-83d7-5af7cbdc3bb2}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMNavigatorSystemMessages,
                                          Ci.nsIDOMGlobalPropertyInitializer,