mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1190680: Part 1 - [webext] Factor common extension context logic into a shared base class. r=billm
This commit is contained in:
parent
64d33abd44
commit
724b49e80c
@ -81,6 +81,7 @@ ExtensionManagement.registerSchema("chrome://extensions/content/schemas/web_requ
|
||||
|
||||
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
||||
var {
|
||||
BaseContext,
|
||||
LocaleData,
|
||||
MessageBroker,
|
||||
Messenger,
|
||||
@ -218,14 +219,16 @@ var gContextId = 0;
|
||||
// |uri| is the URI of the content (optional).
|
||||
// |docShell| is the docshell the content runs in (optional).
|
||||
// |incognito| is the content running in a private context (default: false).
|
||||
ExtensionPage = function(extension, params) {
|
||||
ExtensionPage = class extends BaseContext {
|
||||
constructor(extension, params) {
|
||||
super();
|
||||
|
||||
let {type, contentWindow, uri} = params;
|
||||
this.extension = extension;
|
||||
this.type = type;
|
||||
this.contentWindow = contentWindow || null;
|
||||
this.uri = uri || extension.baseURI;
|
||||
this.incognito = params.incognito || false;
|
||||
this.onClose = new Set();
|
||||
this.contextId = gContextId++;
|
||||
this.unloaded = false;
|
||||
|
||||
@ -246,35 +249,15 @@ ExtensionPage = function(extension, params) {
|
||||
this.messenger = new Messenger(this, globalBroker, sender, filter, delegate);
|
||||
|
||||
this.extension.views.add(this);
|
||||
};
|
||||
}
|
||||
|
||||
ExtensionPage.prototype = {
|
||||
get cloneScope() {
|
||||
return this.contentWindow;
|
||||
},
|
||||
}
|
||||
|
||||
get principal() {
|
||||
return this.contentWindow.document.nodePrincipal;
|
||||
},
|
||||
|
||||
checkLoadURL(url, options = {}) {
|
||||
let ssm = Services.scriptSecurityManager;
|
||||
|
||||
let flags = ssm.STANDARD;
|
||||
if (!options.allowScript) {
|
||||
flags |= ssm.DISALLOW_SCRIPT;
|
||||
}
|
||||
if (!options.allowInheritsPrincipal) {
|
||||
flags |= ssm.DISALLOW_INHERIT_PRINCIPAL;
|
||||
}
|
||||
|
||||
try {
|
||||
ssm.checkLoadURIStrWithPrincipal(this.principal, url, flags);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
// A wrapper around MessageChannel.sendMessage which adds the extension ID
|
||||
// to the recipient object, and ensures replies are not processed after the
|
||||
@ -285,21 +268,13 @@ ExtensionPage.prototype = {
|
||||
sender.contextId = this.contextId;
|
||||
|
||||
return MessageChannel.sendMessage(target, messageName, data, recipient, sender);
|
||||
},
|
||||
|
||||
callOnClose(obj) {
|
||||
this.onClose.add(obj);
|
||||
},
|
||||
|
||||
forgetOnClose(obj) {
|
||||
this.onClose.delete(obj);
|
||||
},
|
||||
}
|
||||
|
||||
// Called when the extension shuts down.
|
||||
shutdown() {
|
||||
Management.emit("page-shutdown", this);
|
||||
this.unload();
|
||||
},
|
||||
}
|
||||
|
||||
// This method is called when an extension page navigates away or
|
||||
// its tab is closed.
|
||||
@ -322,10 +297,8 @@ ExtensionPage.prototype = {
|
||||
|
||||
this.extension.views.delete(this);
|
||||
|
||||
for (let obj of this.onClose) {
|
||||
obj.close();
|
||||
super.unload();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Responsible for loading extension APIs into the right globals.
|
||||
|
@ -37,6 +37,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "MessageChannel",
|
||||
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
||||
var {
|
||||
runSafeSyncWithoutClone,
|
||||
BaseContext,
|
||||
LocaleData,
|
||||
MessageBroker,
|
||||
Messenger,
|
||||
@ -227,7 +228,10 @@ var ExtensionManager;
|
||||
// Scope in which extension content script code can run. It uses
|
||||
// Cu.Sandbox to run the code. There is a separate scope for each
|
||||
// frame.
|
||||
function ExtensionContext(extensionId, contentWindow, contextOptions = {}) {
|
||||
class ExtensionContext extends BaseContext {
|
||||
constructor(extensionId, contentWindow, contextOptions = {}) {
|
||||
super();
|
||||
|
||||
let { isExtensionPage } = contextOptions;
|
||||
|
||||
this.isExtensionPage = isExtensionPage;
|
||||
@ -235,8 +239,6 @@ function ExtensionContext(extensionId, contentWindow, contextOptions = {}) {
|
||||
this.extensionId = extensionId;
|
||||
this.contentWindow = contentWindow;
|
||||
|
||||
this.onClose = new Set();
|
||||
|
||||
let utils = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
let outerWindowId = utils.outerWindowID;
|
||||
@ -249,11 +251,15 @@ function ExtensionContext(extensionId, contentWindow, contextOptions = {}) {
|
||||
let prin;
|
||||
let contentPrincipal = contentWindow.document.nodePrincipal;
|
||||
let ssm = Services.scriptSecurityManager;
|
||||
|
||||
let extensionPrincipal = ssm.createCodebasePrincipal(this.extension.baseURI, {addonId: extensionId});
|
||||
Object.defineProperty(this, "principal",
|
||||
{value: extensionPrincipal, enumerable: true, configurable: true});
|
||||
|
||||
if (ssm.isSystemPrincipal(contentPrincipal)) {
|
||||
// Make sure we don't hand out the system principal by accident.
|
||||
prin = Cc["@mozilla.org/nullprincipal;1"].createInstance(Ci.nsIPrincipal);
|
||||
} else {
|
||||
let extensionPrincipal = ssm.createCodebasePrincipal(this.extension.baseURI, {addonId: extensionId});
|
||||
prin = [contentPrincipal, extensionPrincipal];
|
||||
}
|
||||
|
||||
@ -309,27 +315,16 @@ function ExtensionContext(extensionId, contentWindow, contextOptions = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
ExtensionContext.prototype = {
|
||||
get cloneScope() {
|
||||
return this.sandbox;
|
||||
},
|
||||
}
|
||||
|
||||
execute(script, shouldRun) {
|
||||
script.tryInject(this.extension, this.contentWindow, this.sandbox, shouldRun);
|
||||
},
|
||||
|
||||
callOnClose(obj) {
|
||||
this.onClose.add(obj);
|
||||
},
|
||||
|
||||
forgetOnClose(obj) {
|
||||
this.onClose.delete(obj);
|
||||
},
|
||||
}
|
||||
|
||||
close() {
|
||||
for (let obj of this.onClose) {
|
||||
obj.close();
|
||||
}
|
||||
super.unload();
|
||||
|
||||
// Overwrite the content script APIs with an empty object if the APIs objects are still
|
||||
// defined in the content window (See Bug 1214658 for rationale).
|
||||
@ -338,11 +333,10 @@ ExtensionContext.prototype = {
|
||||
Cu.createObjectIn(this.contentWindow, { defineAs: "browser" });
|
||||
Cu.createObjectIn(this.contentWindow, { defineAs: "chrome" });
|
||||
}
|
||||
|
||||
Cu.nukeSandbox(this.sandbox);
|
||||
this.sandbox = null;
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function windowId(window) {
|
||||
return window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
|
@ -112,6 +112,53 @@ DefaultWeakMap.prototype = {
|
||||
},
|
||||
};
|
||||
|
||||
class BaseContext {
|
||||
constructor() {
|
||||
this.onClose = new Set();
|
||||
}
|
||||
|
||||
get cloneScope() {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
|
||||
get principal() {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
|
||||
checkLoadURL(url, options = {}) {
|
||||
let ssm = Services.scriptSecurityManager;
|
||||
|
||||
let flags = ssm.STANDARD;
|
||||
if (!options.allowScript) {
|
||||
flags |= ssm.DISALLOW_SCRIPT;
|
||||
}
|
||||
if (!options.allowInheritsPrincipal) {
|
||||
flags |= ssm.DISALLOW_INHERIT_PRINCIPAL;
|
||||
}
|
||||
|
||||
try {
|
||||
ssm.checkLoadURIStrWithPrincipal(this.principal, url, flags);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
callOnClose(obj) {
|
||||
this.onClose.add(obj);
|
||||
}
|
||||
|
||||
forgetOnClose(obj) {
|
||||
this.onClose.delete(obj);
|
||||
}
|
||||
|
||||
unload() {
|
||||
for (let obj of this.onClose) {
|
||||
obj.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function LocaleData(data) {
|
||||
this.defaultLocale = data.defaultLocale;
|
||||
this.selectedLocale = data.selectedLocale;
|
||||
@ -786,6 +833,7 @@ this.ExtensionUtils = {
|
||||
runSafeSyncWithoutClone,
|
||||
runSafe,
|
||||
runSafeSync,
|
||||
BaseContext,
|
||||
DefaultWeakMap,
|
||||
EventManager,
|
||||
LocaleData,
|
||||
|
Loading…
Reference in New Issue
Block a user