зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1498293 - Ensure the webextension fallback window has a TabChild actor in content. r=ochameau
This patch remove the usage of `Services.appShell.createWindowlessBrowser` from the webextension target actor (that runs in a child process when the extension is in oop-mode). As a fallback window (needed when an extension doesn't have an extension page yet, e.g. while the extension is being reloaded, or when the extension doesn't have a background page), the actor is going to search for the window related to the XUL browser element created to connect into the extension process. If the extension runs in the child process (e.g. as it currently happens on all platforms supported by Firefox Desktop), the TabParent/TabChild's tabId is used to identify the fallback window. On the contrary, when the extension runs in the parent process (e.g. as it currently happens on Firefox for Android), the XUL browser's ownerGlobal innerWindowID is used to identify the fallback window. Differential Revision: https://phabricator.services.mozilla.com/D8573 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
7ea4ed8008
Коммит
7153f497a9
|
@ -45,20 +45,28 @@ add_task(async function testWebExtensionsToolboxNoBackgroundPage() {
|
|||
.getService(Ci.nsIEnvironment);
|
||||
const testScript = function() {
|
||||
/* eslint-disable no-undef */
|
||||
// This is webextension toolbox process. So we can't access mochitest framework.
|
||||
const waitUntil = async function(predicate, interval = 10) {
|
||||
if (await predicate()) {
|
||||
return true;
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
toolbox.win.setTimeout(function() {
|
||||
waitUntil(predicate, interval).then(() => resolve(true));
|
||||
}, interval);
|
||||
});
|
||||
};
|
||||
|
||||
toolbox.selectTool("inspector").then(async inspector => {
|
||||
const nodeActor = await inspector.walker.querySelector(
|
||||
inspector.walker.rootNode, "body");
|
||||
let nodeActor;
|
||||
|
||||
if (!nodeActor) {
|
||||
throw new Error("nodeActor not found");
|
||||
}
|
||||
|
||||
if (!(nodeActor.inlineTextChild)) {
|
||||
throw new Error("inlineTextChild not found");
|
||||
}
|
||||
dump(`Wait the fallback window to be fully loaded\n`);
|
||||
await waitUntil(async () => {
|
||||
nodeActor = await inspector.walker.querySelector(inspector.walker.rootNode, "h1");
|
||||
return nodeActor && nodeActor.inlineTextChild;
|
||||
});
|
||||
|
||||
dump("Got a nodeActor with an inline text child\n");
|
||||
|
||||
const expectedValue = "Your addon does not have any document opened yet.";
|
||||
const actualValue = nodeActor.inlineTextChild._form.nodeValue;
|
||||
|
||||
|
|
|
@ -76,14 +76,11 @@ const webExtensionTargetPrototype = extend({}, parentProcessTargetPrototype);
|
|||
*/
|
||||
webExtensionTargetPrototype.initialize = function(conn, chromeGlobal, prefix, addonId) {
|
||||
this.addonId = addonId;
|
||||
this.chromeGlobal = chromeGlobal;
|
||||
|
||||
// Try to discovery an existent extension page to attach (which will provide the initial
|
||||
// URL shown in the window tittle when the addon debugger is opened).
|
||||
let extensionWindow = this._searchForExtensionWindow();
|
||||
if (!extensionWindow) {
|
||||
this._createFallbackWindow();
|
||||
extensionWindow = this.fallbackWindow;
|
||||
}
|
||||
const extensionWindow = this._searchForExtensionWindow();
|
||||
|
||||
parentProcessTargetPrototype.initialize.call(this, conn, extensionWindow);
|
||||
this._chromeGlobal = chromeGlobal;
|
||||
|
@ -154,33 +151,24 @@ webExtensionTargetPrototype.exit = function() {
|
|||
|
||||
// Private helpers.
|
||||
|
||||
webExtensionTargetPrototype._createFallbackWindow = function() {
|
||||
webExtensionTargetPrototype._searchFallbackWindow = function() {
|
||||
if (this.fallbackWindow) {
|
||||
// Skip if there is already an existent fallback window.
|
||||
return;
|
||||
return this.fallbackWindow;
|
||||
}
|
||||
|
||||
// Create an empty hidden window as a fallback (e.g. the background page could be
|
||||
// not defined for the target add-on or not yet when the actor instance has been
|
||||
// created).
|
||||
this.fallbackWebNav = Services.appShell.createWindowlessBrowser(true);
|
||||
// Set and initialized the fallbackWindow (which initially is a empty
|
||||
// about:blank browser), this window is related to a XUL browser element
|
||||
// specifically created for the devtools server and it is never used
|
||||
// or navigated anywhere else.
|
||||
this.fallbackWindow = this.chromeGlobal.content;
|
||||
this.fallbackWindow.location = "data:text/html,<h1>" + FALLBACK_DOC_MESSAGE;
|
||||
|
||||
// Save the reference to the fallback DOMWindow.
|
||||
this.fallbackWindow = this.fallbackWebNav.document.defaultView;
|
||||
|
||||
// Insert the fallback doc message.
|
||||
this.fallbackWindow.document.body.innerText = FALLBACK_DOC_MESSAGE;
|
||||
return this.fallbackWindow;
|
||||
};
|
||||
|
||||
webExtensionTargetPrototype._destroyFallbackWindow = function() {
|
||||
if (this.fallbackWebNav) {
|
||||
const systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
|
||||
// Explicitly close the fallback windowless browser to prevent it to leak
|
||||
// (and to prevent it to freeze devtools xpcshell tests).
|
||||
this.fallbackWebNav.loadURI("about:blank", 0, null, null, null, systemPrincipal);
|
||||
this.fallbackWebNav.close();
|
||||
|
||||
this.fallbackWebNav = null;
|
||||
if (this.fallbackWindow) {
|
||||
this.fallbackWindow = null;
|
||||
}
|
||||
};
|
||||
|
@ -196,7 +184,7 @@ webExtensionTargetPrototype._searchForExtensionWindow = function() {
|
|||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
return this._searchFallbackWindow();
|
||||
};
|
||||
|
||||
// Customized ParentProcessTargetActor/BrowsingContextTargetActor hooks.
|
||||
|
@ -214,9 +202,7 @@ webExtensionTargetPrototype._onDocShellDestroy = function(docShell) {
|
|||
// If the destroyed docShell was the current docShell and the actor is
|
||||
// currently attached, switch to the fallback window
|
||||
if (this.attached && docShell == this.docShell) {
|
||||
// Creates a fallback window if it doesn't exist yet.
|
||||
this._createFallbackWindow();
|
||||
this._changeTopLevelDocument(this.fallbackWindow);
|
||||
this._changeTopLevelDocument(this._searchForExtensionWindow());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -232,15 +218,8 @@ webExtensionTargetPrototype._attach = function() {
|
|||
// subscribed to the child doc shell updates.
|
||||
|
||||
if (!this.window || this.window.document.nodePrincipal.addonId !== this.addonId) {
|
||||
// Discovery an existent extension page to attach.
|
||||
const extensionWindow = this._searchForExtensionWindow();
|
||||
|
||||
if (!extensionWindow) {
|
||||
this._createFallbackWindow();
|
||||
this._setWindow(this.fallbackWindow);
|
||||
} else {
|
||||
this._setWindow(extensionWindow);
|
||||
}
|
||||
// Discovery an existent extension page (or fallback window) to attach.
|
||||
this._setWindow(this._searchForExtensionWindow());
|
||||
}
|
||||
|
||||
// Call ParentProcessTargetActor's _attach to listen for any new/destroyed chrome
|
||||
|
|
Загрузка…
Ссылка в новой задаче