зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1309906 - part1: adapt webext-oop internals for devtools contexts and APIs. r=kmag
MozReview-Commit-ID: E0gxV271N31 --HG-- extra : rebase_source : 62e0ef8ac8f7060ff438126982b0d66ec7bfa17b
This commit is contained in:
Родитель
ef2eba34ab
Коммит
54efa5c5bb
|
@ -32,6 +32,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "Schemas",
|
|||
"resource://gre/modules/Schemas.jsm");
|
||||
|
||||
const CATEGORY_EXTENSION_SCRIPTS_ADDON = "webextension-scripts-addon";
|
||||
const CATEGORY_EXTENSION_SCRIPTS_DEVTOOLS = "webextension-scripts-devtools";
|
||||
|
||||
Cu.import("resource://gre/modules/ExtensionCommon.jsm");
|
||||
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
||||
|
@ -463,6 +464,29 @@ var apiManager = new class extends SchemaAPIManager {
|
|||
}
|
||||
}();
|
||||
|
||||
var devtoolsAPIManager = new class extends SchemaAPIManager {
|
||||
constructor() {
|
||||
super("devtools");
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
generateAPIs(...args) {
|
||||
if (!this.initialized) {
|
||||
this.initialized = true;
|
||||
for (let [/* name */, value] of XPCOMUtils.enumerateCategoryEntries(CATEGORY_EXTENSION_SCRIPTS_DEVTOOLS)) {
|
||||
this.loadScript(value);
|
||||
}
|
||||
}
|
||||
return super.generateAPIs(...args);
|
||||
}
|
||||
|
||||
registerSchemaAPI(namespace, envType, getAPI) {
|
||||
if (envType == "devtools_child") {
|
||||
super.registerSchemaAPI(namespace, envType, getAPI);
|
||||
}
|
||||
}
|
||||
}();
|
||||
|
||||
/**
|
||||
* An object that runs an remote implementation of an API.
|
||||
*/
|
||||
|
@ -686,6 +710,19 @@ class ChildAPIManager {
|
|||
if (allowedContexts.includes("addon_parent_only")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do not generate devtools APIs, unless explicitly allowed.
|
||||
if (this.context.envType === "devtools_child" &&
|
||||
!allowedContexts.includes("devtools")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do not generate devtools APIs, unless explicitly allowed.
|
||||
if (this.context.envType !== "devtools_child" &&
|
||||
allowedContexts.includes("devtools_only")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -711,32 +748,32 @@ class ChildAPIManager {
|
|||
}
|
||||
}
|
||||
|
||||
class ExtensionPageContextChild extends BaseContext {
|
||||
class ExtensionBaseContextChild extends BaseContext {
|
||||
/**
|
||||
* This ExtensionPageContextChild represents a privileged addon
|
||||
* execution environment that has full access to the WebExtensions
|
||||
* APIs (provided that the correct permissions have been requested).
|
||||
*
|
||||
* This is the child side of the ExtensionPageContextParent class
|
||||
* defined in ExtensionParent.jsm.
|
||||
* This ExtensionBaseContextChild represents an addon execution environment
|
||||
* that is running in an addon or devtools child process.
|
||||
*
|
||||
* @param {BrowserExtensionContent} extension This context's owner.
|
||||
* @param {object} params
|
||||
* @param {string} params.envType One of "addon_child" or "devtools_child".
|
||||
* @param {nsIDOMWindow} params.contentWindow The window where the addon runs.
|
||||
* @param {string} params.viewType One of "background", "popup" or "tab".
|
||||
* "background" and "tab" are used by `browser.extension.getViews`.
|
||||
* "popup" is only used internally to identify page action and browser
|
||||
* action popups and options_ui pages.
|
||||
* @param {string} params.viewType One of "background", "popup", "tab",
|
||||
* "devtools_page" or "devtools_panel".
|
||||
* @param {number} [params.tabId] This tab's ID, used if viewType is "tab".
|
||||
*/
|
||||
constructor(extension, params) {
|
||||
super("addon_child", extension);
|
||||
if (!params.envType) {
|
||||
throw new Error("Missing envType");
|
||||
}
|
||||
|
||||
if (Services.appinfo.processType != Services.appinfo.PROCESS_TYPE_DEFAULT) {
|
||||
// This check is temporary. It should be removed once the proxy creation
|
||||
// is asynchronous.
|
||||
throw new Error("ExtensionPageContextChild cannot be created in child processes");
|
||||
throw new Error("ExtensionContext cannot be created in child processes");
|
||||
}
|
||||
|
||||
super(params.envType, extension);
|
||||
|
||||
let {viewType, uri, contentWindow, tabId} = params;
|
||||
this.viewType = viewType;
|
||||
this.uri = uri || extension.baseURI;
|
||||
|
@ -769,8 +806,6 @@ class ExtensionPageContextChild extends BaseContext {
|
|||
Schemas.inject(chromeObj, chromeApiWrapper);
|
||||
return chromeObj;
|
||||
});
|
||||
|
||||
this.extension.views.add(this);
|
||||
}
|
||||
|
||||
get cloneScope() {
|
||||
|
@ -808,11 +843,10 @@ class ExtensionPageContextChild extends BaseContext {
|
|||
}
|
||||
|
||||
super.unload();
|
||||
this.extension.views.delete(this);
|
||||
}
|
||||
}
|
||||
|
||||
defineLazyGetter(ExtensionPageContextChild.prototype, "messenger", function() {
|
||||
defineLazyGetter(ExtensionBaseContextChild.prototype, "messenger", function() {
|
||||
let filter = {extensionId: this.extension.id};
|
||||
let optionalFilter = {};
|
||||
// Addon-generated messages (not necessarily from the same process as the
|
||||
|
@ -823,16 +857,89 @@ defineLazyGetter(ExtensionPageContextChild.prototype, "messenger", function() {
|
|||
filter, optionalFilter);
|
||||
});
|
||||
|
||||
class ExtensionPageContextChild extends ExtensionBaseContextChild {
|
||||
/**
|
||||
* This ExtensionPageContextChild represents a privileged addon
|
||||
* execution environment that has full access to the WebExtensions
|
||||
* APIs (provided that the correct permissions have been requested).
|
||||
*
|
||||
* This is the child side of the ExtensionPageContextParent class
|
||||
* defined in ExtensionParent.jsm.
|
||||
*
|
||||
* @param {BrowserExtensionContent} extension This context's owner.
|
||||
* @param {object} params
|
||||
* @param {nsIDOMWindow} params.contentWindow The window where the addon runs.
|
||||
* @param {string} params.viewType One of "background", "popup" or "tab".
|
||||
* "background" and "tab" are used by `browser.extension.getViews`.
|
||||
* "popup" is only used internally to identify page action and browser
|
||||
* action popups and options_ui pages.
|
||||
* @param {number} [params.tabId] This tab's ID, used if viewType is "tab".
|
||||
*/
|
||||
constructor(extension, params) {
|
||||
super(extension, Object.assign(params, {envType: "addon_child"}));
|
||||
|
||||
this.extension.views.add(this);
|
||||
}
|
||||
|
||||
unload() {
|
||||
super.unload();
|
||||
this.extension.views.delete(this);
|
||||
}
|
||||
}
|
||||
|
||||
defineLazyGetter(ExtensionPageContextChild.prototype, "childManager", function() {
|
||||
let localApis = {};
|
||||
apiManager.generateAPIs(this, localApis);
|
||||
|
||||
let childManager = new ChildAPIManager(this, this.messageManager, localApis, {
|
||||
envType: "addon_parent",
|
||||
viewType: this.viewType,
|
||||
url: this.uri.spec,
|
||||
incognito: this.incognito,
|
||||
});
|
||||
|
||||
this.callOnClose(childManager);
|
||||
|
||||
if (this.viewType == "background") {
|
||||
apiManager.global.initializeBackgroundPage(this.contentWindow);
|
||||
}
|
||||
|
||||
return childManager;
|
||||
});
|
||||
|
||||
class DevtoolsContextChild extends ExtensionBaseContextChild {
|
||||
/**
|
||||
* This DevtoolsContextChild represents a devtools-related addon execution
|
||||
* environment that has access to the devtools API namespace and to the same subset
|
||||
* of APIs available in a content script execution environment.
|
||||
*
|
||||
* @param {BrowserExtensionContent} extension This context's owner.
|
||||
* @param {object} params
|
||||
* @param {nsIDOMWindow} params.contentWindow The window where the addon runs.
|
||||
* @param {string} params.viewType One of "devtools_page" or "devtools_panel".
|
||||
* @param {object} [params.devtoolsToolboxInfo] This devtools toolbox's information,
|
||||
* used if viewType is "devtools_page" or "devtools_panel".
|
||||
*/
|
||||
constructor(extension, params) {
|
||||
super(extension, Object.assign(params, {envType: "devtools_child"}));
|
||||
|
||||
this.devtoolsToolboxInfo = params.devtoolsToolboxInfo;
|
||||
|
||||
this.extension.devtoolsViews.add(this);
|
||||
}
|
||||
|
||||
unload() {
|
||||
super.unload();
|
||||
this.extension.devtoolsViews.delete(this);
|
||||
}
|
||||
}
|
||||
|
||||
defineLazyGetter(DevtoolsContextChild.prototype, "childManager", function() {
|
||||
let localApis = {};
|
||||
devtoolsAPIManager.generateAPIs(this, localApis);
|
||||
|
||||
let childManager = new ChildAPIManager(this, this.messageManager, localApis, {
|
||||
envType: "addon_parent",
|
||||
envType: "devtools_parent",
|
||||
viewType: this.viewType,
|
||||
url: this.uri.spec,
|
||||
incognito: this.incognito,
|
||||
|
@ -891,6 +998,11 @@ class ContentGlobal {
|
|||
this.global.removeMessageListener("Extension:InitExtensionView", this);
|
||||
let {viewType, url} = data;
|
||||
this.viewType = viewType;
|
||||
|
||||
if (data.devtoolsToolboxInfo) {
|
||||
this.devtoolsToolboxInfo = data.devtoolsToolboxInfo;
|
||||
}
|
||||
|
||||
this.global.addEventListener("DOMContentLoaded", this);
|
||||
if (url) {
|
||||
// TODO(robwu): Remove this check. It is only here because the popup
|
||||
|
@ -991,11 +1103,21 @@ ExtensionChild = {
|
|||
.getInterface(Ci.nsIDocShell)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
let {viewType, tabId} = this.contentGlobals.get(mm).ensureInitialized();
|
||||
let {
|
||||
viewType, tabId,
|
||||
devtoolsToolboxInfo,
|
||||
} = this.contentGlobals.get(mm).ensureInitialized();
|
||||
|
||||
let uri = contentWindow.document.documentURIObject;
|
||||
|
||||
context = new ExtensionPageContextChild(extension, {viewType, contentWindow, uri, tabId});
|
||||
if (devtoolsToolboxInfo) {
|
||||
context = new DevtoolsContextChild(extension, {
|
||||
viewType, contentWindow, uri, tabId, devtoolsToolboxInfo,
|
||||
});
|
||||
} else {
|
||||
context = new ExtensionPageContextChild(extension, {viewType, contentWindow, uri, tabId});
|
||||
}
|
||||
|
||||
this.extensionContexts.set(windowId, context);
|
||||
},
|
||||
|
||||
|
|
|
@ -542,6 +542,7 @@ class SchemaAPIManager extends EventEmitter {
|
|||
* "main" - The main, one and only chrome browser process.
|
||||
* "addon" - An addon process.
|
||||
* "content" - A content process.
|
||||
* "devtools" - A devtools process.
|
||||
*/
|
||||
constructor(processType) {
|
||||
super();
|
||||
|
@ -553,6 +554,8 @@ class SchemaAPIManager extends EventEmitter {
|
|||
addon_child: [],
|
||||
content_parent: [],
|
||||
content_child: [],
|
||||
devtools_parent: [],
|
||||
devtools_child: [],
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -608,6 +611,8 @@ class SchemaAPIManager extends EventEmitter {
|
|||
* - "addon_child" - addon APIs that runs in an addon process.
|
||||
* - "content_parent" - content script APIs that runs in the main process.
|
||||
* - "content_child" - content script APIs that runs in a content process.
|
||||
* - "devtools_parent" - devtools APIs that runs in the main process.
|
||||
* - "devtools_child" - devtools APIs that runs in a devtools process.
|
||||
* @param {function(BaseContext)} getAPI A function that returns an object
|
||||
* that will be merged with |chrome| and |browser|. The next example adds
|
||||
* the create, update and remove methods to the tabs API.
|
||||
|
|
|
@ -797,6 +797,9 @@ class BrowserExtensionContent extends EventEmitter {
|
|||
// Only used in addon processes.
|
||||
this.views = new Set();
|
||||
|
||||
// Only used for devtools views.
|
||||
this.devtoolsViews = new Set();
|
||||
|
||||
let uri = Services.io.newURI(data.resourceURL, null, null);
|
||||
|
||||
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
|
||||
|
|
|
@ -95,7 +95,8 @@ let apiManager = new class extends SchemaAPIManager {
|
|||
}
|
||||
|
||||
registerSchemaAPI(namespace, envType, getAPI) {
|
||||
if (envType == "addon_parent" || envType == "content_parent") {
|
||||
if (envType == "addon_parent" || envType == "content_parent" ||
|
||||
envType == "devtools_parent") {
|
||||
super.registerSchemaAPI(namespace, envType, getAPI);
|
||||
}
|
||||
}
|
||||
|
@ -321,6 +322,8 @@ class ExtensionPageContextParent extends ProxyContextParent {
|
|||
super(envType, extension, params, xulBrowser, extension.principal);
|
||||
|
||||
this.viewType = params.viewType;
|
||||
|
||||
extension.emit("extension-proxy-context-load", this);
|
||||
}
|
||||
|
||||
// The window that contains this context. This may change due to moving tabs.
|
||||
|
@ -425,7 +428,7 @@ ParentAPIManager = {
|
|||
}
|
||||
|
||||
let context;
|
||||
if (envType == "addon_parent") {
|
||||
if (envType == "addon_parent" || envType == "devtools_parent") {
|
||||
// Privileged addon contexts can only be loaded in documents whose main
|
||||
// frame is also the same addon.
|
||||
if (principal.URI.prePath !== extension.baseURI.prePath ||
|
||||
|
|
Загрузка…
Ссылка в новой задаче