author | Luca Greco <lgreco@mozilla.com> |
Fri, 30 Nov 2018 16:09:34 +0000 | |
changeset 449002 | 39b6008cb9cfb02228f4946463d458d4dee8a8df |
parent 449001 | 7fdaa201c7b3972f9f51af92d935436e6a77b936 |
child 449003 | 541cb39b63231ebdd85159013b9f384d39a13b29 |
push id | 35139 |
push user | ccoroiu@mozilla.com |
push date | Sat, 01 Dec 2018 02:30:08 +0000 |
treeherder | mozilla-central@22425b629a9d [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | zombie, robwu |
bugs | 1509339 |
milestone | 65.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/toolkit/components/extensions/ExtensionContent.jsm +++ b/toolkit/components/extensions/ExtensionContent.jsm @@ -719,16 +719,18 @@ class UserScript extends Script { } for (let key of Object.keys(userScriptAPIs)) { Schemas.exportLazyGetter(userScriptScope, key, () => { // Wrap the custom API methods exported to the userScript sandbox. return wrapUserScriptAPIMethod(userScriptAPIs[key], key); }); } + + context.userScriptsEvents.emit("on-before-script", clonedMetadata, userScriptScope); } } var contentScripts = new DefaultWeakMap(matcher => { const extension = processScript.extensions.get(matcher.extension); if ("userScriptOptions" in matcher) { return new UserScript(extension, matcher); @@ -848,16 +850,21 @@ class ContentScriptContextChild extends // A set of exported API methods provided by the extension to the userScripts sandboxes. this.userScriptAPIs = null; // Keep track if the userScript API script has been already executed in this context // (e.g. because there are more then one UserScripts that match the related webpage // and so the UserScript apiScript has already been executed). this.hasUserScriptAPIs = false; + + // A lazy created EventEmitter related to userScripts-specific events. + defineLazyGetter(this, "userScriptsEvents", () => { + return new ExtensionCommon.EventEmitter(); + }); } injectAPI() { if (!this.isExtensionPage) { throw new Error("Cannot inject extension API into non-extension window"); } // This is an iframe with content script API enabled (See Bug 1214658)
--- a/toolkit/components/extensions/child/ext-toolkit.js +++ b/toolkit/components/extensions/child/ext-toolkit.js @@ -72,16 +72,17 @@ extensions.registerModules({ ["userScripts"], ], }, userScriptsContent: { url: "chrome://extensions/content/child/ext-userScripts-content.js", scopes: ["content_child"], paths: [ ["userScripts", "setScriptAPIs"], + ["userScripts", "onBeforeScript"], ], }, webRequest: { url: "chrome://extensions/content/child/ext-webRequest.js", scopes: ["addon_child"], paths: [ ["webRequest"], ],
--- a/toolkit/components/extensions/child/ext-userScripts-content.js +++ b/toolkit/components/extensions/child/ext-userScripts-content.js @@ -17,12 +17,30 @@ this.userScriptsContent = class extends userScripts: { setScriptAPIs(exportedAPIMethods) { if (!userScriptsEnabled) { throw new ExtensionError(USERSCRIPT_DISABLED_ERRORMSG); } context.setUserScriptAPIs(exportedAPIMethods); }, + onBeforeScript: new EventManager({ + context, + name: "userScripts.onBeforeScript", + register: fire => { + let handler = (event, userScriptMetadata, userScriptSandbox) => { + const apiObj = Cu.createObjectIn(context.cloneScope); + apiObj.metadata = userScriptMetadata; + apiObj.global = userScriptSandbox; + + fire.raw(apiObj); + }; + + context.userScriptsEvents.on("on-before-script", handler); + return () => { + context.userScriptsEvents.off("on-before-script", handler); + }; + }, + }).api(), }, }; } };
--- a/toolkit/components/extensions/ext-toolkit.json +++ b/toolkit/components/extensions/ext-toolkit.json @@ -196,17 +196,18 @@ "paths": [ ["userScripts"] ] }, "userScriptsContent": { "schema": "chrome://extensions/content/schemas/user_scripts_content.json", "scopes": ["content_child"], "paths": [ - ["userScripts", "setScriptAPIs"] + ["userScripts", "setScriptAPIs"], + ["userScripts", "onBeforeScript"] ] }, "webNavigation": { "url": "chrome://extensions/content/parent/ext-webNavigation.js", "schema": "chrome://extensions/content/schemas/web_navigation.json", "scopes": ["addon_parent"], "paths": [ ["webNavigation"]
--- a/toolkit/components/extensions/schemas/user_scripts_content.json +++ b/toolkit/components/extensions/schemas/user_scripts_content.json @@ -24,11 +24,36 @@ "description": "Provides a set of custom API methods available to the registered userScripts", "parameters": [ { "name": "exportedAPIMethods", "$ref": "ExportedAPIMethods" } ] } + ], + "events": [ + { + "name": "onBeforeScript", + "permissions": ["manifest:user_scripts.api_script"], + "allowedContexts": ["content", "content_only"], + "type": "function", + "description": "Event called when a new userScript global has been created", + "parameters": [ + { + "type": "object", + "name": "userScript", + "properties": { + "metadata": { + "type": "any", + "description": "The userScript metadata (as set in userScripts.register)" + }, + "global": { + "type": "any", + "description": "The userScript global" + } + } + } + ] + } ] } ]