зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1368289: Simplify frameloader global metadata tagging. r=mixedpuppy
MozReview-Commit-ID: 1hgTtWysmya --HG-- extra : rebase_source : 1ef46a61bd805e9bf0573ed22db005217afb5478
This commit is contained in:
Родитель
e3153e78e2
Коммит
b31e211aa2
|
@ -237,7 +237,7 @@ class TabTracker extends TabTrackerBase {
|
|||
// Copy the ID from the old tab to the new.
|
||||
this.setId(nativeTab, this.getId(adoptedTab));
|
||||
|
||||
adoptedTab.linkedBrowser.messageManager.sendAsyncMessage("Extension:SetTabAndWindowId", {
|
||||
adoptedTab.linkedBrowser.messageManager.sendAsyncMessage("Extension:SetFrameData", {
|
||||
windowId: windowTracker.getId(nativeTab.ownerGlobal),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -28,6 +28,11 @@ XPCOMUtils.defineLazyModuleGetter(this, "Schemas",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "WebNavigationFrames",
|
||||
"resource://gre/modules/WebNavigationFrames.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(
|
||||
this, "processScript",
|
||||
() => Cc["@mozilla.org/webextensions/extension-process-script;1"]
|
||||
.getService().wrappedJSObject);
|
||||
|
||||
const CATEGORY_EXTENSION_SCRIPTS_ADDON = "webextension-scripts-addon";
|
||||
const CATEGORY_EXTENSION_SCRIPTS_DEVTOOLS = "webextension-scripts-devtools";
|
||||
|
||||
|
@ -54,6 +59,10 @@ const {
|
|||
|
||||
var ExtensionPageChild;
|
||||
|
||||
function getFrameData(global) {
|
||||
return processScript.getFrameData(global, true);
|
||||
}
|
||||
|
||||
var apiManager = new class extends SchemaAPIManager {
|
||||
constructor() {
|
||||
super("addon");
|
||||
|
@ -105,7 +114,7 @@ class ExtensionBaseContextChild extends BaseContext {
|
|||
}
|
||||
|
||||
super(params.envType, extension);
|
||||
let {viewType, uri, contentWindow, tabId} = params;
|
||||
let {viewType = "tab", uri, contentWindow, tabId} = params;
|
||||
this.viewType = viewType;
|
||||
this.uri = uri || extension.baseURI;
|
||||
|
||||
|
@ -150,8 +159,8 @@ class ExtensionBaseContextChild extends BaseContext {
|
|||
|
||||
get windowId() {
|
||||
if (["tab", "popup", "sidebar"].includes(this.viewType)) {
|
||||
let globalView = ExtensionPageChild.contentGlobals.get(this.messageManager);
|
||||
return globalView ? globalView.windowId : -1;
|
||||
let frameData = getFrameData(this.messageManager);
|
||||
return frameData ? frameData.windowId : -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -294,101 +303,7 @@ defineLazyGetter(DevToolsContextChild.prototype, "childManager", function() {
|
|||
return childManager;
|
||||
});
|
||||
|
||||
// All subframes in a tab, background page, popup, etc. have the same view type.
|
||||
// This class keeps track of such global state.
|
||||
// Note that this is created even for non-extension tabs because at present we
|
||||
// do not have a way to distinguish regular tabs from extension tabs at the
|
||||
// initialization of a frame script.
|
||||
class ContentGlobal {
|
||||
/**
|
||||
* @param {nsIContentFrameMessageManager} global The frame script's global.
|
||||
*/
|
||||
constructor(global) {
|
||||
this.global = global;
|
||||
// Unless specified otherwise assume that the extension page is in a tab,
|
||||
// because the majority of all class instances are going to be a tab. Any
|
||||
// special views (background page, extension popup) will immediately send an
|
||||
// Extension:InitExtensionView message to change the viewType.
|
||||
this.viewType = "tab";
|
||||
this.tabId = -1;
|
||||
this.windowId = -1;
|
||||
this.initialized = false;
|
||||
|
||||
this.global.addMessageListener("Extension:InitExtensionView", this);
|
||||
this.global.addMessageListener("Extension:SetTabAndWindowId", this);
|
||||
}
|
||||
|
||||
uninit() {
|
||||
this.global.removeMessageListener("Extension:InitExtensionView", this);
|
||||
this.global.removeMessageListener("Extension:SetTabAndWindowId", this);
|
||||
}
|
||||
|
||||
ensureInitialized() {
|
||||
if (!this.initialized) {
|
||||
// Request tab and window ID in case "Extension:InitExtensionView" is not
|
||||
// sent (e.g. when `viewType` is "tab").
|
||||
let reply = this.global.sendSyncMessage("Extension:GetTabAndWindowId");
|
||||
this.handleSetTabAndWindowId(reply[0] || {});
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
receiveMessage({name, data}) {
|
||||
switch (name) {
|
||||
case "Extension:InitExtensionView":
|
||||
// The view type is initialized once and then fixed.
|
||||
this.global.removeMessageListener("Extension:InitExtensionView", this);
|
||||
this.viewType = data.viewType;
|
||||
|
||||
// Force external links to open in tabs.
|
||||
if (["popup", "sidebar"].includes(this.viewType)) {
|
||||
this.global.docShell.isAppTab = true;
|
||||
}
|
||||
|
||||
if (data.devtoolsToolboxInfo) {
|
||||
this.devtoolsToolboxInfo = data.devtoolsToolboxInfo;
|
||||
}
|
||||
|
||||
promiseEvent(this.global, "DOMContentLoaded", true).then(() => {
|
||||
let windowId = getInnerWindowID(this.global.content);
|
||||
let context = ExtensionPageChild.extensionContexts.get(windowId);
|
||||
|
||||
this.global.sendAsyncMessage("Extension:ExtensionViewLoaded",
|
||||
{childId: context && context.childManager.id});
|
||||
});
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case "Extension:SetTabAndWindowId":
|
||||
this.handleSetTabAndWindowId(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleSetTabAndWindowId(data) {
|
||||
let {tabId, windowId} = data;
|
||||
|
||||
if (tabId) {
|
||||
// Tab IDs are not expected to change.
|
||||
if (this.tabId !== -1 && tabId !== this.tabId) {
|
||||
throw new Error("Attempted to change a tabId after it was set");
|
||||
}
|
||||
this.tabId = tabId;
|
||||
}
|
||||
|
||||
if (windowId !== undefined) {
|
||||
// Window IDs may change if a tab is moved to a different location.
|
||||
// Note: This is the ID of the browser window for the extension API.
|
||||
// Do not confuse it with the innerWindowID of DOMWindows!
|
||||
this.windowId = windowId;
|
||||
}
|
||||
this.initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
ExtensionPageChild = {
|
||||
// Map<nsIContentFrameMessageManager, ContentGlobal>
|
||||
contentGlobals: new Map(),
|
||||
|
||||
// Map<innerWindowId, ExtensionPageContextChild>
|
||||
extensionContexts: new Map(),
|
||||
|
||||
|
@ -403,23 +318,6 @@ ExtensionPageChild = {
|
|||
Services.obs.addObserver(this, "inner-window-destroyed"); // eslint-ignore-line mozilla/balanced-listeners
|
||||
},
|
||||
|
||||
init(global) {
|
||||
if (!WebExtensionPolicy.isExtensionProcess) {
|
||||
throw new Error("Cannot init extension page global in current process");
|
||||
}
|
||||
|
||||
if (!this.contentGlobals.has(global)) {
|
||||
this.contentGlobals.set(global, new ContentGlobal(global));
|
||||
}
|
||||
},
|
||||
|
||||
uninit(global) {
|
||||
if (this.contentGlobals.has(global)) {
|
||||
this.contentGlobals.get(global).uninit();
|
||||
this.contentGlobals.delete(global);
|
||||
}
|
||||
},
|
||||
|
||||
observe(subject, topic, data) {
|
||||
if (topic === "inner-window-destroyed") {
|
||||
let windowId = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
|
@ -428,6 +326,20 @@ ExtensionPageChild = {
|
|||
}
|
||||
},
|
||||
|
||||
expectViewLoad(global, viewType) {
|
||||
if (["popup", "sidebar"].includes(viewType)) {
|
||||
global.docShell.isAppTab = true;
|
||||
}
|
||||
|
||||
promiseEvent(global, "DOMContentLoaded", true).then(() => {
|
||||
let windowId = getInnerWindowID(global.content);
|
||||
let context = this.extensionContexts.get(windowId);
|
||||
|
||||
global.sendAsyncMessage("Extension:ExtensionViewLoaded",
|
||||
{childId: context && context.childManager.id});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a privileged context at document-element-inserted.
|
||||
*
|
||||
|
@ -456,7 +368,7 @@ ExtensionPageChild = {
|
|||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
|
||||
let {viewType, tabId, devtoolsToolboxInfo} = this.contentGlobals.get(mm).ensureInitialized();
|
||||
let {viewType, tabId, devtoolsToolboxInfo} = getFrameData(mm) || {};
|
||||
|
||||
let uri = contentWindow.document.documentURIObject;
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ let apiManager = new class extends SchemaAPIManager {
|
|||
if (sync) {
|
||||
return result;
|
||||
}
|
||||
target.messageManager.sendAsyncMessage("Extension:SetTabAndWindowId", result);
|
||||
target.messageManager.sendAsyncMessage("Extension:SetFrameData", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -282,7 +282,7 @@ GlobalManager = {
|
|||
let {tabTracker} = apiManager.global;
|
||||
Object.assign(data, tabTracker.getBrowserData(browser), additionalData);
|
||||
|
||||
browser.messageManager.sendAsyncMessage("Extension:InitExtensionView",
|
||||
browser.messageManager.sendAsyncMessage("Extension:SetFrameData",
|
||||
data);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -83,6 +83,9 @@ var ExtensionManager;
|
|||
class ExtensionGlobal {
|
||||
constructor(global) {
|
||||
this.global = global;
|
||||
this.global.addMessageListener("Extension:SetFrameData", this);
|
||||
|
||||
this.frameData = null;
|
||||
|
||||
MessageChannel.addListener(global, "Extension:Capture", this);
|
||||
MessageChannel.addListener(global, "Extension:DetectLanguage", this);
|
||||
|
@ -97,7 +100,27 @@ class ExtensionGlobal {
|
|||
};
|
||||
}
|
||||
|
||||
receiveMessage({target, messageName, recipient, data}) {
|
||||
getFrameData(force = false) {
|
||||
if (!this.frameData && force) {
|
||||
this.frameData = this.global.sendSyncMessage("Extension:GetTabAndWindowId")[0];
|
||||
}
|
||||
return this.frameData;
|
||||
}
|
||||
|
||||
receiveMessage({target, messageName, recipient, data, name}) {
|
||||
switch (name) {
|
||||
case "Extension:SetFrameData":
|
||||
if (this.frameData) {
|
||||
Object.assign(this.frameData, data);
|
||||
} else {
|
||||
this.frameData = data;
|
||||
}
|
||||
if (data.viewType && WebExtensionPolicy.isExtensionProcess) {
|
||||
ExtensionPageChild.expectViewLoad(this.global, data.viewType);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (messageName) {
|
||||
case "Extension:Capture":
|
||||
return ExtensionContent.handleExtensionCapture(this.global, data.width, data.height, data.options);
|
||||
|
@ -138,41 +161,17 @@ DocumentManager = {
|
|||
Services.obs.addObserver(this, "tab-content-frameloader-created"); // eslint-disable-line mozilla/balanced-listeners
|
||||
},
|
||||
|
||||
extensionProcessInitialized: false,
|
||||
initExtensionProcess() {
|
||||
if (this.extensionProcessInitialized || !WebExtensionPolicy.isExtensionProcess) {
|
||||
return;
|
||||
}
|
||||
this.extensionProcessInitialized = true;
|
||||
|
||||
for (let global of this.globals.keys()) {
|
||||
ExtensionPageChild.init(global);
|
||||
}
|
||||
},
|
||||
|
||||
// Initialize a frame script global which extension contexts may be loaded
|
||||
// into.
|
||||
initGlobal(global) {
|
||||
// Note: {once: true} does not work as expected here.
|
||||
global.addEventListener("unload", event => { // eslint-disable-line mozilla/balanced-listeners
|
||||
this.uninitGlobal(global);
|
||||
});
|
||||
|
||||
this.globals.set(global, new ExtensionGlobal(global));
|
||||
if (this.extensionProcessInitialized && WebExtensionPolicy.isExtensionProcess) {
|
||||
ExtensionPageChild.init(global);
|
||||
}
|
||||
},
|
||||
uninitGlobal(global) {
|
||||
if (this.extensionProcessInitialized) {
|
||||
ExtensionPageChild.uninit(global);
|
||||
}
|
||||
this.globals.delete(global);
|
||||
// eslint-disable-next-line mozilla/balanced-listeners
|
||||
global.addEventListener("unload", () => {
|
||||
this.globals.delete(global);
|
||||
});
|
||||
},
|
||||
|
||||
initExtension(extension) {
|
||||
this.initExtensionProcess();
|
||||
|
||||
this.injectExtensionScripts(extension);
|
||||
},
|
||||
|
||||
|
@ -384,6 +383,11 @@ ExtensionProcessScript.prototype = {
|
|||
|
||||
get wrappedJSObject() { return this; },
|
||||
|
||||
getFrameData(global, force) {
|
||||
let extGlobal = DocumentManager.globals.get(global);
|
||||
return extGlobal && extGlobal.getFrameData(force);
|
||||
},
|
||||
|
||||
initExtension(data, extension) {
|
||||
return ExtensionManager.initExtensionPolicy(data, extension);
|
||||
},
|
||||
|
|
Загрузка…
Ссылка в новой задаче