Bug 1425104: Part 1b - Split matching logic for content scripts into MozDocumentMatcher base class. r?zombie
MozReview-Commit-ID: JAOWZcB4hZW
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -574,16 +574,21 @@ DOMInterfaces = {
'nativeType': 'mozilla::dom::HTMLCanvasPrintState',
},
'MozChannel': {
'nativeType': 'nsIChannel',
'notflattened': True
},
+'MozDocumentMatcher': {
+ 'nativeType': 'mozilla::extensions::MozDocumentMatcher',
+ 'headerFile': 'mozilla/extensions/WebExtensionContentScript.h',
+},
+
'MozStorageAsyncStatementParams': {
'headerFile': 'mozilla/storage/mozStorageAsyncStatementParams.h',
'nativeType': 'mozilla::storage::AsyncStatementParams',
},
'MozStorageStatementParams': {
'headerFile': 'mozilla/storage/mozStorageStatementParams.h',
'nativeType': 'mozilla::storage::StatementParams',
--- a/dom/chrome-webidl/WebExtensionContentScript.webidl
+++ b/dom/chrome-webidl/WebExtensionContentScript.webidl
@@ -1,96 +1,53 @@
/* 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/. */
interface LoadInfo;
interface URI;
interface WindowProxy;
-/**
- * Describes the earliest point in the load cycle at which a script should
- * run.
- */
-enum ContentScriptRunAt {
- /**
- * The point in the load cycle just after the document element has been
- * inserted, before any page scripts have been allowed to run.
- */
- "document_start",
- /**
- * The point after which the page DOM has fully loaded, but before all page
- * resources have necessarily been loaded. Corresponds approximately to the
- * DOMContentLoaded event.
- */
- "document_end",
- /**
- * The first point after the page and all of its resources has fully loaded
- * when the event loop is idle, and can run scripts without delaying a paint
- * event.
- */
- "document_idle",
-};
-
-[Constructor(WebExtensionPolicy extension, WebExtensionContentScriptInit options), ChromeOnly, Exposed=System]
-interface WebExtensionContentScript {
+[Constructor(MozDocumentMatcherInit options), ChromeOnly, Exposed=System]
+interface MozDocumentMatcher {
/**
* Returns true if the script's match and exclude patterns match the given
* URI, without reference to attributes such as `allFrames`.
*/
boolean matchesURI(URI uri);
/**
- * Returns true if the script matches the given URI and LoadInfo objects.
+ * Returns true if the the given URI and LoadInfo objects match.
* This should be used to determine whether to begin pre-loading a content
* script based on network events.
*/
boolean matchesLoadInfo(URI uri, LoadInfo loadInfo);
/**
- * Returns true if the script matches the given window. This should be used
+ * Returns true if the given window matches. This should be used
* to determine whether to run a script in a window at load time.
*/
boolean matchesWindow(WindowProxy window);
/**
- * The policy object for the extension that this script belongs to.
- */
- [Constant]
- readonly attribute WebExtensionPolicy extension;
-
- /**
- * If true, this script runs in all frames. If false, it only runs in
- * top-level frames.
+ * If true, match all frames. If false, match only top-level frames.
*/
[Constant]
readonly attribute boolean allFrames;
/**
* If true, this (misleadingly-named, but inherited from Chrome) attribute
- * causes the script to run in frames with URLs which inherit a principal
- * that matches one of the match patterns, such as about:blank or
- * about:srcdoc. If false, the script only runs in frames with an explicit
- * matching URL.
+ * causes us to match frames with URLs which inherit a principal that
+ * matches one of the match patterns, such as about:blank or about:srcdoc.
+ * If false, we only match frames with an explicit matching URL.
*/
[Constant]
readonly attribute boolean matchAboutBlank;
/**
- * The earliest point in the load cycle at which this script should run. For
- * static content scripts, in extensions which were present at browser
- * startup, the browser makes every effort to make sure that the script runs
- * no later than this point in the load cycle. For dynamic content scripts,
- * and scripts from extensions installed during this session, the scripts
- * may run at a later point.
- */
- [Constant]
- readonly attribute ContentScriptRunAt runAt;
-
- /**
* The outer window ID of the frame in which to run the script, or 0 if it
* should run in the top-level frame. Should only be used for
* dynamically-injected scripts.
*/
[Constant]
readonly attribute unsigned long long? frameID;
/**
@@ -119,45 +76,91 @@ interface WebExtensionContentScript {
/**
* A set of glob matchers for URLs in which this script should not run, even
* if they match other include patterns or globs.
*/
[Cached, Constant, Frozen]
readonly attribute sequence<MatchGlob>? excludeGlobs;
/**
+ * The policy object for the extension that this matcher belongs to.
+ */
+ [Constant]
+ readonly attribute WebExtensionPolicy? extension;
+};
+
+dictionary MozDocumentMatcherInit {
+ boolean allFrames = false;
+
+ boolean matchAboutBlank = false;
+
+ unsigned long long? frameID = null;
+
+ required MatchPatternSet matches;
+
+ MatchPatternSet? excludeMatches = null;
+
+ sequence<MatchGlob>? includeGlobs = null;
+
+ sequence<MatchGlob>? excludeGlobs = null;
+
+ boolean hasActiveTabPermission = false;
+};
+
+/**
+ * Describes the earliest point in the load cycle at which a script should
+ * run.
+ */
+enum ContentScriptRunAt {
+ /**
+ * The point in the load cycle just after the document element has been
+ * inserted, before any page scripts have been allowed to run.
+ */
+ "document_start",
+ /**
+ * The point after which the page DOM has fully loaded, but before all page
+ * resources have necessarily been loaded. Corresponds approximately to the
+ * DOMContentLoaded event.
+ */
+ "document_end",
+ /**
+ * The first point after the page and all of its resources has fully loaded
+ * when the event loop is idle, and can run scripts without delaying a paint
+ * event.
+ */
+ "document_idle",
+};
+
+[Constructor(WebExtensionPolicy extension, WebExtensionContentScriptInit options), ChromeOnly, Exposed=System]
+interface WebExtensionContentScript : MozDocumentMatcher {
+ /**
+ * The earliest point in the load cycle at which this script should run. For
+ * static content scripts, in extensions which were present at browser
+ * startup, the browser makes every effort to make sure that the script runs
+ * no later than this point in the load cycle. For dynamic content scripts,
+ * and scripts from extensions installed during this session, the scripts
+ * may run at a later point.
+ */
+ [Constant]
+ readonly attribute ContentScriptRunAt runAt;
+
+ /**
* A set of paths, relative to the extension root, of CSS sheets to inject
* into matching pages.
*/
[Cached, Constant, Frozen]
readonly attribute sequence<DOMString> cssPaths;
/**
* A set of paths, relative to the extension root, of JavaScript scripts to
* execute in matching pages.
*/
[Cached, Constant, Frozen]
readonly attribute sequence<DOMString> jsPaths;
};
-dictionary WebExtensionContentScriptInit {
- boolean allFrames = false;
-
- boolean matchAboutBlank = false;
-
+dictionary WebExtensionContentScriptInit : MozDocumentMatcherInit {
ContentScriptRunAt runAt = "document_idle";
- unsigned long long? frameID = null;
-
- boolean hasActiveTabPermission = false;
-
- required MatchPatternSet matches;
-
- MatchPatternSet? excludeMatches = null;
-
- sequence<MatchGlob>? includeGlobs = null;
-
- sequence<MatchGlob>? excludeGlobs = null;
-
sequence<DOMString> cssPaths = [];
sequence<DOMString> jsPaths = [];
};
--- a/toolkit/components/extensions/WebExtensionContentScript.h
+++ b/toolkit/components/extensions/WebExtensionContentScript.h
@@ -75,122 +75,145 @@ private:
using Window = nsPIDOMWindowOuter*;
using LoadInfo = nsILoadInfo*;
const Variant<LoadInfo, Window> mObj;
};
-class WebExtensionContentScript final : public nsISupports
- , public nsWrapperCache
+class MozDocumentMatcher : public nsISupports
+ , public nsWrapperCache
{
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebExtensionContentScript)
-
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MozDocumentMatcher)
using MatchGlobArray = nsTArray<RefPtr<MatchGlob>>;
- using RunAtEnum = dom::ContentScriptRunAt;
- static already_AddRefed<WebExtensionContentScript>
+ static already_AddRefed<MozDocumentMatcher>
Constructor(dom::GlobalObject& aGlobal,
- WebExtensionPolicy& aExtension,
- const ContentScriptInit& aInit,
+ const dom::MozDocumentMatcherInit& aInit,
ErrorResult& aRv);
-
bool Matches(const DocInfo& aDoc) const;
bool MatchesURI(const URLInfo& aURL) const;
bool MatchesLoadInfo(const URLInfo& aURL, nsILoadInfo* aLoadInfo) const
{
return Matches({aURL, aLoadInfo});
}
bool MatchesWindow(nsPIDOMWindowOuter* aWindow) const
{
return Matches(aWindow);
}
+ WebExtensionPolicy* GetExtension() { return mExtension; }
+
WebExtensionPolicy* Extension() { return mExtension; }
const WebExtensionPolicy* Extension() const { return mExtension; }
bool AllFrames() const { return mAllFrames; }
bool MatchAboutBlank() const { return mMatchAboutBlank; }
- RunAtEnum RunAt() const { return mRunAt; }
-
- Nullable<uint64_t> GetFrameID() const { return mFrameID; }
MatchPatternSet* Matches() { return mMatches; }
const MatchPatternSet* GetMatches() const { return mMatches; }
MatchPatternSet* GetExcludeMatches() { return mExcludeMatches; }
const MatchPatternSet* GetExcludeMatches() const { return mExcludeMatches; }
void GetIncludeGlobs(Nullable<MatchGlobArray>& aGlobs)
{
ToNullable(mExcludeGlobs, aGlobs);
}
void GetExcludeGlobs(Nullable<MatchGlobArray>& aGlobs)
{
ToNullable(mExcludeGlobs, aGlobs);
}
+ Nullable<uint64_t> GetFrameID() const { return mFrameID; }
+
+
+ WebExtensionPolicy* GetParentObject() const { return mExtension; }
+ virtual JSObject* WrapObject(JSContext* aCx, JS::HandleObject aGivenProto) override;
+
+protected:
+ friend class WebExtensionPolicy;
+
+ virtual ~MozDocumentMatcher() = default;
+
+ MozDocumentMatcher(const dom::MozDocumentMatcherInit& aInit,
+ ErrorResult& aRv);
+
+ RefPtr<WebExtensionPolicy> mExtension;
+
+ bool mHasActiveTabPermission;
+ bool mRestricted;
+
+ RefPtr<MatchPatternSet> mMatches;
+ RefPtr<MatchPatternSet> mExcludeMatches;
+
+ Nullable<MatchGlobSet> mIncludeGlobs;
+ Nullable<MatchGlobSet> mExcludeGlobs;
+
+
+ bool mAllFrames;
+ Nullable<uint64_t> mFrameID;
+ bool mMatchAboutBlank;
+
+private:
+ template <typename T, typename U>
+ void
+ ToNullable(const Nullable<T>& aInput, Nullable<U>& aOutput)
+ {
+ if (aInput.IsNull()) {
+ aOutput.SetNull();
+ } else {
+ aOutput.SetValue(aInput.Value());
+ }
+ }
+};
+
+class WebExtensionContentScript final : public MozDocumentMatcher
+{
+public:
+
+ using RunAtEnum = dom::ContentScriptRunAt;
+
+ static already_AddRefed<WebExtensionContentScript>
+ Constructor(dom::GlobalObject& aGlobal,
+ WebExtensionPolicy& aExtension,
+ const ContentScriptInit& aInit,
+ ErrorResult& aRv);
+
+ RunAtEnum RunAt() const { return mRunAt; }
+
void GetCssPaths(nsTArray<nsString>& aPaths) const
{
aPaths.AppendElements(mCssPaths);
}
void GetJsPaths(nsTArray<nsString>& aPaths) const
{
aPaths.AppendElements(mJsPaths);
}
-
- WebExtensionPolicy* GetParentObject() const { return mExtension; }
-
virtual JSObject* WrapObject(JSContext* aCx, JS::HandleObject aGivenProto) override;
protected:
friend class WebExtensionPolicy;
virtual ~WebExtensionContentScript() = default;
WebExtensionContentScript(WebExtensionPolicy& aExtension,
const ContentScriptInit& aInit,
ErrorResult& aRv);
private:
- RefPtr<WebExtensionPolicy> mExtension;
-
- bool mHasActiveTabPermission;
- bool mRestricted;
-
- RefPtr<MatchPatternSet> mMatches;
- RefPtr<MatchPatternSet> mExcludeMatches;
-
- Nullable<MatchGlobSet> mIncludeGlobs;
- Nullable<MatchGlobSet> mExcludeGlobs;
-
nsTArray<nsString> mCssPaths;
nsTArray<nsString> mJsPaths;
RunAtEnum mRunAt;
-
- bool mAllFrames;
- Nullable<uint64_t> mFrameID;
- bool mMatchAboutBlank;
-
- template <typename T, typename U>
- void
- ToNullable(const Nullable<T>& aInput, Nullable<U>& aOutput)
- {
- if (aInput.IsNull()) {
- aOutput.SetNull();
- } else {
- aOutput.SetValue(aInput.Value());
- }
- }
};
} // namespace extensions
} // namespace mozilla
#endif // mozilla_extensions_WebExtensionContentScript_h
--- a/toolkit/components/extensions/WebExtensionPolicy.cpp
+++ b/toolkit/components/extensions/WebExtensionPolicy.cpp
@@ -423,58 +423,77 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(WebExtensionPolicy)
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebExtensionPolicy)
/*****************************************************************************
- * WebExtensionContentScript
+ * WebExtensionContentScript / MozDocumentMatcher
*****************************************************************************/
+/* static */ already_AddRefed<MozDocumentMatcher>
+MozDocumentMatcher::Constructor(GlobalObject& aGlobal,
+ const dom::MozDocumentMatcherInit& aInit,
+ ErrorResult& aRv)
+{
+ RefPtr<MozDocumentMatcher> matcher = new MozDocumentMatcher(aInit, aRv);
+ if (aRv.Failed()) {
+ return nullptr;
+ }
+ return matcher.forget();
+}
+
/* static */ already_AddRefed<WebExtensionContentScript>
WebExtensionContentScript::Constructor(GlobalObject& aGlobal,
WebExtensionPolicy& aExtension,
const ContentScriptInit& aInit,
ErrorResult& aRv)
{
RefPtr<WebExtensionContentScript> script = new WebExtensionContentScript(aExtension, aInit, aRv);
if (aRv.Failed()) {
return nullptr;
}
return script.forget();
}
-WebExtensionContentScript::WebExtensionContentScript(WebExtensionPolicy& aExtension,
- const ContentScriptInit& aInit,
- ErrorResult& aRv)
- : mExtension(&aExtension)
- , mHasActiveTabPermission(aInit.mHasActiveTabPermission)
- , mRestricted(!aExtension.HasPermission(nsGkAtoms::mozillaAddons))
+MozDocumentMatcher::MozDocumentMatcher(const dom::MozDocumentMatcherInit& aInit,
+ ErrorResult& aRv)
+ : mHasActiveTabPermission(aInit.mHasActiveTabPermission)
+ , mRestricted(false)
, mMatches(aInit.mMatches)
, mExcludeMatches(aInit.mExcludeMatches)
- , mCssPaths(aInit.mCssPaths)
- , mJsPaths(aInit.mJsPaths)
- , mRunAt(aInit.mRunAt)
, mAllFrames(aInit.mAllFrames)
, mFrameID(aInit.mFrameID)
, mMatchAboutBlank(aInit.mMatchAboutBlank)
{
if (!aInit.mIncludeGlobs.IsNull()) {
mIncludeGlobs.SetValue().AppendElements(aInit.mIncludeGlobs.Value());
}
if (!aInit.mExcludeGlobs.IsNull()) {
mExcludeGlobs.SetValue().AppendElements(aInit.mExcludeGlobs.Value());
}
}
+WebExtensionContentScript::WebExtensionContentScript(WebExtensionPolicy& aExtension,
+ const ContentScriptInit& aInit,
+ ErrorResult& aRv)
+ : MozDocumentMatcher(aInit, aRv)
+ , mCssPaths(aInit.mCssPaths)
+ , mJsPaths(aInit.mJsPaths)
+ , mRunAt(aInit.mRunAt)
+{
+ mExtension = &aExtension;
+ mRestricted = !aExtension.HasPermission(nsGkAtoms::mozillaAddons);
+}
+
bool
-WebExtensionContentScript::Matches(const DocInfo& aDoc) const
+MozDocumentMatcher::Matches(const DocInfo& aDoc) const
{
if (!mFrameID.IsNull()) {
if (aDoc.FrameID() != mFrameID.Value()) {
return false;
}
} else {
if (!mAllFrames && !aDoc.IsTopLevel()) {
return false;
@@ -503,17 +522,17 @@ WebExtensionContentScript::Matches(const
MatchPattern::MatchesAllURLs(urlinfo)) {
return true;
}
return MatchesURI(urlinfo);
}
bool
-WebExtensionContentScript::MatchesURI(const URLInfo& aURL) const
+MozDocumentMatcher::MatchesURI(const URLInfo& aURL) const
{
if (!mMatches->Matches(aURL)) {
return false;
}
if (mExcludeMatches && mExcludeMatches->Matches(aURL)) {
return false;
}
@@ -530,34 +549,40 @@ WebExtensionContentScript::MatchesURI(co
return false;
}
return true;
}
JSObject*
+MozDocumentMatcher::WrapObject(JSContext* aCx, JS::HandleObject aGivenProto)
+{
+ return MozDocumentMatcherBinding::Wrap(aCx, this, aGivenProto);
+}
+
+JSObject*
WebExtensionContentScript::WrapObject(JSContext* aCx, JS::HandleObject aGivenProto)
{
return WebExtensionContentScriptBinding::Wrap(aCx, this, aGivenProto);
}
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebExtensionContentScript,
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MozDocumentMatcher,
mMatches, mExcludeMatches,
mIncludeGlobs, mExcludeGlobs,
mExtension)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebExtensionContentScript)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MozDocumentMatcher)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
-NS_IMPL_CYCLE_COLLECTING_ADDREF(WebExtensionContentScript)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(WebExtensionContentScript)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(MozDocumentMatcher)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(MozDocumentMatcher)
/*****************************************************************************
* DocInfo
*****************************************************************************/
DocInfo::DocInfo(const URLInfo& aURL, nsILoadInfo* aLoadInfo)
: mURL(aURL)