Bug 1339144 - Use windowless browser for remote background pages. r=aswan

MozReview-Commit-ID: LfmPbkTsgwu

--HG--
extra : source : 2ba94924e6d7959f5d8850e6ab14008d4a1c6288
extra : histedit_source : 2035406acd128331977baf481e5ad6c85252d067%2C97c30a16513b28e0f932161804f421145dc3e363
This commit is contained in:
Kris Maglione 2017-02-16 17:26:15 -08:00
Родитель adaec16e2b
Коммит 43e4c2bb06
7 изменённых файлов: 40 добавлений и 73 удалений

Просмотреть файл

@ -26,7 +26,6 @@ const {CustomizableUI} = Cu.import("resource:///modules/CustomizableUI.jsm", {})
// use to select our configuration.
if (gTestPath.includes("test-oop-extensions")) {
SpecialPowers.pushPrefEnv({set: [
["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

Просмотреть файл

@ -2923,6 +2923,9 @@ pref("dom.ipc.processCount", 2);
pref("dom.ipc.processCount", 1);
#endif
// WebExtensions only support a single extension process.
pref("dom.ipc.processCount.extension", 1);
// Disable support for SVG
pref("svg.disabled", false);

Просмотреть файл

@ -724,35 +724,32 @@ class HiddenExtensionPage {
* @returns {Promise<XULElement>}
* a Promise which resolves to the newly created browser XUL element.
*/
createBrowserElement() {
async createBrowserElement() {
if (this.browser) {
throw new Error("createBrowserElement called twice");
}
let waitForParentDocument;
let chromeDoc = await this.createWindowlessBrowser();
const browser = this.browser = chromeDoc.createElement("browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");
browser.setAttribute("webextension-view-type", this.viewType);
let awaitFrameLoader = Promise.resolve();
if (this.extension.remote) {
waitForParentDocument = this.createWindowedBrowser();
} else {
waitForParentDocument = this.createWindowlessBrowser();
browser.setAttribute("remote", "true");
browser.setAttribute("remoteType", E10SUtils.EXTENSION_REMOTE_TYPE);
awaitFrameLoader = promiseEvent(browser, "XULFrameLoaderCreated");
}
return waitForParentDocument.then(chromeDoc => {
const browser = this.browser = chromeDoc.createElement("browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");
browser.setAttribute("webextension-view-type", this.viewType);
chromeDoc.documentElement.appendChild(browser);
await awaitFrameLoader;
let awaitFrameLoader = Promise.resolve();
browser.docShellIsActive = false;
if (this.extension.remote) {
browser.setAttribute("remote", "true");
browser.setAttribute("remoteType", E10SUtils.EXTENSION_REMOTE_TYPE);
awaitFrameLoader = promiseEvent(browser, "XULFrameLoaderCreated");
}
chromeDoc.documentElement.appendChild(browser);
return awaitFrameLoader.then(() => browser);
});
return browser;
}
/**
@ -769,58 +766,26 @@ class HiddenExtensionPage {
* a promise which resolves to the newly created XULDocument.
*/
createWindowlessBrowser() {
return Task.spawn(function* () {
// The invisible page is currently wrapped in a XUL window to fix an issue
// with using the canvas API from a background page (See Bug 1274775).
let windowlessBrowser = Services.appShell.createWindowlessBrowser(true);
this.windowlessBrowser = windowlessBrowser;
// The invisible page is currently wrapped in a XUL window to fix an issue
// with using the canvas API from a background page (See Bug 1274775).
let windowlessBrowser = Services.appShell.createWindowlessBrowser(true);
this.windowlessBrowser = windowlessBrowser;
// The windowless browser is a thin wrapper around a docShell that keeps
// its related resources alive. It implements nsIWebNavigation and
// forwards its methods to the underlying docShell, but cannot act as a
// docShell itself. Calling `getInterface(nsIDocShell)` gives us the
// underlying docShell, and `QueryInterface(nsIWebNavigation)` gives us
// access to the webNav methods that are already available on the
// windowless browser, but contrary to appearances, they are not the same
// object.
let chromeShell = windowlessBrowser.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIWebNavigation);
yield this.initParentWindow(chromeShell);
// The windowless browser is a thin wrapper around a docShell that keeps
// its related resources alive. It implements nsIWebNavigation and
// forwards its methods to the underlying docShell, but cannot act as a
// docShell itself. Calling `getInterface(nsIDocShell)` gives us the
// underlying docShell, and `QueryInterface(nsIWebNavigation)` gives us
// access to the webNav methods that are already available on the
// windowless browser, but contrary to appearances, they are not the same
// object.
let chromeShell = windowlessBrowser.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIWebNavigation);
return this.initParentWindow(chromeShell).then(() => {
return promiseDocumentLoaded(windowlessBrowser.document);
}.bind(this));
}
/**
* Private helper that create a XULDocument in a visible dialog window.
*
* Using this helper, the extension page is loaded into a visible dialog window.
* Only to be used for debugging, and in temporary, test-only use for
* out-of-process extensions.
*
* @returns {Promise<XULDocument>}
* a promise which resolves to the newly created XULDocument.
*/
createWindowedBrowser() {
return Task.spawn(function* () {
let window = Services.ww.openWindow(null, "about:blank", "_blank",
"chrome,alwaysLowered,dialog", null);
this.parentWindow = window;
let chromeShell = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIWebNavigation);
yield this.initParentWindow(chromeShell);
window.minimize();
return promiseDocumentLoaded(window.document);
}.bind(this));
});
}
/**

Просмотреть файл

@ -159,7 +159,7 @@ class FilteringMessageManager {
* passes the result to our message callback.
*/
receiveMessage({data, target}) {
let handlers = Array.from(this.getHandlers(data.messageName, data.sender, data.recipient));
let handlers = Array.from(this.getHandlers(data.messageName, data.sender || null, data.recipient));
data.target = target;
this.callback(handlers, data);

Просмотреть файл

@ -966,7 +966,7 @@ class StringType extends Type {
format = FORMATS[schema.format];
}
return new this(schema,
schema.id,
schema.id || undefined,
enumeration,
schema.minLength || 0,
schema.maxLength || Infinity,

Просмотреть файл

@ -10,7 +10,6 @@ var {AppConstants} = SpecialPowers.Cu.import("resource://gre/modules/AppConstant
// use to select our configuration.
if (location.pathname.includes("test-oop-extensions")) {
SpecialPowers.pushPrefEnv({set: [
["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

Просмотреть файл

@ -47,6 +47,7 @@ skip-if = release_or_beta
[test_ext_manifest_incognito.js]
[test_ext_manifest_minimum_chrome_version.js]
[test_ext_onmessage_removelistener.js]
skip-if = true # This test no longer tests what it is meant to test.
[test_ext_runtime_connect_no_receiver.js]
[test_ext_runtime_getBrowserInfo.js]
[test_ext_runtime_getPlatformInfo.js]