Bug 1320395: Part 3 - Run WebExtensions in their own process type. r?billm,bobowen f?pauljt
MozReview-Commit-ID: FZ4f1Lda5vh
--- a/browser/components/extensions/ext-utils.js
+++ b/browser/components/extensions/ext-utils.js
@@ -227,16 +227,17 @@ class BasePopup {
createBrowser(viewNode, popupURL = null) {
let document = viewNode.ownerDocument;
let browser = document.createElementNS(XUL_NS, "browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");
browser.setAttribute("transparent", "true");
browser.setAttribute("class", "webextension-popup-browser");
+ browser.setAttribute("remoteType", "extension");
browser.setAttribute("webextension-view-type", "popup");
browser.setAttribute("tooltip", "aHTMLTooltip");
if (this.extension.remote) {
browser.setAttribute("remote", "true");
}
// We only need flex sizing for the sake of the slide-in sub-views of the
--- a/browser/components/extensions/test/browser/head.js
+++ b/browser/components/extensions/test/browser/head.js
@@ -20,19 +20,22 @@ const {AppConstants} = Cu.import("resour
const {CustomizableUI} = Cu.import("resource:///modules/CustomizableUI.jsm");
// We run tests under two different configurations, from browser.ini and
// browser-remote.ini. When running from browser-remote.ini, the tests are
// copied to the sub-directory "test-oop-extensions", which we detect here, and
// use to select our configuration.
if (gTestPath.includes("test-oop-extensions")) {
SpecialPowers.pushPrefEnv({set: [
- ["dom.ipc.processCount", 1],
+ ["dom.ipc.processCount.extension", 1],
["extensions.webextensions.remote", true],
]});
+ // We don't want to reset this at the end of the test, so that we don't have
+ // to spawn a new extension child process for each test unit.
+ SpecialPowers.setIntPref("dom.ipc.keepProcessesAlive.extension", 1);
}
// Bug 1239884: Our tests occasionally hit a long GC pause at unpredictable
// times in debug builds, which results in intermittent timeouts. Until we have
// a better solution, we force a GC after certain strategic tests, which tend to
// accumulate a high number of unreaped windows.
function forceGC() {
if (AppConstants.DEBUG) {
--- a/browser/modules/E10SUtils.jsm
+++ b/browser/modules/E10SUtils.jsm
@@ -28,28 +28,30 @@ function getAboutModule(aURL) {
}
}
const NOT_REMOTE = null;
// These must match any similar ones in ContentParent.h.
const WEB_REMOTE_TYPE = "web";
const FILE_REMOTE_TYPE = "file";
+const EXTENSION_REMOTE_TYPE = "extension";
const DEFAULT_REMOTE_TYPE = WEB_REMOTE_TYPE;
function validatedWebRemoteType(aPreferredRemoteType) {
return aPreferredRemoteType && aPreferredRemoteType.startsWith(WEB_REMOTE_TYPE)
? aPreferredRemoteType : WEB_REMOTE_TYPE;
}
this.E10SUtils = {
DEFAULT_REMOTE_TYPE,
NOT_REMOTE,
WEB_REMOTE_TYPE,
FILE_REMOTE_TYPE,
+ EXTENSION_REMOTE_TYPE,
canLoadURIInProcess: function(aURL, aProcess) {
let remoteType = aProcess == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT
? DEFAULT_REMOTE_TYPE : NOT_REMOTE;
return remoteType == this.getRemoteTypeForURI(aURL, true, remoteType);
},
getRemoteTypeForURI: function(aURL, aMultiProcess,
@@ -127,17 +129,17 @@ this.E10SUtils = {
aPreferredRemoteType != NOT_REMOTE) {
return DEFAULT_REMOTE_TYPE;
}
return NOT_REMOTE;
}
if (aURL.startsWith("moz-extension:")) {
- return useRemoteWebExtensions ? WEB_REMOTE_TYPE : NOT_REMOTE;
+ return useRemoteWebExtensions ? EXTENSION_REMOTE_TYPE : NOT_REMOTE;
}
if (aURL.startsWith("view-source:")) {
return this.getRemoteTypeForURI(aURL.substr("view-source:".length),
aMultiProcess, aPreferredRemoteType);
}
return validatedWebRemoteType(aPreferredRemoteType);
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -32,16 +32,17 @@
#define CHILD_PROCESS_SHUTDOWN_MESSAGE NS_LITERAL_STRING("child-process-shutdown")
#define NO_REMOTE_TYPE ""
// These must match the similar ones in E10SUtils.jsm.
#define DEFAULT_REMOTE_TYPE "web"
#define FILE_REMOTE_TYPE "file"
+#define EXTENSION_REMOTE_TYPE "extension"
// This must start with the DEFAULT_REMOTE_TYPE above.
#define LARGE_ALLOCATION_REMOTE_TYPE "webLargeAllocation"
class nsConsoleService;
class nsICycleCollectorLogSink;
class nsIDumpGCAndCCLogsCallback;
class nsITabParent;
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -23,17 +23,17 @@ const Cr = Components.results;
Cu.importGlobalProperties(["TextEncoder"]);
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
/* globals processCount */
-XPCOMUtils.defineLazyPreferenceGetter(this, "processCount", "dom.ipc.processCount");
+XPCOMUtils.defineLazyPreferenceGetter(this, "processCount", "dom.ipc.processCount.extension");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
"resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
"resource://gre/modules/AppConstants.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionAPIs",
"resource://gre/modules/ExtensionAPI.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionStorage",
--- a/toolkit/components/extensions/ExtensionManagement.jsm
+++ b/toolkit/components/extensions/ExtensionManagement.jsm
@@ -300,18 +300,20 @@ function getAPILevelForWindow(window, ad
}
// WebExtension URLs loaded into top frames UI could have full API level privileges.
return FULL_PRIVILEGES;
}
ExtensionManagement = {
get isExtensionProcess() {
- return (this.useRemoteWebExtensions ||
- Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_DEFAULT);
+ if (this.useRemoteWebExtensions) {
+ return Services.appinfo.remoteType === "extension";
+ }
+ return Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_DEFAULT;
},
startupExtension: Service.startupExtension.bind(Service),
shutdownExtension: Service.shutdownExtension.bind(Service),
registerAPI: APIs.register.bind(APIs),
unregisterAPI: APIs.unregister.bind(APIs),
--- a/toolkit/components/extensions/ExtensionParent.jsm
+++ b/toolkit/components/extensions/ExtensionParent.jsm
@@ -451,17 +451,20 @@ ParentAPIManager = {
}
let context;
if (envType == "addon_parent" || envType == "devtools_parent") {
let processMessageManager = (target.messageManager.processMessageManager ||
Services.ppmm.getChildAt(0));
if (!extension.parentMessageManager) {
- extension.parentMessageManager = processMessageManager;
+ let expectedRemoteType = extension.remote ? "extension" : null;
+ if (target.remoteType === expectedRemoteType) {
+ extension.parentMessageManager = processMessageManager;
+ }
}
if (processMessageManager !== extension.parentMessageManager) {
throw new Error("Attempt to create privileged extension parent from incorrect child process");
}
context = new ExtensionPageContextParent(envType, extension, data, target);
} else if (envType == "content_parent") {
--- a/toolkit/components/extensions/ext-backgroundPage.js
+++ b/toolkit/components/extensions/ext-backgroundPage.js
@@ -47,16 +47,17 @@ class BackgroundPageBase {
url = this.extension.baseURI.resolve("_blank.html");
}
let chromeDoc = yield this.getParentDocument();
let browser = chromeDoc.createElement("browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");
+ browser.setAttribute("remoteType", "extension");
browser.setAttribute("webextension-view-type", "background");
let awaitFrameLoader;
if (this.extension.remote) {
browser.setAttribute("remote", "true");
awaitFrameLoader = promiseEvent(browser, "XULFrameLoaderCreated");
}
--- a/toolkit/components/extensions/test/mochitest/head.js
+++ b/toolkit/components/extensions/test/mochitest/head.js
@@ -1,19 +1,22 @@
"use strict";
// We run tests under two different configurations, from mochitest.ini and
// mochitest-remote.ini. When running from mochitest-remote.ini, the tests are
// copied to the sub-directory "test-oop-extensions", which we detect here, and
// use to select our configuration.
if (location.pathname.includes("test-oop-extensions")) {
SpecialPowers.pushPrefEnv({set: [
- ["dom.ipc.processCount", 1],
+ ["dom.ipc.processCount.extension", 1],
["extensions.webextensions.remote", true],
]});
+ // We don't want to reset this at the end of the test, so that we don't have
+ // to spawn a new extension child process for each test unit.
+ SpecialPowers.setIntPref("dom.ipc.keepProcessesAlive.extension", 1);
}
/* exported waitForLoad */
function waitForLoad(win) {
return new Promise(resolve => {
win.addEventListener("load", function listener() {
win.removeEventListener("load", listener, true);
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -3529,16 +3529,17 @@ var gDetailView = {
}
},
createOptionsBrowser: Task.async(function*(parentNode) {
let browser = document.createElement("browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");
browser.setAttribute("class", "inline-options-browser");
+ browser.setAttribute("remoteType", "extension");
let {optionsURL} = this._addon;
let remote = !E10SUtils.canLoadURIInProcess(optionsURL, Services.appinfo.PROCESS_TYPE_DEFAULT);
let readyPromise;
if (remote) {
browser.setAttribute("remote", "true");
readyPromise = promiseEvent("XULFrameLoaderCreated", browser);