Bug 1480244: Part 5 - Run most framescripts in shared scope. r=mconley draft
authorKris Maglione <maglione.k@gmail.com>
Fri, 10 Aug 2018 13:58:18 -0700
changeset 828433 bc17120defb1e66071339f11a7e9fff3d47a95da
parent 828432 be076323bc70bf5d80261efe1504b4ae54497f98
push id118679
push usermaglione.k@gmail.com
push dateFri, 10 Aug 2018 21:19:41 +0000
reviewersmconley
bugs1480244, 1472491
milestone63.0a1
Bug 1480244: Part 5 - Run most framescripts in shared scope. r=mconley Creating non-shared scopes for frame scripts is fairly expensive. After these changes it's even more expensive. However, many frame scripts have no use for the shared scopes at all. Run-once scripts which execute in closures, for instance, make no use of them. And after bug 1472491, neither do most of our default frame scripts. MozReview-Commit-ID: 9PK7bYdQ0yh
browser/base/content/browser.js
browser/base/content/webext-panels.js
browser/components/extensions/ExtensionPopups.jsm
browser/components/extensions/test/browser/browser_ext_find.js
browser/components/sessionstore/SessionStore.jsm
browser/extensions/formautofill/bootstrap.js
browser/extensions/onboarding/bootstrap.js
mobile/android/chrome/content/browser.js
services/sync/tps/extensions/tps/resource/modules/tabs.jsm
toolkit/components/extensions/ExtensionParent.jsm
toolkit/components/extensions/ExtensionXPCShellUtils.jsm
toolkit/components/extensions/test/xpcshell/test_ext_content_security_policy.js
toolkit/components/extensions/test/xpcshell/test_ext_permissions.js
toolkit/components/processsingleton/MainProcessSingleton.js
toolkit/mozapps/extensions/addonManager.js
toolkit/mozapps/extensions/content/extensions.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1312,18 +1312,18 @@ var gBrowserInit = {
     LanguageDetectionListener.init();
     BrowserOnClick.init();
     FeedHandler.init();
     TrackingProtection.init();
     CaptivePortalWatcher.init();
     ZoomUI.init(window);
 
     let mm = window.getGroupMessageManager("browsers");
-    mm.loadFrameScript("chrome://browser/content/tab-content.js", true);
-    mm.loadFrameScript("chrome://browser/content/content.js", true);
+    mm.loadFrameScript("chrome://browser/content/tab-content.js", true, true);
+    mm.loadFrameScript("chrome://browser/content/content.js", true, true);
     mm.loadFrameScript("chrome://global/content/content-HybridContentTelemetry.js", true);
 
     window.messageManager.addMessageListener("Browser:LoadURI", RedirectLoad);
 
     if (!gMultiProcessBrowser) {
       // There is a Content:Click message manually sent from content.
       Services.els.addSystemEventListener(gBrowser.tabpanels, "click",
         contentAreaClick, true);
@@ -5202,17 +5202,17 @@ const AccessibilityRefreshBlocker = {
       Services.prefs.removeObserver(this.PREF, this);
     }
   },
 
   loadFrameScript() {
     if (!this._loaded) {
       this._loaded = true;
       let mm = window.getGroupMessageManager("browsers");
-      mm.loadFrameScript("chrome://browser/content/content-refreshblocker.js", true);
+      mm.loadFrameScript("chrome://browser/content/content-refreshblocker.js", true, true);
     }
   }
 };
 
 var TabsProgressListener = {
   onStateChange(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
     // Collect telemetry data about tab load times.
     if (aWebProgress.isTopLevel && (!aRequest.originalURI || aRequest.originalURI.spec.scheme != "about")) {
--- a/browser/base/content/webext-panels.js
+++ b/browser/base/content/webext-panels.js
@@ -59,22 +59,22 @@ function getBrowser(sidebar) {
   } else {
     readyPromise = Promise.resolve();
   }
 
   stack.appendChild(browser);
   document.documentElement.appendChild(stack);
 
   return readyPromise.then(() => {
-    browser.messageManager.loadFrameScript("chrome://browser/content/content.js", false);
+    browser.messageManager.loadFrameScript("chrome://browser/content/content.js", false, true);
     ExtensionParent.apiManager.emit("extension-browser-inserted", browser);
 
     if (sidebar.browserStyle) {
       browser.messageManager.loadFrameScript(
-        "chrome://extensions/content/ext-browser-content.js", false);
+        "chrome://extensions/content/ext-browser-content.js", false, true);
 
       browser.messageManager.sendAsyncMessage("Extension:InitBrowser", {
         stylesheets: ExtensionParent.extensionStylesheets,
       });
     }
     return browser;
   });
 }
--- a/browser/components/extensions/ExtensionPopups.jsm
+++ b/browser/components/extensions/ExtensionPopups.jsm
@@ -306,20 +306,20 @@ class BasePopup {
       return setupBrowser(browser);
     }
 
     return readyPromise.then(() => {
       setupBrowser(browser);
       let mm = browser.messageManager;
 
       // Sets the context information for context menus.
-      mm.loadFrameScript("chrome://browser/content/content.js", true);
+      mm.loadFrameScript("chrome://browser/content/content.js", true, true);
 
       mm.loadFrameScript(
-        "chrome://extensions/content/ext-browser-content.js", false);
+        "chrome://extensions/content/ext-browser-content.js", false, true);
 
       mm.sendAsyncMessage("Extension:InitBrowser", {
         allowScriptsToClose: true,
         blockParser: this.blockParser,
         fixedWidth: this.fixedWidth,
         maxWidth: 800,
         maxHeight: 600,
         stylesheets: this.STYLESHEETS,
--- a/browser/components/extensions/test/browser/browser_ext_find.js
+++ b/browser/components/extensions/test/browser/browser_ext_find.js
@@ -137,17 +137,17 @@ add_task(async function testDuplicatePin
   await extension.startup();
   let rectData = await extension.awaitMessage("test:find:WebExtensionFinished");
   let {top, left} = rectData[5].rectsAndTexts.rectList[0];
   await extension.unload();
 
   let {selectedBrowser} = gBrowser;
 
   let frameScriptUrl = `data:,(${frameScript}).call(this)`;
-  selectedBrowser.messageManager.loadFrameScript(frameScriptUrl, false);
+  selectedBrowser.messageManager.loadFrameScript(frameScriptUrl, false, true);
   let message = await waitForMessage(selectedBrowser.messageManager, "test:find:selectionTest");
 
   info("Test that text was highlighted properly.");
   is(message.data.text, "bananA", `The text that was highlighted: - Expected: bananA, Actual: ${message.data.text}`);
 
   info("Test that rectangle data returned from the search matches the highlighted result.");
   is(message.data.rect.top, top, `rect.top: - Expected: ${message.data.rect.top}, Actual: ${top}`);
   is(message.data.rect.left, left, `rect.left: - Expected: ${message.data.rect.left}, Actual: ${left}`);
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -1096,17 +1096,17 @@ var SessionStoreInternal = {
 
     let mm = aWindow.getGroupMessageManager("browsers");
     MESSAGES.forEach(msg => {
       let listenWhenClosed = CLOSED_MESSAGES.has(msg);
       mm.addMessageListener(msg, this, listenWhenClosed);
     });
 
     // Load the frame script after registering listeners.
-    mm.loadFrameScript("chrome://browser/content/content-sessionStore.js", true);
+    mm.loadFrameScript("chrome://browser/content/content-sessionStore.js", true, true);
 
     // and create its data object
     this._windows[aWindow.__SSi] = { tabs: [], selected: 0, _closedTabs: [], busy: false };
 
     if (PrivateBrowsingUtils.isWindowPrivate(aWindow))
       this._windows[aWindow.__SSi].isPrivate = true;
     if (!this._isWindowLoaded(aWindow))
       this._windows[aWindow.__SSi]._restoring = true;
--- a/browser/extensions/formautofill/bootstrap.js
+++ b/browser/extensions/formautofill/bootstrap.js
@@ -126,17 +126,17 @@ function startup(data) {
   Services.mm.addMessageListener("FormAutoComplete:MaybeOpenPopup", onMaybeOpenPopup);
 
   formAutofillParent.init().catch(Cu.reportError);
   /* eslint-disable no-unused-vars */
   Services.ppmm.loadProcessScript("data:,new " + function() {
     ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
   }, true);
   /* eslint-enable no-unused-vars */
-  Services.mm.loadFrameScript("chrome://formautofill/content/FormAutofillFrameScript.js", true);
+  Services.mm.loadFrameScript("chrome://formautofill/content/FormAutofillFrameScript.js", true, true);
 }
 
 function shutdown() {
   resProto.setSubstitution(RESOURCE_HOST, null);
 
   Services.mm.removeMessageListener("FormAutoComplete:MaybeOpenPopup", onMaybeOpenPopup);
 
   let enumerator = Services.wm.getEnumerator("navigator:browser");
--- a/browser/extensions/onboarding/bootstrap.js
+++ b/browser/extensions/onboarding/bootstrap.js
@@ -169,17 +169,17 @@ function initContentMessageListener() {
 /**
  * onBrowserReady - Continues startup of the add-on after browser is ready.
  */
 function onBrowserReady() {
   waitingForBrowserReady = false;
 
   OnboardingTourType.check();
   OnboardingTelemetry.init(startupData);
-  Services.mm.loadFrameScript("resource://onboarding/onboarding.js", true);
+  Services.mm.loadFrameScript("resource://onboarding/onboarding.js", true, true);
   initContentMessageListener();
 }
 
 /**
  * observe - nsIObserver callback to handle various browser notifications.
  */
 function observe(subject, topic, data) {
   switch (topic) {
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -502,20 +502,20 @@ var BrowserApp = {
         let logsDir = OS.Path.join(downloadsDir, "memory-reports");
         yield OS.File.removeDir(logsDir);
       });
     });
 
     // Don't delay loading content.js because when we restore reader mode tabs,
     // we require the reader mode scripts in content.js right away.
     let mm = window.getGroupMessageManager("browsers");
-    mm.loadFrameScript("chrome://browser/content/content.js", true);
+    mm.loadFrameScript("chrome://browser/content/content.js", true, true);
 
     // Listen to manifest messages
-    mm.loadFrameScript("chrome://global/content/manifestMessages.js", true);
+    mm.loadFrameScript("chrome://global/content/manifestMessages.js", true, true);
 
     // We can't delay registering WebChannel listeners: if the first page is
     // about:accounts, which can happen when starting the Firefox Account flow
     // from the first run experience, or via the Firefox Account Status
     // Activity, we can and do miss messages from the fxa-content-server.
     // However, we never allow suitably restricted profiles from listening to
     // fxa-content-server messages.
     if (ParentalControls.isAllowed(ParentalControls.MODIFY_ACCOUNTS)) {
--- a/services/sync/tps/extensions/tps/resource/modules/tabs.jsm
+++ b/services/sync/tps/extensions/tps/resource/modules/tabs.jsm
@@ -20,17 +20,17 @@ ChromeUtils.import("resource://tps/logge
 // hence the hackiness here and in BrowserTabs.Add.
 Services
 .mm
 .loadFrameScript("data:application/javascript;charset=utf-8," + encodeURIComponent(`
   Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
   addEventListener("load", function(event) {
     let subframe = event.target != content.document;
     sendAsyncMessage("tps:loadEvent", {subframe: subframe, url: event.target.documentURI});
-  }, true)`), true);
+  }, true)`), true, true);
 
 var BrowserTabs = {
   /**
    * Add
    *
    * Opens a new tab in the current browser window for the
    * given uri. Rejects on error.
    *
--- a/toolkit/components/extensions/ExtensionParent.jsm
+++ b/toolkit/components/extensions/ExtensionParent.jsm
@@ -518,17 +518,17 @@ GlobalManager = {
     }
   },
 
   _onExtensionBrowser(type, browser, additionalData = {}) {
     browser.messageManager.loadFrameScript(`data:,
       Components.utils.import("resource://gre/modules/Services.jsm");
 
       Services.obs.notifyObservers(this, "tab-content-frameloader-created", "");
-    `, false);
+    `, false, true);
 
     let viewType = browser.getAttribute("webextension-view-type");
     if (viewType) {
       let data = {viewType};
 
       let {tabTracker} = apiManager.global;
       Object.assign(data, tabTracker.getBrowserData(browser), additionalData);
 
--- a/toolkit/components/extensions/ExtensionXPCShellUtils.jsm
+++ b/toolkit/components/extensions/ExtensionXPCShellUtils.jsm
@@ -30,17 +30,17 @@ ChromeUtils.defineModuleGetter(this, "Se
 ChromeUtils.defineModuleGetter(this, "TestUtils",
                                "resource://testing-common/TestUtils.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "Management", () => {
   const {Management} = ChromeUtils.import("resource://gre/modules/Extension.jsm", {});
   return Management;
 });
 
-Services.mm.loadFrameScript("chrome://global/content/browser-content.js", true);
+Services.mm.loadFrameScript("chrome://global/content/browser-content.js", true, true);
 
 ActorManagerParent.flush();
 
 /* exported ExtensionTestUtils */
 
 const {
   promiseDocumentLoaded,
   promiseEvent,
@@ -163,17 +163,17 @@ class ContentPage {
   }
 
   sendMessage(msg, data) {
     return MessageChannel.sendMessage(this.browser.messageManager, msg, data);
   }
 
   loadFrameScript(func) {
     let frameScript = `data:text/javascript,(${encodeURI(func)}).call(this)`;
-    this.browser.messageManager.loadFrameScript(frameScript, true);
+    this.browser.messageManager.loadFrameScript(frameScript, true, true);
   }
 
   addFrameScriptHelper(func) {
     let frameScript = `data:text/javascript,${encodeURI(func)}`;
     this.browser.messageManager.loadFrameScript(frameScript, false, true);
   }
 
   async loadURL(url, redirectUrl = undefined) {
@@ -673,17 +673,17 @@ var ExtensionTestUtils = {
     this.fetchScopes = new Map();
 
     // We need to load at least one frame script into every message
     // manager to ensure that the scriptable wrapper for its global gets
     // created before we try to access it externally. If we don't, we
     // fail sanity checks on debug builds the first time we try to
     // create a wrapper, because we should never have a global without a
     // cached wrapper.
-    Services.mm.loadFrameScript("data:text/javascript,//", true);
+    Services.mm.loadFrameScript("data:text/javascript,//", true, true);
 
 
     let tmpD = this.profileDir.clone();
     tmpD.append("tmp");
     tmpD.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
 
     let dirProvider = {
       getFile(prop, persistent) {
--- a/toolkit/components/extensions/test/xpcshell/test_ext_content_security_policy.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_content_security_policy.js
@@ -102,17 +102,17 @@ async function testPolicy(customCSP = nu
       function getCSP() {
         let {cspJSON} = Cu.getObjectPrincipal(win);
         return win.wrappedJSObject.JSON.parse(cspJSON);
       }
       Cu.exportFunction(getCSP, win, {defineAs: "getCSP"});
     }, true);
   }
   let frameScriptURL = `data:,(${encodeURI(frameScript)}).call(this)`;
-  Services.mm.loadFrameScript(frameScriptURL, true);
+  Services.mm.loadFrameScript(frameScriptURL, true, true);
 
 
   info(`Testing CSP for policy: ${content_security_policy}`);
 
   await extension.startup();
 
   baseURL = await extension.awaitMessage("base-url");
 
--- a/toolkit/components/extensions/test/xpcshell/test_ext_permissions.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_permissions.js
@@ -31,17 +31,17 @@ function frameScript() {
     },
   });
 }
 
 async function withHandlingUserInput(extension, fn) {
   let {messageManager} = extension.extension.groupFrameLoader;
 
   if (!extensionHandlers.has(extension)) {
-    messageManager.loadFrameScript(`data:,(${frameScript}).call(this)`, false);
+    messageManager.loadFrameScript(`data:,(${frameScript}).call(this)`, false, true);
     extensionHandlers.add(extension);
   }
 
   await MessageChannel.sendMessage(messageManager, "ExtensionTest:HandleUserInput", true);
   await fn();
   await MessageChannel.sendMessage(messageManager, "ExtensionTest:HandleUserInput", false);
 }
 
--- a/toolkit/components/processsingleton/MainProcessSingleton.js
+++ b/toolkit/components/processsingleton/MainProcessSingleton.js
@@ -60,18 +60,18 @@ MainProcessSingleton.prototype = {
   observe(subject, topic, data) {
     switch (topic) {
     case "app-startup": {
       Services.obs.addObserver(this, "xpcom-shutdown");
       Services.obs.addObserver(this, "document-element-inserted");
 
       // Load this script early so that console.* is initialized
       // before other frame scripts.
-      Services.mm.loadFrameScript("chrome://global/content/browser-content.js", true);
-      Services.ppmm.loadProcessScript("chrome://global/content/process-content.js", true);
+      Services.mm.loadFrameScript("chrome://global/content/browser-content.js", true, true);
+      Services.ppmm.loadProcessScript("chrome://global/content/process-content.js", true, true);
       Services.mm.addMessageListener("Search:AddEngine", this.addSearchEngine);
       Services.ppmm.loadProcessScript("resource:///modules/ContentObservers.js", true);
       break;
     }
 
     case "document-element-inserted":
       // Set up Custom Elements for XUL windows before anything else happens
       // in the document. Anything loaded here should be considered part of
--- a/toolkit/mozapps/extensions/addonManager.js
+++ b/toolkit/mozapps/extensions/addonManager.js
@@ -38,17 +38,17 @@ ChromeUtils.import("resource://gre/modul
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 var gSingleton = null;
 
 function amManager() {
   ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
   /* globals AddonManagerPrivate*/
 
-  Services.mm.loadFrameScript(CHILD_SCRIPT, true);
+  Services.mm.loadFrameScript(CHILD_SCRIPT, true, true);
   Services.mm.addMessageListener(MSG_INSTALL_ENABLED, this);
   Services.mm.addMessageListener(MSG_INSTALL_ADDON, this);
   Services.mm.addMessageListener(MSG_PROMISE_REQUEST, this);
   Services.mm.addMessageListener(MSG_INSTALL_CLEANUP, this);
   Services.mm.addMessageListener(MSG_ADDON_EVENT_REQ, this);
 
   Services.obs.addObserver(this, "message-manager-close");
   Services.obs.addObserver(this, "message-manager-disconnect");
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -3089,18 +3089,18 @@ var gDetailView = {
         // removed from the document in the meantime (e.g. due to a rapid sequence
         // of addon reload), ensure that the stack is also removed and return null.
         stack.remove();
         resolve(null);
         return;
       }
 
       mm.loadFrameScript("chrome://extensions/content/ext-browser-content.js",
-                         false);
-      mm.loadFrameScript("chrome://browser/content/content.js", false);
+                         false, true);
+      mm.loadFrameScript("chrome://browser/content/content.js", false, true);
       mm.addMessageListener("Extension:BrowserContentLoaded", messageListener);
       mm.addMessageListener("Extension:BrowserResized", messageListener);
 
       let browserOptions = {
         fixedWidth: true,
         isInline: true,
       };