2017-04-15 03:00:51 +03:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This script contains the minimum, skeleton content process code that we need
|
|
|
|
* in order to lazily load other extension modules when they are first
|
|
|
|
* necessary. Anything which is not likely to be needed immediately, or shortly
|
|
|
|
* after startup, in *every* browser process live outside of this file.
|
|
|
|
*/
|
|
|
|
|
2018-01-30 02:20:18 +03:00
|
|
|
ChromeUtils.import("resource://gre/modules/MessageChannel.jsm");
|
|
|
|
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
|
|
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
2017-04-15 03:00:51 +03:00
|
|
|
|
2017-08-09 23:03:36 +03:00
|
|
|
XPCOMUtils.defineLazyModuleGetters(this, {
|
|
|
|
ExtensionChild: "resource://gre/modules/ExtensionChild.jsm",
|
2018-06-26 05:30:21 +03:00
|
|
|
ExtensionCommon: "resource://gre/modules/ExtensionCommon.jsm",
|
2017-08-09 23:03:36 +03:00
|
|
|
ExtensionContent: "resource://gre/modules/ExtensionContent.jsm",
|
|
|
|
ExtensionPageChild: "resource://gre/modules/ExtensionPageChild.jsm",
|
|
|
|
});
|
2017-06-05 01:38:11 +03:00
|
|
|
|
2018-01-30 02:20:18 +03:00
|
|
|
ChromeUtils.import("resource://gre/modules/ExtensionUtils.jsm");
|
2017-04-15 03:00:51 +03:00
|
|
|
|
2018-06-26 05:30:21 +03:00
|
|
|
XPCOMUtils.defineLazyGetter(this, "console", () => ExtensionCommon.getConsole());
|
2017-06-05 01:38:11 +03:00
|
|
|
|
|
|
|
const {
|
|
|
|
DefaultWeakMap,
|
|
|
|
getInnerWindowID,
|
|
|
|
} = ExtensionUtils;
|
2017-04-15 03:00:51 +03:00
|
|
|
|
2018-06-25 02:34:44 +03:00
|
|
|
const {sharedData} = Services.cpmm;
|
|
|
|
|
|
|
|
function getData(extension, key = "") {
|
|
|
|
return sharedData.get(`extension/${extension.id}/${key}`);
|
|
|
|
}
|
|
|
|
|
2017-04-16 18:42:03 +03:00
|
|
|
// We need to avoid touching Services.appinfo here in order to prevent
|
|
|
|
// the wrong version from being cached during xpcshell test startup.
|
2017-10-30 19:29:58 +03:00
|
|
|
// eslint-disable-next-line mozilla/use-services
|
2017-04-16 18:42:03 +03:00
|
|
|
const appinfo = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
|
|
|
|
const isContentProcess = appinfo.processType == appinfo.PROCESS_TYPE_CONTENT;
|
2017-04-15 03:00:51 +03:00
|
|
|
|
2018-05-10 04:55:59 +03:00
|
|
|
function tryMatchPatternSet(patterns, options) {
|
|
|
|
try {
|
|
|
|
return new MatchPatternSet(patterns, options);
|
|
|
|
} catch (e) {
|
|
|
|
Cu.reportError(e);
|
|
|
|
return new MatchPatternSet([]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function parseScriptOptions(options, restrictSchemes = true) {
|
2017-06-04 03:11:08 +03:00
|
|
|
return {
|
2018-08-18 06:02:52 +03:00
|
|
|
...options,
|
2017-06-04 03:11:08 +03:00
|
|
|
|
2018-05-10 04:55:59 +03:00
|
|
|
matches: tryMatchPatternSet(options.matches, {restrictSchemes}),
|
2018-08-18 06:02:52 +03:00
|
|
|
excludeMatches: tryMatchPatternSet(options.excludeMatches || [], {restrictSchemes}),
|
|
|
|
includeGlobs: options.includeGlobs && options.includeGlobs.map(glob => new MatchGlob(glob)),
|
|
|
|
excludeGlobs: options.excludeGlobs && options.excludeGlobs.map(glob => new MatchGlob(glob)),
|
2017-06-04 03:11:08 +03:00
|
|
|
};
|
|
|
|
}
|
2017-04-15 03:00:51 +03:00
|
|
|
|
2017-05-26 07:57:48 +03:00
|
|
|
var extensions = new DefaultWeakMap(policy => {
|
2017-08-13 03:21:27 +03:00
|
|
|
let data = policy.initData;
|
|
|
|
if (data.serialize) {
|
|
|
|
// We have an actual Extension rather than serialized extension
|
|
|
|
// data, so serialize it now to make sure we have consistent inputs
|
|
|
|
// between parent and child processes.
|
|
|
|
data = data.serialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
let extension = new ExtensionChild.BrowserExtensionContent(data);
|
2017-05-26 07:57:48 +03:00
|
|
|
extension.policy = policy;
|
|
|
|
return extension;
|
|
|
|
});
|
|
|
|
|
2017-06-04 23:29:03 +03:00
|
|
|
var contentScripts = new DefaultWeakMap(matcher => {
|
|
|
|
return new ExtensionContent.Script(extensions.get(matcher.extension),
|
|
|
|
matcher);
|
|
|
|
});
|
2017-04-15 03:00:51 +03:00
|
|
|
|
|
|
|
var DocumentManager;
|
|
|
|
var ExtensionManager;
|
|
|
|
|
|
|
|
class ExtensionGlobal {
|
|
|
|
constructor(global) {
|
|
|
|
this.global = global;
|
2017-05-28 03:30:53 +03:00
|
|
|
this.global.addMessageListener("Extension:SetFrameData", this);
|
|
|
|
|
|
|
|
this.frameData = null;
|
2017-04-15 03:00:51 +03:00
|
|
|
|
|
|
|
MessageChannel.addListener(global, "Extension:Capture", this);
|
|
|
|
MessageChannel.addListener(global, "Extension:DetectLanguage", this);
|
|
|
|
MessageChannel.addListener(global, "Extension:Execute", this);
|
|
|
|
MessageChannel.addListener(global, "WebNavigation:GetFrame", this);
|
|
|
|
MessageChannel.addListener(global, "WebNavigation:GetAllFrames", this);
|
|
|
|
}
|
|
|
|
|
|
|
|
get messageFilterStrict() {
|
|
|
|
return {
|
|
|
|
innerWindowID: getInnerWindowID(this.global.content),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-05-28 03:30:53 +03:00
|
|
|
getFrameData(force = false) {
|
|
|
|
if (!this.frameData && force) {
|
|
|
|
this.frameData = this.global.sendSyncMessage("Extension:GetTabAndWindowId")[0];
|
|
|
|
}
|
|
|
|
return this.frameData;
|
|
|
|
}
|
|
|
|
|
2017-11-24 21:17:33 +03:00
|
|
|
async receiveMessage({target, messageName, recipient, data, name}) {
|
2017-05-28 03:30:53 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-04-15 03:00:51 +03:00
|
|
|
switch (messageName) {
|
|
|
|
case "Extension:Capture":
|
|
|
|
return ExtensionContent.handleExtensionCapture(this.global, data.width, data.height, data.options);
|
|
|
|
case "Extension:DetectLanguage":
|
|
|
|
return ExtensionContent.handleDetectLanguage(this.global, target);
|
|
|
|
case "Extension:Execute":
|
2017-05-26 07:57:48 +03:00
|
|
|
let policy = WebExtensionPolicy.getByID(recipient.extensionId);
|
2017-06-04 03:11:08 +03:00
|
|
|
|
2018-05-10 04:55:59 +03:00
|
|
|
let matcher = new WebExtensionContentScript(policy, parseScriptOptions(data.options, !policy.hasPermission("mozillaAddons")));
|
2017-06-04 03:11:08 +03:00
|
|
|
|
2017-06-04 23:29:03 +03:00
|
|
|
Object.assign(matcher, {
|
2017-06-04 03:11:08 +03:00
|
|
|
wantReturnValue: data.options.wantReturnValue,
|
2018-08-18 06:02:52 +03:00
|
|
|
removeCSS: data.options.removeCSS,
|
|
|
|
cssOrigin: data.options.cssOrigin,
|
2017-06-04 03:11:08 +03:00
|
|
|
jsCode: data.options.jsCode,
|
|
|
|
});
|
|
|
|
|
2017-06-04 23:29:03 +03:00
|
|
|
let script = contentScripts.get(matcher);
|
2017-04-15 03:00:51 +03:00
|
|
|
|
2017-11-24 21:17:33 +03:00
|
|
|
// Add the cssCode to the script, so that it can be converted into a cached URL.
|
|
|
|
await script.addCSSCode(data.options.cssCode);
|
|
|
|
delete data.options.cssCode;
|
|
|
|
|
2017-04-15 03:00:51 +03:00
|
|
|
return ExtensionContent.handleExtensionExecute(this.global, target, data.options, script);
|
|
|
|
case "WebNavigation:GetFrame":
|
|
|
|
return ExtensionContent.handleWebNavigationGetFrame(this.global, data.options);
|
|
|
|
case "WebNavigation:GetAllFrames":
|
|
|
|
return ExtensionContent.handleWebNavigationGetAllFrames(this.global);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Responsible for creating ExtensionContexts and injecting content
|
|
|
|
// scripts into them when new documents are created.
|
|
|
|
DocumentManager = {
|
|
|
|
globals: new Map(),
|
|
|
|
|
|
|
|
// Initialize listeners that we need regardless of whether extensions are
|
|
|
|
// enabled.
|
|
|
|
earlyInit() {
|
2018-08-18 08:09:23 +03:00
|
|
|
// eslint-disable-next-line mozilla/balanced-listeners
|
|
|
|
Services.obs.addObserver((subject) => this.initGlobal(subject),
|
|
|
|
"tab-content-frameloader-created");
|
2017-04-15 03:00:51 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
// Initialize a frame script global which extension contexts may be loaded
|
|
|
|
// into.
|
|
|
|
initGlobal(global) {
|
|
|
|
this.globals.set(global, new ExtensionGlobal(global));
|
2017-05-28 03:30:53 +03:00
|
|
|
// eslint-disable-next-line mozilla/balanced-listeners
|
|
|
|
global.addEventListener("unload", () => {
|
|
|
|
this.globals.delete(global);
|
|
|
|
});
|
2017-04-15 03:00:51 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
// Script loading
|
|
|
|
|
2017-04-16 18:32:59 +03:00
|
|
|
/**
|
|
|
|
* Checks that all parent frames for the given withdow either have the
|
|
|
|
* same add-on ID, or are special chrome-privileged documents such as
|
|
|
|
* about:addons or developer tools panels.
|
|
|
|
*
|
|
|
|
* @param {Window} window
|
|
|
|
* The window to check.
|
|
|
|
* @param {string} addonId
|
|
|
|
* The add-on ID to check.
|
|
|
|
* @returns {boolean}
|
|
|
|
*/
|
|
|
|
checkParentFrames(window, addonId) {
|
|
|
|
while (window.parent !== window) {
|
|
|
|
window = window.parent;
|
|
|
|
|
|
|
|
let principal = window.document.nodePrincipal;
|
|
|
|
|
|
|
|
if (Services.scriptSecurityManager.isSystemPrincipal(principal)) {
|
|
|
|
// The add-on manager is a special case, since it contains extension
|
|
|
|
// options pages in same-type <browser> frames.
|
|
|
|
if (window.location.href === "about:addons") {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (principal.addonId !== addonId) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
2017-05-26 22:07:06 +03:00
|
|
|
loadInto(policy, window) {
|
2017-05-26 07:57:48 +03:00
|
|
|
let extension = extensions.get(policy);
|
2017-05-26 22:07:06 +03:00
|
|
|
if (WebExtensionPolicy.isExtensionProcess && this.checkParentFrames(window, policy.id)) {
|
2017-04-16 18:32:59 +03:00
|
|
|
// We're in a top-level extension frame, or a sub-frame thereof,
|
|
|
|
// in the extension process. Inject the full extension page API.
|
2017-05-26 07:57:48 +03:00
|
|
|
ExtensionPageChild.initExtensionContext(extension, window);
|
2017-04-15 03:00:51 +03:00
|
|
|
} else {
|
2017-04-16 18:32:59 +03:00
|
|
|
// We're in a content sub-frame or not in the extension process.
|
|
|
|
// Only inject a minimal content script API.
|
2017-05-26 07:57:48 +03:00
|
|
|
ExtensionContent.initExtensionContext(extension, window);
|
2017-04-15 03:00:51 +03:00
|
|
|
}
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
ExtensionManager = {
|
2017-11-03 19:01:58 +03:00
|
|
|
// WeakMap<WebExtensionPolicy, Map<string, WebExtensionContentScript>>
|
2018-05-08 00:45:44 +03:00
|
|
|
registeredContentScripts: new DefaultWeakMap((policy) => new Map()),
|
2017-11-03 19:01:58 +03:00
|
|
|
|
2017-04-15 03:00:51 +03:00
|
|
|
init() {
|
|
|
|
MessageChannel.setupMessageManagers([Services.cpmm]);
|
|
|
|
|
|
|
|
Services.cpmm.addMessageListener("Extension:Startup", this);
|
|
|
|
Services.cpmm.addMessageListener("Extension:Shutdown", this);
|
|
|
|
Services.cpmm.addMessageListener("Extension:FlushJarCache", this);
|
2017-11-03 19:01:58 +03:00
|
|
|
Services.cpmm.addMessageListener("Extension:RegisterContentScript", this);
|
|
|
|
Services.cpmm.addMessageListener("Extension:UnregisterContentScripts", this);
|
2017-04-15 03:00:51 +03:00
|
|
|
|
2018-06-25 02:34:44 +03:00
|
|
|
for (let id of sharedData.get("extensions/activeIDs") || []) {
|
|
|
|
this.initExtension(getData({id}));
|
2017-04-15 03:00:51 +03:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-08-13 03:21:27 +03:00
|
|
|
initExtensionPolicy(extension) {
|
|
|
|
let policy = WebExtensionPolicy.getByID(extension.id);
|
2017-05-26 22:04:18 +03:00
|
|
|
if (!policy) {
|
2017-08-13 03:21:27 +03:00
|
|
|
let localizeCallback, allowedOrigins, webAccessibleResources;
|
2018-06-05 21:26:24 +03:00
|
|
|
let restrictSchemes = !extension.permissions.has("mozillaAddons");
|
|
|
|
|
2017-08-13 03:21:27 +03:00
|
|
|
if (extension.localize) {
|
|
|
|
// We have a real Extension object.
|
|
|
|
localizeCallback = extension.localize.bind(extension);
|
|
|
|
allowedOrigins = extension.whiteListedHosts;
|
|
|
|
webAccessibleResources = extension.webAccessibleResources;
|
|
|
|
} else {
|
|
|
|
// We have serialized extension data;
|
|
|
|
localizeCallback = str => extensions.get(policy).localize(str);
|
2018-06-05 21:26:24 +03:00
|
|
|
allowedOrigins = new MatchPatternSet(extension.whiteListedHosts, {restrictSchemes});
|
2017-08-13 03:21:27 +03:00
|
|
|
webAccessibleResources = extension.webAccessibleResources.map(host => new MatchGlob(host));
|
|
|
|
}
|
2017-05-26 22:04:18 +03:00
|
|
|
|
2018-06-25 02:34:44 +03:00
|
|
|
let {backgroundScripts} = extension;
|
|
|
|
if (!backgroundScripts && WebExtensionPolicy.isExtensionProcess) {
|
|
|
|
({backgroundScripts} = getData(extension, "extendedData") || {});
|
|
|
|
}
|
|
|
|
|
2017-05-26 07:57:48 +03:00
|
|
|
policy = new WebExtensionPolicy({
|
2017-08-13 03:21:27 +03:00
|
|
|
id: extension.id,
|
|
|
|
mozExtensionHostname: extension.uuid,
|
2017-08-12 07:22:18 +03:00
|
|
|
name: extension.name,
|
2017-08-13 03:21:27 +03:00
|
|
|
baseURL: extension.resourceURL,
|
2017-05-26 07:57:48 +03:00
|
|
|
|
2017-08-13 03:21:27 +03:00
|
|
|
permissions: Array.from(extension.permissions),
|
|
|
|
allowedOrigins,
|
|
|
|
webAccessibleResources,
|
2017-05-26 07:57:48 +03:00
|
|
|
|
2018-06-25 02:34:44 +03:00
|
|
|
contentSecurityPolicy: extension.contentSecurityPolicy,
|
2017-05-26 07:57:48 +03:00
|
|
|
|
2017-05-26 22:04:18 +03:00
|
|
|
localizeCallback,
|
2017-05-26 07:57:48 +03:00
|
|
|
|
2018-06-25 02:34:44 +03:00
|
|
|
backgroundScripts,
|
2017-05-26 07:57:48 +03:00
|
|
|
|
2018-05-10 04:55:59 +03:00
|
|
|
contentScripts: extension.contentScripts.map(script => parseScriptOptions(script, restrictSchemes)),
|
2017-05-26 07:57:48 +03:00
|
|
|
});
|
|
|
|
|
2018-01-13 00:21:03 +03:00
|
|
|
policy.debugName = `${JSON.stringify(policy.name)} (ID: ${policy.id}, ${policy.getURL()})`;
|
|
|
|
|
2018-04-04 08:22:07 +03:00
|
|
|
// Register any existent dynamically registered content script for the extension
|
2017-11-03 19:01:58 +03:00
|
|
|
// when a content process is started for the first time (which also cover
|
|
|
|
// a content process that crashed and it has been recreated).
|
|
|
|
const registeredContentScripts = this.registeredContentScripts.get(policy);
|
|
|
|
|
2018-06-25 02:34:44 +03:00
|
|
|
for (let [scriptId, options] of getData(extension, "contentScripts") || []) {
|
|
|
|
const parsedOptions = parseScriptOptions(options, restrictSchemes);
|
|
|
|
const script = new WebExtensionContentScript(policy, parsedOptions);
|
|
|
|
policy.registerContentScript(script);
|
|
|
|
registeredContentScripts.set(scriptId, script);
|
2017-11-03 19:01:58 +03:00
|
|
|
}
|
|
|
|
|
2017-05-26 07:57:48 +03:00
|
|
|
policy.active = true;
|
2017-08-13 03:21:27 +03:00
|
|
|
policy.initData = extension;
|
2017-05-26 07:57:48 +03:00
|
|
|
}
|
2017-05-26 22:04:18 +03:00
|
|
|
return policy;
|
|
|
|
},
|
2017-05-26 07:57:48 +03:00
|
|
|
|
2017-05-26 22:04:18 +03:00
|
|
|
initExtension(data) {
|
2018-06-25 02:34:44 +03:00
|
|
|
if (typeof data === "string") {
|
|
|
|
data = getData({id: data});
|
|
|
|
}
|
2017-05-26 22:04:18 +03:00
|
|
|
let policy = this.initExtensionPolicy(data);
|
2017-05-26 07:57:48 +03:00
|
|
|
|
2018-08-18 08:09:23 +03:00
|
|
|
policy.injectContentScripts();
|
2017-04-15 03:00:51 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
receiveMessage({name, data}) {
|
|
|
|
switch (name) {
|
|
|
|
case "Extension:Startup": {
|
2017-05-26 07:57:48 +03:00
|
|
|
this.initExtension(data);
|
2017-04-15 03:00:51 +03:00
|
|
|
|
|
|
|
Services.cpmm.sendAsyncMessage("Extension:StartupComplete");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case "Extension:Shutdown": {
|
2017-05-26 07:57:48 +03:00
|
|
|
let policy = WebExtensionPolicy.getByID(data.id);
|
|
|
|
|
2017-07-13 02:58:15 +03:00
|
|
|
if (policy) {
|
|
|
|
if (extensions.has(policy)) {
|
|
|
|
extensions.get(policy).shutdown();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isContentProcess) {
|
|
|
|
policy.active = false;
|
|
|
|
}
|
2017-05-11 06:26:01 +03:00
|
|
|
}
|
2017-06-04 23:29:03 +03:00
|
|
|
Services.cpmm.sendAsyncMessage("Extension:ShutdownComplete");
|
2017-04-15 03:00:51 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case "Extension:FlushJarCache": {
|
|
|
|
ExtensionUtils.flushJarCache(data.path);
|
|
|
|
Services.cpmm.sendAsyncMessage("Extension:FlushJarCacheComplete");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-11-03 19:01:58 +03:00
|
|
|
case "Extension:RegisterContentScript": {
|
|
|
|
let policy = WebExtensionPolicy.getByID(data.id);
|
|
|
|
|
|
|
|
if (policy) {
|
|
|
|
const registeredContentScripts = this.registeredContentScripts.get(policy);
|
|
|
|
|
|
|
|
if (registeredContentScripts.has(data.scriptId)) {
|
|
|
|
Cu.reportError(new Error(
|
|
|
|
`Registering content script ${data.scriptId} on ${data.id} more than once`));
|
|
|
|
} else {
|
|
|
|
try {
|
2018-05-10 04:55:59 +03:00
|
|
|
const parsedOptions = parseScriptOptions(data.options, !policy.hasPermission("mozillaAddons"));
|
2017-11-03 19:01:58 +03:00
|
|
|
const script = new WebExtensionContentScript(policy, parsedOptions);
|
|
|
|
policy.registerContentScript(script);
|
|
|
|
registeredContentScripts.set(data.scriptId, script);
|
|
|
|
} catch (e) {
|
|
|
|
Cu.reportError(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Services.cpmm.sendAsyncMessage("Extension:RegisterContentScriptComplete");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case "Extension:UnregisterContentScripts": {
|
|
|
|
let policy = WebExtensionPolicy.getByID(data.id);
|
|
|
|
|
|
|
|
if (policy) {
|
|
|
|
const registeredContentScripts = this.registeredContentScripts.get(policy);
|
|
|
|
|
|
|
|
for (const scriptId of data.scriptIds) {
|
|
|
|
const script = registeredContentScripts.get(scriptId);
|
|
|
|
if (script) {
|
|
|
|
try {
|
|
|
|
policy.unregisterContentScript(script);
|
|
|
|
registeredContentScripts.delete(scriptId);
|
|
|
|
} catch (e) {
|
|
|
|
Cu.reportError(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Services.cpmm.sendAsyncMessage("Extension:UnregisterContentScriptsComplete");
|
|
|
|
break;
|
|
|
|
}
|
2017-04-15 03:00:51 +03:00
|
|
|
}
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2017-06-05 01:38:11 +03:00
|
|
|
function ExtensionProcessScript() {
|
|
|
|
if (!ExtensionProcessScript.singleton) {
|
|
|
|
ExtensionProcessScript.singleton = this;
|
|
|
|
}
|
|
|
|
return ExtensionProcessScript.singleton;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExtensionProcessScript.singleton = null;
|
|
|
|
|
|
|
|
ExtensionProcessScript.prototype = {
|
|
|
|
classID: Components.ID("{21f9819e-4cdf-49f9-85a0-850af91a5058}"),
|
2018-04-23 06:55:06 +03:00
|
|
|
QueryInterface: ChromeUtils.generateQI([Ci.mozIExtensionProcessScript]),
|
2017-06-05 01:38:11 +03:00
|
|
|
|
2017-05-26 22:04:18 +03:00
|
|
|
get wrappedJSObject() { return this; },
|
|
|
|
|
2017-05-28 03:30:53 +03:00
|
|
|
getFrameData(global, force) {
|
|
|
|
let extGlobal = DocumentManager.globals.get(global);
|
|
|
|
return extGlobal && extGlobal.getFrameData(force);
|
|
|
|
},
|
|
|
|
|
2017-08-13 03:21:27 +03:00
|
|
|
initExtension(extension) {
|
|
|
|
return ExtensionManager.initExtensionPolicy(extension);
|
2017-05-26 22:04:18 +03:00
|
|
|
},
|
|
|
|
|
2017-05-26 22:07:06 +03:00
|
|
|
initExtensionDocument(policy, doc) {
|
2018-08-03 06:49:09 +03:00
|
|
|
if (DocumentManager.globals.has(doc.defaultView.docShell.messageManager)) {
|
2017-05-26 22:07:06 +03:00
|
|
|
DocumentManager.loadInto(policy, doc.defaultView);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2018-01-10 04:20:55 +03:00
|
|
|
getExtensionChild(id) {
|
|
|
|
let policy = WebExtensionPolicy.getByID(id);
|
|
|
|
if (policy) {
|
|
|
|
return extensions.get(policy);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-06-05 01:38:11 +03:00
|
|
|
preloadContentScript(contentScript) {
|
2017-06-04 23:29:03 +03:00
|
|
|
contentScripts.get(contentScript).preload();
|
2017-06-05 01:38:11 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
loadContentScript(contentScript, window) {
|
2018-08-18 08:09:23 +03:00
|
|
|
return contentScripts.get(contentScript).injectInto(window);
|
2017-06-05 01:38:11 +03:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ExtensionProcessScript]);
|
|
|
|
|
2017-04-15 03:00:51 +03:00
|
|
|
DocumentManager.earlyInit();
|
|
|
|
ExtensionManager.init();
|