Bug 1386785 - Part 4. Uplift Bug 1385090 - Pass Remote Pages instance from AboutNewTab on override r=mossop draft
authorahillier <ahillier@mozilla.com>
Tue, 01 Aug 2017 15:08:16 -0400
changeset 619914 9b3a511cf3a40e4153e5842979f6f7b22ff37e65
parent 619913 1a45bbdd7f32cbbc87c9ff84b459677de3e705ea
child 619915 9de343e19eb350b36fc4e7b0e77d4f9e8693d3f8
push id71861
push userbmo:edilee@mozilla.com
push dateWed, 02 Aug 2017 20:06:54 +0000
reviewersmossop
bugs1386785, 1385090
milestone56.0
Bug 1386785 - Part 4. Uplift Bug 1385090 - Pass Remote Pages instance from AboutNewTab on override r=mossop MozReview-Commit-ID: 7oBsmIUpQXs
browser/extensions/activity-stream/lib/ActivityStreamMessageChannel.jsm
browser/modules/AboutNewTab.jsm
toolkit/modules/RemotePageManager.jsm
--- a/browser/extensions/activity-stream/lib/ActivityStreamMessageChannel.jsm
+++ b/browser/extensions/activity-stream/lib/ActivityStreamMessageChannel.jsm
@@ -121,36 +121,39 @@ this.ActivityStreamMessageChannel = clas
     return null;
   }
 
   /**
    * createChannel - Create RemotePages channel to establishing message passing
    *                 between the main process and child pages
    */
   createChannel() {
-    //  RemotePageManager must be disabled for about:newtab, since only one can exist at once
-    if (this.pageURL === ABOUT_NEW_TAB_URL) {
-      AboutNewTab.override();
-    }
-    this.channel = new RemotePages(this.pageURL);
+    //  Receive AboutNewTab's Remote Pages instance, if it exists, on override
+    const channel = this.pageURL === ABOUT_NEW_TAB_URL && AboutNewTab.override(true);
+    this.channel = channel || new RemotePages(this.pageURL);
     this.channel.addMessageListener("RemotePage:Init", this.onNewTabInit);
     this.channel.addMessageListener("RemotePage:Load", this.onNewTabLoad);
     this.channel.addMessageListener("RemotePage:Unload", this.onNewTabUnload);
     this.channel.addMessageListener(this.incomingMessageName, this.onMessage);
   }
 
   /**
    * destroyChannel - Destroys the RemotePages channel
    */
   destroyChannel() {
-    this.channel.destroy();
-    this.channel = null;
+    this.channel.removeMessageListener("RemotePage:Init", this.onNewTabInit);
+    this.channel.removeMessageListener("RemotePage:Load", this.onNewTabLoad);
+    this.channel.removeMessageListener("RemotePage:Unload", this.onNewTabUnload);
+    this.channel.removeMessageListener(this.incomingMessageName, this.onMessage);
     if (this.pageURL === ABOUT_NEW_TAB_URL) {
-      AboutNewTab.reset();
+      AboutNewTab.reset(this.channel);
+    } else {
+      this.channel.destroy();
     }
+    this.channel = null;
   }
 
 /**
  * onNewTabInit - Handler for special RemotePage:Init message fired
  * by RemotePages
  *
  * @param  {obj} msg The messsage from a page that was just initialized
  */
--- a/browser/modules/AboutNewTab.jsm
+++ b/browser/modules/AboutNewTab.jsm
@@ -21,24 +21,24 @@ XPCOMUtils.defineLazyModuleGetter(this, 
   "resource://gre/modules/RemotePageManager.jsm");
 
 var AboutNewTab = {
 
   pageListener: null,
 
   isOverridden: false,
 
-  init() {
+  init(pageListener) {
     if (this.isOverridden) {
       return;
     }
-    this.pageListener = new RemotePages("about:newtab");
-    this.pageListener.addMessageListener("NewTab:Customize", this.customize.bind(this));
+    this.pageListener = pageListener || new RemotePages("about:newtab");
+    this.pageListener.addMessageListener("NewTab:Customize", this.customize);
     this.pageListener.addMessageListener("NewTab:MaybeShowMigrateMessage",
-      this.maybeShowMigrateMessage.bind(this));
+      this.maybeShowMigrateMessage);
   },
 
   maybeShowMigrateMessage({ target }) {
     AutoMigrate.shouldShowMigratePrompt(target.browser).then((prompt) => {
       if (prompt) {
         AutoMigrate.showUndoNotificationBar(target.browser);
       }
     });
@@ -51,18 +51,29 @@ var AboutNewTab = {
 
   uninit() {
     if (this.pageListener) {
       this.pageListener.destroy();
       this.pageListener = null;
     }
   },
 
-  override() {
+  override(shouldPassPageListener) {
+    this.isOverridden = true;
+    const pageListener = this.pageListener;
+    if (!pageListener)
+      return null;
+    if (shouldPassPageListener) {
+      this.pageListener = null;
+      pageListener.removeMessageListener("NewTab:Customize", this.customize);
+      pageListener.removeMessageListener("NewTab:MaybeShowMigrateMessage",
+        this.maybeShowMigrateMessage);
+      return pageListener;
+    }
     this.uninit();
-    this.isOverridden = true;
+    return null;
   },
 
-  reset() {
+  reset(pageListener) {
     this.isOverridden = false;
-    this.init();
+    this.init(pageListener);
   }
 };
--- a/toolkit/modules/RemotePageManager.jsm
+++ b/toolkit/modules/RemotePageManager.jsm
@@ -1,17 +1,17 @@
 /* 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";
 
 this.EXPORTED_SYMBOLS = ["RemotePages", "RemotePageManager", "PageListener"];
 
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 function MessageListener() {
   this.listeners = new Map();
 }
 
@@ -122,17 +122,24 @@ RemotePages.prototype = {
 
   registerPortListener(port, name) {
     port.addMessageListener(name, this.portMessageReceived);
   },
 
   // Sends a message to all known pages
   sendAsyncMessage(name, data = null) {
     for (let port of this.messagePorts.values()) {
-      port.sendAsyncMessage(name, data);
+      try {
+        port.sendAsyncMessage(name, data);
+      } catch (e) {
+        // Unless the port is in the process of unloading, something strange
+        // happened but allow other ports to receive the message
+        if (e.result !== Cr.NS_ERROR_NOT_INITIALIZED)
+          Cu.reportError(e);
+      }
     }
   },
 
   addMessageListener(name, callback) {
     if (this.destroyed) {
       throw new Error("RemotePages has been destroyed");
     }