Backed out changeset 530bcc00246e (bug 1576918) for browser-chrome failures on browser_dismissFooter.js. CLOSED TREE
authorCsoregi Natalia <ncsoregi@mozilla.com>
Thu, 24 Oct 2019 23:51:59 +0300
changeset 498919 e3ce16ac9143028c9f8353bff57a63aebcd5d127
parent 498918 5eb5f44dcf96cedbfeef132741fffc41dc329756
child 498920 122109471f12efe05c36ca28a0ad7458dd01d122
push id36732
push userdluca@mozilla.com
push dateFri, 25 Oct 2019 09:55:46 +0000
treeherdermozilla-central@86d60b2e9638 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1576918
milestone72.0a1
backs out530bcc00246e68a35fe03c19269d4282b9a0e8af
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 530bcc00246e (bug 1576918) for browser-chrome failures on browser_dismissFooter.js. CLOSED TREE
browser/actors/PageStyleChild.jsm
browser/actors/PageStyleParent.jsm
browser/actors/moz.build
browser/base/content/browser.js
browser/base/content/test/general/browser_page_style_menu.js
browser/base/content/test/general/browser_page_style_menu_update.js
browser/base/content/test/general/head.js
browser/components/BrowserGlue.jsm
--- a/browser/actors/PageStyleChild.jsm
+++ b/browser/actors/PageStyleChild.jsm
@@ -1,95 +1,108 @@
 /* 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";
 
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 var EXPORTED_SYMBOLS = ["PageStyleChild"];
 
-class PageStyleChild extends JSWindowActorChild {
-  handleEvent(event) {
-    // On page show, tell the parent all of the stylesheets this document has.
-    if (event.type == "pageshow") {
-      // If we are in the topmost browsing context,
-      // delete the stylesheets from the previous page.
-      if (this.browsingContext.top === this.browsingContext) {
-        this.sendAsyncMessage("PageStyle:Clear");
-      }
+const { ActorChild } = ChromeUtils.import(
+  "resource://gre/modules/ActorChild.jsm"
+);
+
+class PageStyleChild extends ActorChild {
+  getViewer(content) {
+    return content.docShell.contentViewer;
+  }
 
-      let window = event.target.ownerGlobal;
-      window.requestIdleCallback(() => {
-        if (!window || window.closed) {
-          return;
-        }
-        let styleSheets = Array.from(this.document.styleSheets);
-        let filteredStyleSheets = this._filterStyleSheets(styleSheets, window);
+  sendStyleSheetInfo(mm) {
+    let content = mm.content;
+    content.requestIdleCallback(() => {
+      let filteredStyleSheets = this._filterStyleSheets(
+        this.getAllStyleSheets(content),
+        content
+      );
 
-        this.sendAsyncMessage("PageStyle:Add", {
-          filteredStyleSheets,
-          authorStyleDisabled: this.docShell.contentViewer.authorStyleDisabled,
-          preferredStyleSheetSet: this.document.preferredStyleSheetSet,
-        });
+      mm.sendAsyncMessage("PageStyle:StyleSheets", {
+        filteredStyleSheets,
+        authorStyleDisabled: this.getViewer(content).authorStyleDisabled,
+        preferredStyleSheetSet: content.document.preferredStyleSheetSet,
       });
-    }
+    });
+  }
+
+  getAllStyleSheets(frameset) {
+    let selfSheets = Array.from(frameset.document.styleSheets);
+    let subSheets = Array.from(frameset.frames, frame =>
+      this.getAllStyleSheets(frame)
+    );
+    return selfSheets.concat(...subSheets);
   }
 
   receiveMessage(msg) {
+    let content = msg.target.content;
     switch (msg.name) {
-      // Sent when the page's enabled style sheet is changed.
       case "PageStyle:Switch":
-        this.docShell.contentViewer.authorStyleDisabled = false;
-        this._switchStylesheet(msg.data.title);
+        this.getViewer(content).authorStyleDisabled = false;
+        this._stylesheetSwitchAll(content, msg.data.title);
+        break;
+
+      case "PageStyle:Disable":
+        this.getViewer(content).authorStyleDisabled = true;
         break;
-      // Sent when "No Style" is chosen.
-      case "PageStyle:Disable":
-        this.docShell.contentViewer.authorStyleDisabled = true;
-        break;
+    }
+
+    this.sendStyleSheetInfo(msg.target);
+  }
+
+  handleEvent(event) {
+    let win = event.target.ownerGlobal;
+    if (win != win.top) {
+      return;
+    }
+
+    let mm = win.docShell.messageManager;
+    this.sendStyleSheetInfo(mm);
+  }
+
+  _stylesheetSwitchAll(frameset, title) {
+    if (!title || this._stylesheetInFrame(frameset, title)) {
+      this._stylesheetSwitchFrame(frameset, title);
+    }
+
+    for (let i = 0; i < frameset.frames.length; i++) {
+      // Recurse into sub-frames.
+      this._stylesheetSwitchAll(frameset.frames[i], title);
     }
   }
 
-  /**
-   * Switch the stylesheet so that only the sheet with the given title is enabled.
-   */
-  _switchStylesheet(title) {
-    let docStyleSheets = this.document.styleSheets;
+  _stylesheetSwitchFrame(frame, title) {
+    var docStyleSheets = frame.document.styleSheets;
 
-    // Does this doc contain a stylesheet with this title?
-    // If not, it's a subframe's stylesheet that's being changed,
-    // so no need to disable stylesheets here.
-    let docContainsStyleSheet = false;
-    for (let docStyleSheet of docStyleSheets) {
-      if (docStyleSheet.title === title) {
-        docContainsStyleSheet = true;
-        break;
-      }
-    }
-
-    for (let docStyleSheet of docStyleSheets) {
+    for (let i = 0; i < docStyleSheets.length; ++i) {
+      let docStyleSheet = docStyleSheets[i];
       if (docStyleSheet.title) {
-        if (docContainsStyleSheet) {
-          docStyleSheet.disabled = docStyleSheet.title !== title;
-        }
+        docStyleSheet.disabled = docStyleSheet.title != title;
       } else if (docStyleSheet.disabled) {
         docStyleSheet.disabled = false;
       }
     }
   }
 
-  /**
-   * Filter the stylesheets that actually apply to this webpage.
-   * @param styleSheets The list of stylesheets from the document.
-   * @param content     The window object that the webpage lives in.
-   */
+  _stylesheetInFrame(frame, title) {
+    return Array.from(frame.document.styleSheets).some(
+      styleSheet => styleSheet.title == title
+    );
+  }
+
   _filterStyleSheets(styleSheets, content) {
     let result = [];
 
-    // Only stylesheets with a title can act as an alternative stylesheet.
     for (let currentStyleSheet of styleSheets) {
       if (!currentStyleSheet.title) {
         continue;
       }
 
       // Skip any stylesheets that don't match the screen media type.
       if (currentStyleSheet.media.length) {
         let mediaQueryList = currentStyleSheet.media.mediaText;
@@ -97,17 +110,17 @@ class PageStyleChild extends JSWindowAct
           continue;
         }
       }
 
       let URI;
       try {
         if (
           !currentStyleSheet.ownerNode ||
-          // Special-case style nodes, which have no href.
+          // special-case style nodes, which have no href
           currentStyleSheet.ownerNode.nodeName.toLowerCase() != "style"
         ) {
           URI = Services.io.newURI(currentStyleSheet.href);
         }
       } catch (e) {
         if (e.result != Cr.NS_ERROR_MALFORMED_URI) {
           throw e;
         }
deleted file mode 100644
--- a/browser/actors/PageStyleParent.jsm
+++ /dev/null
@@ -1,33 +0,0 @@
-/* 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";
-
-var EXPORTED_SYMBOLS = ["PageStyleParent"];
-
-class PageStyleParent extends JSWindowActorParent {
-  receiveMessage(msg) {
-    // The top browser.
-    let browser = this.browsingContext.top.embedderElement;
-    let permanentKey = browser.permanentKey;
-    let window = browser.ownerGlobal;
-    if (window.closed) {
-      return;
-    }
-    let styleMenu = window.gPageStyleMenu;
-
-    switch (msg.name) {
-      case "PageStyle:Add":
-        if (browser.outerBrowser) {
-          // We are in RDM mode and we probably
-          // want to work with the outer browser.
-          browser = browser.outerBrowser;
-        }
-        styleMenu.addBrowserStyleSheets(msg.data, permanentKey);
-        break;
-      case "PageStyle:Clear":
-        styleMenu.clearBrowserStyleSheets(permanentKey);
-        break;
-    }
-  }
-}
--- a/browser/actors/moz.build
+++ b/browser/actors/moz.build
@@ -36,17 +36,16 @@ FINAL_TARGET_FILES.actors += [
     'FormValidationChild.jsm',
     'FormValidationParent.jsm',
     'LightweightThemeChild.jsm',
     'LinkHandlerChild.jsm',
     'NetErrorChild.jsm',
     'OfflineAppsChild.jsm',
     'PageInfoChild.jsm',
     'PageStyleChild.jsm',
-    'PageStyleParent.jsm',
     'PluginChild.jsm',
     'PluginParent.jsm',
     'PromptParent.jsm',
     'RFPHelperChild.jsm',
     'RFPHelperParent.jsm',
     'SearchTelemetryChild.jsm',
     'SwitchDocumentDirectionChild.jsm',
     'URIFixupChild.jsm',
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1803,16 +1803,17 @@ var gBrowserInit = {
 
     window.addEventListener("AppCommand", HandleAppCommandEvent, true);
 
     // These routines add message listeners. They must run before
     // loading the frame script to ensure that we don't miss any
     // message sent between when the frame script is loaded and when
     // the listener is registered.
     DOMEventHandler.init();
+    gPageStyleMenu.init();
     LanguageDetectionListener.init();
     BrowserOnClick.init();
     CaptivePortalWatcher.init();
     ZoomUI.init(window);
 
     let mm = window.getGroupMessageManager("browsers");
     mm.loadFrameScript("chrome://browser/content/tab-content.js", true, true);
     mm.loadFrameScript("chrome://browser/content/content.js", true, true);
@@ -7724,38 +7725,27 @@ var gPageStyleMenu = {
   //   the current page.
   //
   // preferredStyleSheetSet (bool):
   //   Whether or not the user currently has the "Default" style selected
   //   for the current page.
   //
   _pageStyleSheets: new WeakMap(),
 
-  /**
-   * Add/append styleSheets to the _pageStyleSheets weakmap.
-   * @param styleSheets
-   *        The stylesheets to add, including the preferred
-   *        stylesheet set for this document.
-   * @param permanentKey
-   *        The permanent key of the browser that
-   *        these stylesheets come from.
-   */
-  addBrowserStyleSheets(styleSheets, permanentKey) {
-    let sheetData = this._pageStyleSheets.get(permanentKey);
-    if (!sheetData) {
-      this._pageStyleSheets.set(permanentKey, styleSheets);
-      return;
-    }
-    sheetData.filteredStyleSheets.push(...styleSheets.filteredStyleSheets);
-    sheetData.preferredStyleSheetSet =
-      sheetData.preferredStyleSheetSet || styleSheets.preferredStyleSheetSet;
+  init() {
+    let mm = window.messageManager;
+    mm.addMessageListener("PageStyle:StyleSheets", msg => {
+      if (msg.target.permanentKey) {
+        this._pageStyleSheets.set(msg.target.permanentKey, msg.data);
+      }
+    });
   },
 
   /**
-   * Return an array of Objects representing stylesheets in a
+   * Returns an array of Objects representing stylesheets in a
    * browser. Note that the pageshow event needs to fire in content
    * before this information will be available.
    *
    * @param browser (optional)
    *        The <xul:browser> to search for stylesheets. If omitted, this
    *        defaults to the currently selected tab's browser.
    * @returns Array
    *        An Array of Objects representing stylesheets in the browser.
@@ -7769,20 +7759,16 @@ var gPageStyleMenu = {
 
     let data = this._pageStyleSheets.get(browser.permanentKey);
     if (!data) {
       return [];
     }
     return data.filteredStyleSheets;
   },
 
-  clearBrowserStyleSheets(permanentKey) {
-    this._pageStyleSheets.delete(permanentKey);
-  },
-
   _getStyleSheetInfo(browser) {
     let data = this._pageStyleSheets.get(browser.permanentKey);
     if (!data) {
       return {
         filteredStyleSheets: [],
         authorStyleDisabled: false,
         preferredStyleSheetSet: true,
       };
@@ -7841,66 +7827,24 @@ var gPageStyleMenu = {
     noStyle.setAttribute("checked", styleDisabled);
     persistentOnly.setAttribute("checked", !altStyleSelected && !styleDisabled);
     persistentOnly.hidden = styleSheetInfo.preferredStyleSheetSet
       ? haveAltSheets
       : false;
     sep.hidden = (noStyle.hidden && persistentOnly.hidden) || !haveAltSheets;
   },
 
-  /**
-   * Send a message to all PageStyleParents by walking the BrowsingContext tree.
-   * @param message
-   *        The string message to send to each PageStyleChild.
-   * @param data
-   *        The data to send to each PageStyleChild within the message.
-   */
-  _sendMessageToAll(message, data) {
-    let contextsToVisit = [gBrowser.selectedBrowser.browsingContext];
-    while (contextsToVisit.length) {
-      let currentContext = contextsToVisit.pop();
-      let global = currentContext.currentWindowGlobal;
-
-      if (!global) {
-        continue;
-      }
-
-      let actor = global.getActor("PageStyle");
-      actor.sendAsyncMessage(message, data);
-
-      contextsToVisit.push(...currentContext.getChildren());
-    }
-  },
-
-  /**
-   * Switch the stylesheet of all documents in the current browser.
-   * @param title The title of the stylesheet to switch to.
-   */
   switchStyleSheet(title) {
-    let { permanentKey } = gBrowser.selectedBrowser;
-    let sheetData = this._pageStyleSheets.get(permanentKey);
-    if (sheetData && sheetData.filteredStyleSheets) {
-      sheetData.authorStyleDisabled = false;
-      for (let sheet of sheetData.filteredStyleSheets) {
-        sheet.disabled = sheet.title !== title;
-      }
-    }
-    this._sendMessageToAll("PageStyle:Switch", { title });
-  },
-
-  /**
-   * Disable all stylesheets. Called with View > Page Style > No Style.
-   */
+    let mm = gBrowser.selectedBrowser.messageManager;
+    mm.sendAsyncMessage("PageStyle:Switch", { title });
+  },
+
   disableStyle() {
-    let { permanentKey } = gBrowser.selectedBrowser;
-    let sheetData = this._pageStyleSheets.get(permanentKey);
-    if (sheetData) {
-      sheetData.authorStyleDisabled = true;
-    }
-    this._sendMessageToAll("PageStyle:Disable", {});
+    let mm = gBrowser.selectedBrowser.messageManager;
+    mm.sendAsyncMessage("PageStyle:Disable");
   },
 };
 
 var LanguageDetectionListener = {
   init() {
     window.messageManager.addMessageListener(
       "Translation:DocumentState",
       msg => {
--- a/browser/base/content/test/general/browser_page_style_menu.js
+++ b/browser/base/content/test/general/browser_page_style_menu.js
@@ -10,17 +10,17 @@ const PAGE =
 add_task(async function() {
   let tab = await BrowserTestUtils.openNewForegroundTab(
     gBrowser,
     "about:blank",
     false
   );
   let browser = tab.linkedBrowser;
   await BrowserTestUtils.loadURI(browser, PAGE);
-  await promiseStylesheetsLoaded(tab, 17);
+  await promiseStylesheetsUpdated(browser);
 
   let menupopup = document.getElementById("pageStyleMenu").menupopup;
   gPageStyleMenu.fillPopup(menupopup);
 
   var items = [];
   var current = menupopup.getElementsByTagName("menuseparator")[0];
   while (current.nextElementSibling) {
     current = current.nextElementSibling;
--- a/browser/base/content/test/general/browser_page_style_menu_update.js
+++ b/browser/base/content/test/general/browser_page_style_menu_update.js
@@ -9,18 +9,19 @@ const PAGE =
  */
 add_task(async function() {
   let tab = await BrowserTestUtils.openNewForegroundTab(
     gBrowser,
     "about:blank",
     false
   );
   let browser = tab.linkedBrowser;
+
   await BrowserTestUtils.loadURI(browser, PAGE);
-  await promiseStylesheetsLoaded(tab, 17);
+  await promiseStylesheetsUpdated(browser);
 
   let menupopup = document.getElementById("pageStyleMenu").menupopup;
   gPageStyleMenu.fillPopup(menupopup);
 
   // page_style_sample.html should default us to selecting the stylesheet
   // with the title "6" first.
   let selected = menupopup.querySelector("menuitem[checked='true']");
   is(
@@ -28,16 +29,20 @@ add_task(async function() {
     "6",
     "Should have '6' stylesheet selected by default"
   );
 
   // Now select stylesheet "1"
   let target = menupopup.querySelector("menuitem[label='1']");
   target.click();
 
+  // Now we need to wait for the content process to send its stylesheet
+  // update for the selected tab to the parent.
+  await promiseStylesheetsUpdated(browser);
+
   gPageStyleMenu.fillPopup(menupopup);
   // gPageStyleMenu empties out the menu between opens, so we need
   // to get a new reference to the selected menuitem
   selected = menupopup.querySelector("menuitem[checked='true']");
   is(
     selected.getAttribute("label"),
     "1",
     "Should now have stylesheet 1 selected"
--- a/browser/base/content/test/general/head.js
+++ b/browser/base/content/test/general/head.js
@@ -525,25 +525,23 @@ async function loadBadCertPage(url) {
 
   await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
     content.document.getElementById("exceptionDialogButton").click();
   });
   await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
 }
 
 /**
- * Waits for the stylesheets to be loaded into the browser menu.
+ * Waits for the message from content to update the Page Style menu.
  *
- * @param tab
- *        The tab that contains the webpage we're testing.
- * @param styleSheetCount
- *        How many stylesheets we expect to be loaded.
+ * @param browser
+ *        The <xul:browser> to wait for.
  * @return Promise
  */
-async function promiseStylesheetsLoaded(tab, styleSheetCount) {
-  let styleMenu = tab.ownerGlobal.gPageStyleMenu;
-  let permanentKey = tab.permanentKey;
-
-  await TestUtils.waitForCondition(() => {
-    let menu = styleMenu._pageStyleSheets.get(permanentKey);
-    return menu && menu.filteredStyleSheets.length >= styleSheetCount;
-  }, "waiting for style sheets to load");
+async function promiseStylesheetsUpdated(browser) {
+  await BrowserTestUtils.waitForMessage(
+    browser.messageManager,
+    "PageStyle:StyleSheets"
+  );
+  // Resolve on the next tick of the event loop to give the Page Style
+  // menu code an opportunity to update.
+  await new Promise(resolve => Services.tm.dispatchToMainThread(resolve));
 }
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -99,33 +99,16 @@ let ACTORS = {
   PageInfo: {
     child: {
       moduleURI: "resource:///actors/PageInfoChild.jsm",
     },
 
     allFrames: true,
   },
 
-  PageStyle: {
-    parent: {
-      moduleURI: "resource:///actors/PageStyleParent.jsm",
-    },
-    child: {
-      moduleURI: "resource:///actors/PageStyleChild.jsm",
-      events: {
-        pageshow: {},
-      },
-    },
-
-    // Only matching web pages, as opposed to internal about:, chrome: or
-    // resource: pages. See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns
-    matches: ["*://*/*"],
-    allFrames: true,
-  },
-
   Plugin: {
     parent: {
       moduleURI: "resource:///actors/PluginParent.jsm",
     },
     child: {
       moduleURI: "resource:///actors/PluginChild.jsm",
       events: {
         PluginBindingAttached: { capture: true, wantUntrusted: true },
@@ -325,16 +308,30 @@ let LEGACY_ACTORS = {
       module: "resource:///actors/OfflineAppsChild.jsm",
       events: {
         MozApplicationManifest: {},
       },
       messages: ["OfflineApps:StartFetching"],
     },
   },
 
+  PageStyle: {
+    child: {
+      module: "resource:///actors/PageStyleChild.jsm",
+      group: "browsers",
+      events: {
+        pageshow: {},
+      },
+      messages: ["PageStyle:Switch", "PageStyle:Disable"],
+      // Only matching web pages, as opposed to internal about:, chrome: or
+      // resource: pages. See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns
+      matches: ["*://*/*"],
+    },
+  },
+
   SearchTelemetry: {
     child: {
       module: "resource:///actors/SearchTelemetryChild.jsm",
       events: {
         DOMContentLoaded: {},
         pageshow: { mozSystemGroup: true },
       },
     },