mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-14 18:51:28 +00:00
Bug 1368102: Part 5 - Move static content script matching into C++. r=mixedpuppy,zombie
MozReview-Commit-ID: Co04MoscqMx --HG-- extra : rebase_source : 4a9b4c3146f99b4fd7eb8724224e954a5b3967f2
This commit is contained in:
parent
884bb014cb
commit
bc5050f651
@ -573,6 +573,7 @@
|
||||
|
||||
; [Extensions]
|
||||
@RESPATH@/components/extensions-toolkit.manifest
|
||||
@RESPATH@/components/extension-process-script.js
|
||||
@RESPATH@/browser/components/extensions-browser.manifest
|
||||
|
||||
; Modules
|
||||
|
@ -441,6 +441,7 @@
|
||||
; [Extensions]
|
||||
@BINPATH@/components/extensions-toolkit.manifest
|
||||
@BINPATH@/components/extensions-mobile.manifest
|
||||
@BINPATH@/components/extension-process-script.js
|
||||
|
||||
; Features
|
||||
@BINPATH@/features/*
|
||||
|
@ -9,8 +9,17 @@
|
||||
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozIExtensionProcessScript.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsILoadInfo.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -24,6 +33,23 @@ using namespace extensions;
|
||||
"script-src 'self'; object-src 'self';"
|
||||
|
||||
|
||||
#define OBS_TOPIC_PRELOAD_SCRIPT "web-extension-preload-content-script"
|
||||
#define OBS_TOPIC_LOAD_SCRIPT "web-extension-load-content-script"
|
||||
|
||||
|
||||
static mozIExtensionProcessScript&
|
||||
ProcessScript()
|
||||
{
|
||||
static nsCOMPtr<mozIExtensionProcessScript> sProcessScript;
|
||||
|
||||
if (MOZ_UNLIKELY(!sProcessScript)) {
|
||||
sProcessScript = do_GetService("@mozilla.org/webextensions/extension-process-script;1");
|
||||
MOZ_RELEASE_ASSERT(sProcessScript);
|
||||
ClearOnShutdown(&sProcessScript);
|
||||
}
|
||||
return *sProcessScript;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* ExtensionPolicyService
|
||||
*****************************************************************************/
|
||||
@ -40,6 +66,14 @@ ExtensionPolicyService::GetSingleton()
|
||||
return *sExtensionPolicyService.get();
|
||||
}
|
||||
|
||||
ExtensionPolicyService::ExtensionPolicyService()
|
||||
{
|
||||
mObs = services::GetObserverService();
|
||||
MOZ_RELEASE_ASSERT(mObs);
|
||||
|
||||
RegisterObservers();
|
||||
}
|
||||
|
||||
|
||||
WebExtensionPolicy*
|
||||
ExtensionPolicyService::GetByURL(const URLInfo& aURL)
|
||||
@ -114,6 +148,134 @@ ExtensionPolicyService::DefaultCSP(nsAString& aDefaultCSP) const
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Content script management
|
||||
*****************************************************************************/
|
||||
|
||||
void
|
||||
ExtensionPolicyService::RegisterObservers()
|
||||
{
|
||||
mObs->AddObserver(this, "content-document-global-created", false);
|
||||
mObs->AddObserver(this, "document-element-inserted", false);
|
||||
if (XRE_IsContentProcess()) {
|
||||
mObs->AddObserver(this, "http-on-opening-request", false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ExtensionPolicyService::UnregisterObservers()
|
||||
{
|
||||
mObs->RemoveObserver(this, "content-document-global-created");
|
||||
mObs->RemoveObserver(this, "document-element-inserted");
|
||||
if (XRE_IsContentProcess()) {
|
||||
mObs->RemoveObserver(this, "http-on-opening-request");
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
ExtensionPolicyService::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
|
||||
{
|
||||
if (!strcmp(aTopic, "content-document-global-created")) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win = do_QueryInterface(aSubject);
|
||||
if (win) {
|
||||
CheckWindow(win);
|
||||
}
|
||||
} else if (!strcmp(aTopic, "document-element-inserted")) {
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aSubject);
|
||||
if (doc) {
|
||||
CheckDocument(doc);
|
||||
}
|
||||
} else if (!strcmp(aTopic, "http-on-opening-request")) {
|
||||
nsCOMPtr<nsIChannel> chan = do_QueryInterface(aSubject);
|
||||
if (chan) {
|
||||
CheckRequest(chan);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Checks a request for matching content scripts, and begins pre-loading them
|
||||
// if necessary.
|
||||
void
|
||||
ExtensionPolicyService::CheckRequest(nsIChannel* aChannel)
|
||||
{
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
|
||||
if (!loadInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto loadType = loadInfo->GetExternalContentPolicyType();
|
||||
if (loadType != nsIContentPolicy::TYPE_DOCUMENT &&
|
||||
loadType != nsIContentPolicy::TYPE_SUBDOCUMENT) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (NS_FAILED(aChannel->GetURI(getter_AddRefs(uri)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
CheckContentScripts({uri.get(), loadInfo}, true);
|
||||
}
|
||||
|
||||
// Checks a document, just after the document element has been inserted, for
|
||||
// matching content scripts or extension principals, and loads them if
|
||||
// necessary.
|
||||
void
|
||||
ExtensionPolicyService::CheckDocument(nsIDocument* aDocument)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win = aDocument->GetWindow();
|
||||
if (win) {
|
||||
CheckContentScripts(win.get(), false);
|
||||
}
|
||||
}
|
||||
|
||||
// Checks for loads of about:blank into new window globals, and loads any
|
||||
// matching content scripts. about:blank loads do not trigger document element
|
||||
// inserted events, so they're the only load type that are special cased this
|
||||
// way.
|
||||
void
|
||||
ExtensionPolicyService::CheckWindow(nsPIDOMWindowOuter* aWindow)
|
||||
{
|
||||
// We only care about non-initial document loads here. The initial
|
||||
// about:blank document will usually be re-used to load another document.
|
||||
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
|
||||
if (!doc || doc->IsInitialDocument()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> aboutBlank;
|
||||
NS_ENSURE_SUCCESS_VOID(NS_NewURI(getter_AddRefs(aboutBlank),
|
||||
"about:blank"));
|
||||
|
||||
nsCOMPtr<nsIURI> uri = doc->GetDocumentURI();
|
||||
bool equal;
|
||||
if (NS_FAILED(uri->EqualsExceptRef(aboutBlank, &equal)) || !equal) {
|
||||
return;
|
||||
}
|
||||
|
||||
CheckContentScripts(aWindow, false);
|
||||
}
|
||||
|
||||
void
|
||||
ExtensionPolicyService::CheckContentScripts(const DocInfo& aDocInfo, bool aIsPreload)
|
||||
{
|
||||
for (auto iter = mExtensions.Iter(); !iter.Done(); iter.Next()) {
|
||||
RefPtr<WebExtensionPolicy> policy = iter.Data();
|
||||
|
||||
for (auto& script : policy->ContentScripts()) {
|
||||
if (script->Matches(aDocInfo)) {
|
||||
if (aIsPreload) {
|
||||
ProcessScript().PreloadContentScript(script);
|
||||
} else {
|
||||
ProcessScript().LoadContentScript(script, aDocInfo.GetWindow());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* nsIAddonPolicyService
|
||||
*****************************************************************************/
|
||||
@ -213,7 +375,8 @@ NS_IMPL_CYCLE_COLLECTION(ExtensionPolicyService, mExtensions, mExtensionHosts)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ExtensionPolicyService)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIAddonPolicyService)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAddonPolicyService)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ExtensionPolicyService)
|
||||
|
@ -12,20 +12,34 @@
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsIAddonPolicyService.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsPointerHashKeys.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
namespace mozilla {
|
||||
class nsIChannel;
|
||||
class nsIObserverService;
|
||||
class nsIDocument;
|
||||
class nsIPIDOMWindowOuter;
|
||||
|
||||
namespace mozilla {
|
||||
namespace extensions {
|
||||
class DocInfo;
|
||||
}
|
||||
|
||||
using extensions::DocInfo;
|
||||
using extensions::WebExtensionPolicy;
|
||||
|
||||
class ExtensionPolicyService final : public nsIAddonPolicyService
|
||||
, public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(ExtensionPolicyService)
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ExtensionPolicyService,
|
||||
nsIAddonPolicyService)
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_NSIADDONPOLICYSERVICE
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
static ExtensionPolicyService& GetSingleton();
|
||||
|
||||
@ -65,10 +79,21 @@ protected:
|
||||
virtual ~ExtensionPolicyService() = default;
|
||||
|
||||
private:
|
||||
ExtensionPolicyService() = default;
|
||||
ExtensionPolicyService();
|
||||
|
||||
void RegisterObservers();
|
||||
void UnregisterObservers();
|
||||
|
||||
void CheckRequest(nsIChannel* aChannel);
|
||||
void CheckDocument(nsIDocument* aDocument);
|
||||
void CheckWindow(nsPIDOMWindowOuter* aWindow);
|
||||
|
||||
void CheckContentScripts(const DocInfo& aDocInfo, bool aIsPreload);
|
||||
|
||||
nsRefPtrHashtable<nsPtrHashKey<const nsIAtom>, WebExtensionPolicy> mExtensions;
|
||||
nsRefPtrHashtable<nsCStringHashKey, WebExtensionPolicy> mExtensionHosts;
|
||||
|
||||
nsCOMPtr<nsIObserverService> mObs;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -48,6 +48,14 @@ public:
|
||||
|
||||
uint64_t FrameID() const;
|
||||
|
||||
nsPIDOMWindowOuter* GetWindow() const
|
||||
{
|
||||
if (mObj.is<Window>()) {
|
||||
return mObj.as<Window>();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void SetURL(const URLInfo& aURL);
|
||||
|
||||
|
@ -26,11 +26,15 @@ XPCOMUtils.defineLazyModuleGetter(this, "ExtensionContent",
|
||||
"resource://gre/modules/ExtensionContent.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionPageChild",
|
||||
"resource://gre/modules/ExtensionPageChild.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionUtils",
|
||||
"resource://gre/modules/ExtensionUtils.jsm");
|
||||
|
||||
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "console", () => ExtensionUtils.getConsole());
|
||||
XPCOMUtils.defineLazyGetter(this, "getInnerWindowID", () => ExtensionUtils.getInnerWindowID);
|
||||
|
||||
const {
|
||||
DefaultWeakMap,
|
||||
getInnerWindowID,
|
||||
} = ExtensionUtils;
|
||||
|
||||
// We need to avoid touching Services.appinfo here in order to prevent
|
||||
// the wrong version from being cached during xpcshell test startup.
|
||||
@ -62,10 +66,6 @@ class ScriptMatcher {
|
||||
this._script = null;
|
||||
}
|
||||
|
||||
get matchAboutBlank() {
|
||||
return this.matcher.matchAboutBlank;
|
||||
}
|
||||
|
||||
get script() {
|
||||
if (!this._script) {
|
||||
this._script = new ExtensionContent.Script(this.extension.realExtension,
|
||||
@ -81,10 +81,6 @@ class ScriptMatcher {
|
||||
script.compileScripts();
|
||||
}
|
||||
|
||||
matchesLoadInfo(uri, loadInfo) {
|
||||
return this.matcher.matchesLoadInfo(uri, loadInfo);
|
||||
}
|
||||
|
||||
matchesWindow(window) {
|
||||
return this.matcher.matchesWindow(window);
|
||||
}
|
||||
@ -157,6 +153,10 @@ class ExtensionGlobal {
|
||||
}
|
||||
}
|
||||
|
||||
let stubExtensions = new WeakMap();
|
||||
let scriptMatchers = new DefaultWeakMap(matcher => new ScriptMatcher(stubExtensions.get(matcher.extension),
|
||||
matcher));
|
||||
|
||||
// Responsible for creating ExtensionContexts and injecting content
|
||||
// scripts into them when new documents are created.
|
||||
DocumentManager = {
|
||||
@ -176,32 +176,6 @@ DocumentManager = {
|
||||
Services.obs.removeObserver(this, "document-element-inserted");
|
||||
},
|
||||
|
||||
// Initialize listeners that we need when any extension content script is
|
||||
// enabled.
|
||||
initMatchers() {
|
||||
if (isContentProcess) {
|
||||
Services.obs.addObserver(this, "http-on-opening-request");
|
||||
}
|
||||
},
|
||||
uninitMatchers() {
|
||||
if (isContentProcess) {
|
||||
Services.obs.removeObserver(this, "http-on-opening-request");
|
||||
}
|
||||
},
|
||||
|
||||
// Initialize listeners that we need when any about:blank content script is
|
||||
// enabled.
|
||||
//
|
||||
// Loads of about:blank are special, and do not trigger "document-element-inserted"
|
||||
// observers. So if we have any scripts that match about:blank, we also need
|
||||
// to observe "content-document-global-created".
|
||||
initAboutBlankMatchers() {
|
||||
Services.obs.addObserver(this, "content-document-global-created");
|
||||
},
|
||||
uninitAboutBlankMatchers() {
|
||||
Services.obs.removeObserver(this, "content-document-global-created");
|
||||
},
|
||||
|
||||
extensionProcessInitialized: false,
|
||||
initExtensionProcess() {
|
||||
if (this.extensionProcessInitialized || !ExtensionManagement.isExtensionProcess) {
|
||||
@ -243,82 +217,20 @@ DocumentManager = {
|
||||
}
|
||||
this.extensionCount++;
|
||||
|
||||
for (let script of extension.scripts) {
|
||||
this.addContentScript(script);
|
||||
}
|
||||
|
||||
this.injectExtensionScripts(extension);
|
||||
},
|
||||
uninitExtension(extension) {
|
||||
for (let script of extension.scripts) {
|
||||
this.removeContentScript(script);
|
||||
}
|
||||
|
||||
this.extensionCount--;
|
||||
if (this.extensionCount === 0) {
|
||||
this.uninit();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
extensionCount: 0,
|
||||
matchAboutBlankCount: 0,
|
||||
|
||||
contentScripts: new Set(),
|
||||
|
||||
addContentScript(script) {
|
||||
if (this.contentScripts.size == 0) {
|
||||
this.initMatchers();
|
||||
}
|
||||
|
||||
if (script.matchAboutBlank) {
|
||||
if (this.matchAboutBlankCount == 0) {
|
||||
this.initAboutBlankMatchers();
|
||||
}
|
||||
this.matchAboutBlankCount++;
|
||||
}
|
||||
|
||||
this.contentScripts.add(script);
|
||||
},
|
||||
removeContentScript(script) {
|
||||
this.contentScripts.delete(script);
|
||||
|
||||
if (this.contentScripts.size == 0) {
|
||||
this.uninitMatchers();
|
||||
}
|
||||
|
||||
if (script.matchAboutBlank) {
|
||||
this.matchAboutBlankCount--;
|
||||
if (this.matchAboutBlankCount == 0) {
|
||||
this.uninitAboutBlankMatchers();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Listeners
|
||||
|
||||
observers: {
|
||||
async "content-document-global-created"(window) {
|
||||
// We only care about about:blank here, since it doesn't trigger
|
||||
// "document-element-inserted".
|
||||
if ((window.location && window.location.href !== "about:blank") ||
|
||||
// Make sure we only load into frames that belong to tabs, or other
|
||||
// special areas that we want to load content scripts into.
|
||||
!this.globals.has(getMessageManager(window))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We can't tell for certain whether the final document will actually be
|
||||
// about:blank at this point, though, so wait for the DOM to finish
|
||||
// loading and check again before injecting scripts.
|
||||
await new Promise(resolve => window.addEventListener(
|
||||
"DOMContentLoaded", resolve, {once: true, capture: true}));
|
||||
|
||||
if (window.location.href === "about:blank") {
|
||||
this.injectWindowScripts(window);
|
||||
}
|
||||
},
|
||||
|
||||
"document-element-inserted"(document) {
|
||||
let window = document.defaultView;
|
||||
if (!document.location || !window ||
|
||||
@ -328,24 +240,9 @@ DocumentManager = {
|
||||
return;
|
||||
}
|
||||
|
||||
this.injectWindowScripts(window);
|
||||
this.loadInto(window);
|
||||
},
|
||||
|
||||
"http-on-opening-request"(subject, topic, data) {
|
||||
// If this request is a docshell load, check whether any of our scripts
|
||||
// are likely to be loaded into it, and begin preloading the ones that
|
||||
// are.
|
||||
let {loadInfo} = subject.QueryInterface(Ci.nsIChannel);
|
||||
if (loadInfo) {
|
||||
let {externalContentPolicyType: type} = loadInfo;
|
||||
if (type === Ci.nsIContentPolicy.TYPE_DOCUMENT ||
|
||||
type === Ci.nsIContentPolicy.TYPE_SUBDOCUMENT) {
|
||||
this.preloadScripts(subject.URI, loadInfo);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"tab-content-frameloader-created"(global) {
|
||||
this.initGlobal(global);
|
||||
},
|
||||
@ -359,30 +256,14 @@ DocumentManager = {
|
||||
|
||||
injectExtensionScripts(extension) {
|
||||
for (let window of this.enumerateWindows()) {
|
||||
for (let script of extension.scripts) {
|
||||
for (let script of extension.policy.contentScripts) {
|
||||
if (script.matchesWindow(window)) {
|
||||
script.injectInto(window);
|
||||
scriptMatchers.get(script).injectInto(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
injectWindowScripts(window) {
|
||||
for (let script of this.contentScripts) {
|
||||
if (script.matchesWindow(window)) {
|
||||
script.injectInto(window);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
preloadScripts(uri, loadInfo) {
|
||||
for (let script of this.contentScripts) {
|
||||
if (script.matchesLoadInfo(uri, loadInfo)) {
|
||||
script.preload();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks that all parent frames for the given withdow either have the
|
||||
* same add-on ID, or are special chrome-privileged documents such as
|
||||
@ -495,6 +376,8 @@ class StubExtension {
|
||||
} else {
|
||||
this.policy = WebExtensionPolicy.getByID(this.id);
|
||||
}
|
||||
|
||||
stubExtensions.set(this.policy, this);
|
||||
}
|
||||
|
||||
shutdown() {
|
||||
@ -597,5 +480,31 @@ ExtensionManager = {
|
||||
},
|
||||
};
|
||||
|
||||
function ExtensionProcessScript() {
|
||||
if (!ExtensionProcessScript.singleton) {
|
||||
ExtensionProcessScript.singleton = this;
|
||||
}
|
||||
return ExtensionProcessScript.singleton;
|
||||
}
|
||||
|
||||
ExtensionProcessScript.singleton = null;
|
||||
|
||||
ExtensionProcessScript.prototype = {
|
||||
classID: Components.ID("{21f9819e-4cdf-49f9-85a0-850af91a5058}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.mozIExtensionProcessScript]),
|
||||
|
||||
preloadContentScript(contentScript) {
|
||||
scriptMatchers.get(contentScript).preload();
|
||||
},
|
||||
|
||||
loadContentScript(contentScript, window) {
|
||||
if (DocumentManager.globals.has(getMessageManager(window))) {
|
||||
scriptMatchers.get(contentScript).injectInto(window);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ExtensionProcessScript]);
|
||||
|
||||
DocumentManager.earlyInit();
|
||||
ExtensionManager.init();
|
||||
|
@ -7,3 +7,7 @@ category webextension-scripts-addon toolkit chrome://extensions/content/ext-c-to
|
||||
category webextension-schemas events chrome://extensions/content/schemas/events.json
|
||||
category webextension-schemas native_host_manifest chrome://extensions/content/schemas/native_host_manifest.json
|
||||
category webextension-schemas types chrome://extensions/content/schemas/types.json
|
||||
|
||||
|
||||
component {21f9819e-4cdf-49f9-85a0-850af91a5058} extension-process-script.js
|
||||
contract @mozilla.org/webextensions/extension-process-script;1 {21f9819e-4cdf-49f9-85a0-850af91a5058}
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
toolkit.jar:
|
||||
% content extensions %content/extensions/
|
||||
content/extensions/extension-process-script.js
|
||||
content/extensions/ext-alarms.js
|
||||
content/extensions/ext-backgroundPage.js
|
||||
content/extensions/ext-browser-content.js
|
||||
|
@ -32,6 +32,7 @@ EXTRA_JS_MODULES += [
|
||||
]
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'extension-process-script.js',
|
||||
'extensions-toolkit.manifest',
|
||||
]
|
||||
|
||||
@ -45,6 +46,12 @@ DIRS += [
|
||||
'webrequest',
|
||||
]
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'mozIExtensionProcessScript.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'webextensions'
|
||||
|
||||
EXPORTS.mozilla = [
|
||||
'ExtensionPolicyService.h',
|
||||
]
|
||||
|
16
toolkit/components/extensions/mozIExtensionProcessScript.idl
Normal file
16
toolkit/components/extensions/mozIExtensionProcessScript.idl
Normal file
@ -0,0 +1,16 @@
|
||||
/* 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/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface mozIDOMWindowProxy;
|
||||
|
||||
[scriptable,uuid(6b09dc51-6caa-4ca7-9d6d-30c87258a630)]
|
||||
interface mozIExtensionProcessScript : nsISupports
|
||||
{
|
||||
void preloadContentScript(in nsISupports contentScript);
|
||||
|
||||
void loadContentScript(in nsISupports contentScript, in mozIDOMWindowProxy window);
|
||||
|
||||
};
|
@ -67,7 +67,7 @@ add_task(async function test_contentscript_cache() {
|
||||
let {ExtensionManager} = Components.utils.import("resource://gre/modules/ExtensionChild.jsm", {});
|
||||
let ext = ExtensionManager.extensions.get(extensionId);
|
||||
|
||||
if (ext) {
|
||||
if (ext && ext.staticScripts) {
|
||||
assert.equal(ext.staticScripts.size, 0, "Should have no cached scripts in the parent process");
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,12 @@ XPCOMUtils.defineLazyGetter(this, "CertUtils", function() {
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, "WEBEXT_PERMISSION_PROMPTS",
|
||||
PREF_WEBEXT_PERM_PROMPTS, false);
|
||||
|
||||
Services.ppmm.loadProcessScript("chrome://extensions/content/extension-process-script.js", true);
|
||||
// Initialize the WebExtension process script service as early as possible,
|
||||
// since it needs to be able to track things like new frameLoader globals that
|
||||
// are created before other framework code has been initialized.
|
||||
Services.ppmm.loadProcessScript(
|
||||
"data:,Components.classes['@mozilla.org/webextensions/extension-process-script;1'].getService()",
|
||||
true);
|
||||
|
||||
const INTEGER = /^[1-9]\d*$/;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user