Bug 1472491: Part 2a - Split matching logic for content scripts into MozDocumentMatcher base class. r=zombie

MozReview-Commit-ID: JAOWZcB4hZW

--HG--
extra : rebase_source : 35847d616bd2f04f1d82788f76649b8acb5c1090
extra : source : 466c39fc8af5170ea39d19d6d7aa13b8fe5cd838
This commit is contained in:
Kris Maglione 2018-04-18 14:02:15 -07:00
Родитель 57d6fb6016
Коммит cdd41d5705
4 изменённых файлов: 181 добавлений и 125 удалений

Просмотреть файл

@ -581,6 +581,11 @@ DOMInterfaces = {
'notflattened': True
},
'MozDocumentMatcher': {
'nativeType': 'mozilla::extensions::MozDocumentMatcher',
'headerFile': 'mozilla/extensions/WebExtensionContentScript.h',
},
'MozSharedMap': {
'nativeType': 'mozilla::dom::ipc::SharedMap',
},

Просмотреть файл

@ -6,32 +6,8 @@ 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`.
@ -39,52 +15,33 @@ interface WebExtensionContentScript {
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
@ -123,6 +80,68 @@ interface WebExtensionContentScript {
[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.
@ -138,25 +157,9 @@ interface WebExtensionContentScript {
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 = [];

Просмотреть файл

@ -80,23 +80,19 @@ private:
};
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;
@ -110,14 +106,13 @@ class WebExtensionContentScript final : public nsISupports
}
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; }
@ -134,6 +129,63 @@ class WebExtensionContentScript final : public nsISupports
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);
@ -143,9 +195,6 @@ class WebExtensionContentScript final : public nsISupports
aPaths.AppendElements(mJsPaths);
}
WebExtensionPolicy* GetParentObject() const { return mExtension; }
virtual JSObject* WrapObject(JSContext* aCx, JS::HandleObject aGivenProto) override;
protected:
@ -158,36 +207,10 @@ protected:
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

Просмотреть файл

@ -428,9 +428,21 @@ 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,
@ -444,17 +456,12 @@ WebExtensionContentScript::Constructor(GlobalObject& aGlobal,
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)
@ -468,8 +475,20 @@ WebExtensionContentScript::WebExtensionContentScript(WebExtensionPolicy& aExtens
}
}
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()) {
@ -508,7 +527,7 @@ WebExtensionContentScript::Matches(const DocInfo& aDoc) const
}
bool
WebExtensionContentScript::MatchesURI(const URLInfo& aURL) const
MozDocumentMatcher::MatchesURI(const URLInfo& aURL) const
{
if (!mMatches->Matches(aURL)) {
return false;
@ -534,6 +553,12 @@ WebExtensionContentScript::MatchesURI(const URLInfo& aURL) const
}
JSObject*
MozDocumentMatcher::WrapObject(JSContext* aCx, JS::HandleObject aGivenProto)
{
return MozDocumentMatcher_Binding::Wrap(aCx, this, aGivenProto);
}
JSObject*
WebExtensionContentScript::WrapObject(JSContext* aCx, JS::HandleObject aGivenProto)
{
@ -541,18 +566,18 @@ WebExtensionContentScript::WrapObject(JSContext* aCx, JS::HandleObject aGivenPro
}
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)
/*****************************************************************************