Backed out changeset f840add2cdd4 (bug 1474163) for causing mochitest frequent leaks.
authorCosmin Sabou <csabou@mozilla.com>
Mon, 23 Jul 2018 16:29:05 +0300
changeset 482865 e207f210919a58c9032e3ea032ee1553194c8872
parent 482864 cee6f792620d5953257bf8f866472ee296e83d94
child 482866 f5959a93f562f1c5716ad4e902efabe3f37e9774
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1474163
milestone63.0a1
backs outf840add2cdd448ccb2a59d97c0ac6cbd967f038d
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
Backed out changeset f840add2cdd4 (bug 1474163) for causing mochitest frequent leaks.
browser/base/content/contentTheme.js
browser/base/content/tab-content.js
browser/base/content/test/performance/browser_startup_content.js
browser/modules/LightweightThemeChildHelper.jsm
browser/modules/LightweightThemeChildListener.jsm
browser/modules/moz.build
toolkit/components/extensions/test/browser/browser_ext_themes_ntp_colors.js
toolkit/components/extensions/test/browser/browser_ext_themes_ntp_colors_perwindow.js
toolkit/modules/LightweightThemeConsumer.jsm
--- a/browser/base/content/contentTheme.js
+++ b/browser/base/content/contentTheme.js
@@ -41,24 +41,27 @@ const inContentVariableMap = [
  */
 const ContentThemeController = {
   /**
    * Tell the frame script that the page supports theming, and watch for updates
    * from the frame script.
    */
   init() {
     addEventListener("LightweightTheme:Set", this);
+
+    const event = new CustomEvent("LightweightTheme:Support", {bubbles: true});
+    document.dispatchEvent(event);
   },
 
   /**
    * Handle theme updates from the frame script.
    * @param {Object} event object containing the theme update.
    */
-  handleEvent({ type, detail }) {
-    if (type == "LightweightTheme:Set") {
+  handleEvent({ detail }) {
+    if (detail.type == "LightweightTheme:Update") {
       let {data} = detail;
       if (!data) {
         data = {};
       }
       this._setProperties(document.body, data);
     }
   },
 
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -19,16 +19,18 @@ ChromeUtils.defineModuleGetter(this, "Ut
 ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 ChromeUtils.defineModuleGetter(this, "AboutReader",
   "resource://gre/modules/AboutReader.jsm");
 ChromeUtils.defineModuleGetter(this, "ReaderMode",
   "resource://gre/modules/ReaderMode.jsm");
 ChromeUtils.defineModuleGetter(this, "PageStyleHandler",
   "resource:///modules/PageStyleHandler.jsm");
+ChromeUtils.defineModuleGetter(this, "LightweightThemeChildListener",
+  "resource:///modules/LightweightThemeChildListener.jsm");
 
 // TabChildGlobal
 var global = this;
 
 
 addEventListener("MozDOMPointerLock:Entered", function(aEvent) {
   sendAsyncMessage("PointerLock:Entered", {
     originNoSuffix: aEvent.target.nodePrincipal.originNoSuffix
@@ -82,31 +84,43 @@ addMessageListener("Browser:Reload", fun
   } catch (e) {
   }
 });
 
 addMessageListener("MixedContent:ReenableProtection", function() {
   docShell.mixedContentChannel = null;
 });
 
-XPCOMUtils.defineLazyProxy(this, "LightweightThemeChildHelper",
-  "resource:///modules/LightweightThemeChildHelper.jsm");
+var LightweightThemeChildListenerStub = {
+  _childListener: null,
+  get childListener() {
+    if (!this._childListener) {
+      this._childListener = new LightweightThemeChildListener();
+    }
+    return this._childListener;
+  },
 
-let themeablePagesWhitelist = new Set([
-  "about:home",
-  "about:newtab",
-  "about:welcome",
-]);
+  init() {
+    addEventListener("LightweightTheme:Support", this, false, true);
+    addMessageListener("LightweightTheme:Update", this);
+    sendAsyncMessage("LightweightTheme:Request");
+    this.init = null;
+  },
 
-addEventListener("pageshow", function({ originalTarget }) {
-  if (originalTarget.defaultView == content && themeablePagesWhitelist.has(content.document.documentURI)) {
-    LightweightThemeChildHelper.listen(themeablePagesWhitelist);
-    LightweightThemeChildHelper.update(chromeOuterWindowID, content);
-  }
-}, false, true);
+  handleEvent(event) {
+    return this.childListener.handleEvent(event);
+  },
+
+  receiveMessage(msg) {
+    return this.childListener.receiveMessage(msg);
+  },
+};
+
+LightweightThemeChildListenerStub.init();
+
 
 var AboutReaderListener = {
 
   _articlePromise: null,
 
   _isLeavingReaderableReaderMode: false,
 
   init() {
--- a/browser/base/content/test/performance/browser_startup_content.js
+++ b/browser/base/content/test/performance/browser_startup_content.js
@@ -51,16 +51,17 @@ const whitelist = {
     // Forms and passwords
     "resource://formautofill/FormAutofill.jsm",
     "resource://formautofill/FormAutofillContent.jsm",
 
     // Browser front-end
     "resource:///modules/ContentLinkHandler.jsm",
     "resource:///modules/ContentMetaHandler.jsm",
     "resource:///modules/PageStyleHandler.jsm",
+    "resource:///modules/LightweightThemeChildListener.jsm",
     "resource://gre/modules/BrowserUtils.jsm",
     "resource://gre/modules/E10SUtils.jsm",
     "resource://gre/modules/PrivateBrowsingUtils.jsm",
     "resource://gre/modules/ReaderMode.jsm",
     "resource://gre/modules/RemotePageManager.jsm",
 
     // Pocket
     "chrome://pocket/content/AboutPocket.jsm",
rename from browser/modules/LightweightThemeChildHelper.jsm
rename to browser/modules/LightweightThemeChildListener.jsm
--- a/browser/modules/LightweightThemeChildHelper.jsm
+++ b/browser/modules/LightweightThemeChildListener.jsm
@@ -1,71 +1,82 @@
 /* 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";
 
-ChromeUtils.import("resource://gre/modules/Services.jsm");
-
-var EXPORTED_SYMBOLS = ["LightweightThemeChildHelper"];
+/**
+ * LightweightThemeChildListener forwards theme updates from LightweightThemeConsumer to
+ * the whitelisted in-content pages
+ */
+class LightweightThemeChildListener {
+  constructor() {
+    /**
+     * The pages that will receive theme updates
+     */
+    this.whitelist = new Set([
+      "about:home",
+      "about:newtab",
+      "about:welcome",
+    ]);
 
-/**
- * LightweightThemeChildHelper forwards theme data to in-content pages.
- */
-var LightweightThemeChildHelper = {
-  listener: null,
-  whitelist: [],
+    /**
+     * The last theme data received from LightweightThemeConsumer
+     */
+    this._lastData = null;
+  }
 
   /**
-   * Listen to theme updates for the current process
-   * @param {Array} whitelist The pages that can receive theme updates.
+   * Handles theme updates from the parent process
+   * @param {Object} message from the parent process.
    */
-  listen(whitelist) {
-    if (!this.listener) {
-      // Clone the whitelist to avoid leaking the global the whitelist
-      // originates from.
-      this.whitelist = new Set([...whitelist]);
-      this.listener = ({ changedKeys }) => {
-        if (changedKeys.find(change => change.startsWith("theme/"))) {
-          this._updateProcess(changedKeys);
-        }
-      };
-      Services.cpmm.sharedData.addEventListener("change", this.listener);
+  receiveMessage({ name, data, target }) {
+    if (name == "LightweightTheme:Update") {
+      this._lastData = data;
+      this._update(data, target.content);
     }
-  },
+  }
 
   /**
-   * Update the theme data for the whole process
-   * @param {Array} changedKeys The sharedData keys that were changed.
+   * Handles events from the content scope.
+   * @param {Object} event The received event.
    */
-  _updateProcess(changedKeys) {
-    const windowEnumerator = Services.ww.getWindowEnumerator();
-    while (windowEnumerator.hasMoreElements()) {
-      const window = windowEnumerator.getNext().QueryInterface(Ci.nsIDOMWindow);
-      const tabChildGlobal = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                                   .getInterface(Ci.nsIDocShell)
-                                   .sameTypeRootTreeItem
-                                   .QueryInterface(Ci.nsIInterfaceRequestor)
-                                   .getInterface(Ci.nsIContentFrameMessageManager);
-      const {chromeOuterWindowID, content} = tabChildGlobal;
-      if (changedKeys.includes(`theme/${chromeOuterWindowID}`) &&
-          content && this.whitelist.has(content.document.documentURI)) {
-        this.update(chromeOuterWindowID, content);
-      }
+  handleEvent(event) {
+    const content = event.originalTarget.defaultView;
+    if (content != content.top) {
+      return;
+    }
+
+    if (event.type == "LightweightTheme:Support") {
+      this._update(this._lastData, content);
     }
-  },
+  }
+
+  /**
+   * Checks if a given global is allowed to receive theme updates
+   * @param {Object} content The global to check against.
+   * @returns {boolean} Whether the global is allowed to receive updates.
+   */
+  _isContentWhitelisted(content) {
+    return this.whitelist.has(content.document.documentURI);
+  }
 
   /**
    * Forward the theme data to the page.
-   * @param {Object} outerWindowID The outerWindowID the parent process window has.
+   * @param {Object} data The theme data to forward
    * @param {Object} content The receiving global
    */
-  update(outerWindowID, content) {
-    const event = Cu.cloneInto({
-      detail: {
-        data: Services.cpmm.sharedData.get(`theme/${outerWindowID}`)
-      },
-    }, content);
-    content.dispatchEvent(new content.CustomEvent("LightweightTheme:Set",
-                                                  event));
-  },
-};
+  _update(data, content) {
+    if (this._isContentWhitelisted(content)) {
+      const event = Cu.cloneInto({
+        detail: {
+          type: "LightweightTheme:Update",
+          data,
+        },
+      }, content);
+      content.dispatchEvent(new content.CustomEvent("LightweightTheme:Set",
+                                                    event));
+    }
+  }
+}
+
+var EXPORTED_SYMBOLS = ["LightweightThemeChildListener"];
--- a/browser/modules/moz.build
+++ b/browser/modules/moz.build
@@ -65,17 +65,17 @@ with Files("ContentWebRTC.jsm"):
     BUG_COMPONENT = ("Firefox", "Device Permissions")
 
 with Files("ExtensionsUI.jsm"):
     BUG_COMPONENT = ("WebExtensions", "General")
 
 with Files("LaterRun.jsm"):
     BUG_COMPONENT = ("Firefox", "Tours")
 
-with Files("LightweightThemeChildHelper.jsm"):
+with Files("LightweightThemeChildListener.jsm"):
     BUG_COMPONENT = ("WebExtensions", "Themes")
 
 with Files("LightWeightThemeWebInstallListener.jsm"):
     BUG_COMPONENT = ("Firefox", "Theme")
 
 with Files("OpenInTabsUtils.jsm"):
     BUG_COMPONENT = ("Firefox", "Tabbed Browser")
 
@@ -155,17 +155,17 @@ EXTRA_JS_MODULES += [
     'ContentWebRTC.jsm',
     'ContextMenu.jsm',
     'ExtensionsUI.jsm',
     'Feeds.jsm',
     'FormSubmitObserver.jsm',
     'FormValidationHandler.jsm',
     'HomePage.jsm',
     'LaterRun.jsm',
-    'LightweightThemeChildHelper.jsm',
+    'LightweightThemeChildListener.jsm',
     'LightWeightThemeWebInstallListener.jsm',
     'NetErrorContent.jsm',
     'OpenInTabsUtils.jsm',
     'PageActions.jsm',
     'PageInfoListener.jsm',
     'PageStyleHandler.jsm',
     'PermissionUI.jsm',
     'PingCentre.jsm',
--- a/toolkit/components/extensions/test/browser/browser_ext_themes_ntp_colors.js
+++ b/toolkit/components/extensions/test/browser/browser_ext_themes_ntp_colors.js
@@ -29,18 +29,16 @@ async function test_ntp_theme(theme, isB
     return {
       originalBackground: content.getComputedStyle(doc.body).backgroundColor,
       originalColor: content.getComputedStyle(doc.querySelector(".outer-wrapper")).color,
     };
   });
 
   await extension.startup();
 
-  Services.ppmm.sharedData.flush();
-
   await ContentTask.spawn(browser, {
     isBrightText,
     background: hexToCSS(theme.colors.ntp_background),
     color: hexToCSS(theme.colors.ntp_text),
   }, function({isBrightText, background, color}) {
     let doc = content.document;
     ok(doc.body.hasAttribute("lwt-newtab"),
        "New tab page should have lwt-newtab attribute");
@@ -50,18 +48,16 @@ async function test_ntp_theme(theme, isB
     is(content.getComputedStyle(doc.body).backgroundColor, background,
        "New tab page background should be set.");
     is(content.getComputedStyle(doc.querySelector(".outer-wrapper")).color, color,
        "New tab page text color should be set.");
   });
 
   await extension.unload();
 
-  Services.ppmm.sharedData.flush();
-
   await ContentTask.spawn(browser, {
     originalBackground,
     originalColor,
   }, function({originalBackground, originalColor}) {
     let doc = content.document;
     ok(!doc.body.hasAttribute("lwt-newtab"),
        "New tab page should not have lwt-newtab attribute");
     ok(!doc.body.hasAttribute("lwt-newtab-brighttext"),
--- a/toolkit/components/extensions/test/browser/browser_ext_themes_ntp_colors_perwindow.js
+++ b/toolkit/components/extensions/test/browser/browser_ext_themes_ntp_colors_perwindow.js
@@ -5,17 +5,16 @@
 /**
  * Test whether a given browser has the new tab page theme applied
  * @param {Object} browser to test against
  * @param {Object} theme that is applied
  * @param {boolean} isBrightText whether the brighttext attribute should be set
  * @returns {Promise} The task as a promise
  */
 function test_ntp_theme(browser, theme, isBrightText) {
-  Services.ppmm.sharedData.flush();
   return ContentTask.spawn(browser, {
     isBrightText,
     background: hexToCSS(theme.colors.ntp_background),
     color: hexToCSS(theme.colors.ntp_text),
   }, function({isBrightText, background, color}) {
     let doc = content.document;
     ok(doc.body.hasAttribute("lwt-newtab"),
        "New tab page should have lwt-newtab attribute");
@@ -30,17 +29,16 @@ function test_ntp_theme(browser, theme, 
 }
 
 /**
  * Test whether a given browser has the default theme applied
  * @param {Object} browser to test against
  * @returns {Promise} The task as a promise
  */
 function test_ntp_default_theme(browser) {
-  Services.ppmm.sharedData.flush();
   return ContentTask.spawn(browser, {
     background: hexToCSS("#F9F9FA"),
     color: hexToCSS("#0C0C0D"),
   }, function({background, color}) {
     let doc = content.document;
     ok(!doc.body.hasAttribute("lwt-newtab"),
        "New tab page should not have lwt-newtab attribute");
     ok(!doc.body.hasAttribute("lwt-newtab-brighttext"),
--- a/toolkit/modules/LightweightThemeConsumer.jsm
+++ b/toolkit/modules/LightweightThemeConsumer.jsm
@@ -107,69 +107,82 @@ ChromeUtils.defineModuleGetter(this, "Th
 ChromeUtils.defineModuleGetter(this, "ThemeVariableMap",
   "resource:///modules/ThemeVariableMap.jsm");
 ChromeUtils.defineModuleGetter(this, "LightweightThemeImageOptimizer",
   "resource://gre/modules/addons/LightweightThemeImageOptimizer.jsm");
 
 function LightweightThemeConsumer(aDocument) {
   this._doc = aDocument;
   this._win = aDocument.defaultView;
-  this._winId = this._win
-    .QueryInterface(Ci.nsIInterfaceRequestor)
-    .getInterface(Ci.nsIDOMWindowUtils)
-    .outerWindowID;
 
   Services.obs.addObserver(this, "lightweight-theme-styling-update");
 
   var temp = {};
   ChromeUtils.import("resource://gre/modules/LightweightThemeManager.jsm", temp);
   this._update(temp.LightweightThemeManager.currentThemeForDisplay);
 
   this._win.addEventListener("resolutionchange", this);
   this._win.addEventListener("unload", this, { once: true });
+  this._win.addEventListener("EndSwapDocShells", this, true);
+  this._win.messageManager.addMessageListener("LightweightTheme:Request", this);
 
   let darkThemeMediaQuery = this._win.matchMedia("(-moz-system-dark-theme)");
   darkThemeMediaQuery.addListener(temp.LightweightThemeManager);
   temp.LightweightThemeManager.systemThemeChanged(darkThemeMediaQuery);
 }
 
 LightweightThemeConsumer.prototype = {
   _lastData: null,
   // Whether a lightweight theme is enabled.
   _active: false,
 
   observe(aSubject, aTopic, aData) {
     if (aTopic != "lightweight-theme-styling-update")
       return;
 
+    const { outerWindowID } = this._win
+      .QueryInterface(Ci.nsIInterfaceRequestor)
+      .getInterface(Ci.nsIDOMWindowUtils);
+
     let parsedData = JSON.parse(aData);
     if (!parsedData) {
       parsedData = { theme: null };
     }
 
-    if (parsedData.window && parsedData.window !== this._winId) {
+    if (parsedData.window && parsedData.window !== outerWindowID) {
       return;
     }
 
     this._update(parsedData.theme);
   },
 
+  receiveMessage({ name, target }) {
+    if (name == "LightweightTheme:Request") {
+      let contentThemeData = _getContentProperties(this._doc, this._active, this._lastData);
+      target.messageManager.sendAsyncMessage("LightweightTheme:Update", contentThemeData);
+    }
+  },
+
   handleEvent(aEvent) {
     switch (aEvent.type) {
       case "resolutionchange":
         if (this._active) {
           this._update(this._lastData);
         }
         break;
       case "unload":
         Services.obs.removeObserver(this, "lightweight-theme-styling-update");
-        Services.ppmm.sharedData.delete(`theme/${this._winId}`);
         this._win.removeEventListener("resolutionchange", this);
+        this._win.removeEventListener("EndSwapDocShells", this, true);
         this._win = this._doc = null;
         break;
+      case "EndSwapDocShells":
+        let contentThemeData = _getContentProperties(this._doc, this._active, this._lastData);
+        aEvent.target.messageManager.sendAsyncMessage("LightweightTheme:Update", contentThemeData);
+        break;
     }
   },
 
   _update(aData) {
     this._lastData = aData;
     if (aData) {
       aData = LightweightThemeImageOptimizer.optimize(aData, this._win.screen);
     }
@@ -213,17 +226,21 @@ LightweightThemeConsumer.prototype = {
     }
 
     if (active && aData.footerURL)
       root.setAttribute("lwthemefooter", "true");
     else
       root.removeAttribute("lwthemefooter");
 
     let contentThemeData = _getContentProperties(this._doc, active, aData);
-    Services.ppmm.sharedData.set(`theme/${this._winId}`, contentThemeData);
+
+    let browserMessageManager = this._win.getGroupMessageManager("browsers");
+    browserMessageManager.broadcastAsyncMessage(
+      "LightweightTheme:Update", contentThemeData
+    );
   }
 };
 
 function _getContentProperties(doc, active, data) {
   if (!active) {
     return {};
   }
   let properties = {};