1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef mozilla_extensions_WebExtensionContentScript_h 7 #define mozilla_extensions_WebExtensionContentScript_h 8 9 #include "mozilla/dom/BindingDeclarations.h" 10 #include "mozilla/dom/WebExtensionContentScriptBinding.h" 11 12 #include "jspubtd.h" 13 14 #include "mozilla/Maybe.h" 15 #include "mozilla/Variant.h" 16 #include "mozilla/extensions/MatchGlob.h" 17 #include "mozilla/extensions/MatchPattern.h" 18 #include "nsCOMPtr.h" 19 #include "nsCycleCollectionParticipant.h" 20 #include "nsISupports.h" 21 #include "nsIDocShell.h" 22 #include "nsPIDOMWindow.h" 23 #include "nsWrapperCache.h" 24 25 class nsILoadInfo; 26 class nsPIDOMWindowOuter; 27 28 namespace mozilla { 29 namespace dom { 30 class WindowGlobalChild; 31 } 32 33 namespace extensions { 34 35 using dom::Nullable; 36 using ContentScriptInit = dom::WebExtensionContentScriptInit; 37 38 class WebExtensionPolicy; 39 40 class MOZ_STACK_CLASS DocInfo final { 41 public: 42 DocInfo(const URLInfo& aURL, nsILoadInfo* aLoadInfo); 43 44 MOZ_IMPLICIT DocInfo(nsPIDOMWindowOuter* aWindow); 45 URL()46 const URLInfo& URL() const { return mURL; } 47 48 // The principal of the document, or the expected principal of a request. 49 // May be null for non-DOMWindow DocInfo objects unless 50 // URL().InheritsPrincipal() is true. 51 nsIPrincipal* Principal() const; 52 53 // Returns the URL of the document's principal. Note that this must *only* 54 // be called for content principals. 55 const URLInfo& PrincipalURL() const; 56 57 bool IsTopLevel() const; 58 bool ShouldMatchActiveTabPermission() const; 59 60 uint64_t FrameID() const; 61 GetWindow()62 nsPIDOMWindowOuter* GetWindow() const { 63 if (mObj.is<Window>()) { 64 return mObj.as<Window>(); 65 } 66 return nullptr; 67 } 68 GetLoadInfo()69 nsILoadInfo* GetLoadInfo() const { 70 if (mObj.is<LoadInfo>()) { 71 return mObj.as<LoadInfo>(); 72 } 73 return nullptr; 74 } 75 GetLoadContext()76 already_AddRefed<nsILoadContext> GetLoadContext() const { 77 nsCOMPtr<nsILoadContext> loadContext; 78 if (nsPIDOMWindowOuter* window = GetWindow()) { 79 nsIDocShell* docShell = window->GetDocShell(); 80 loadContext = do_QueryInterface(docShell); 81 } else if (nsILoadInfo* loadInfo = GetLoadInfo()) { 82 nsCOMPtr<nsISupports> requestingContext = loadInfo->GetLoadingContext(); 83 loadContext = do_QueryInterface(requestingContext); 84 } 85 return loadContext.forget(); 86 } 87 88 private: 89 void SetURL(const URLInfo& aURL); 90 91 const URLInfo mURL; 92 mutable Maybe<const URLInfo> mPrincipalURL; 93 94 mutable Maybe<bool> mIsTopLevel; 95 96 mutable Maybe<nsCOMPtr<nsIPrincipal>> mPrincipal; 97 mutable Maybe<uint64_t> mFrameID; 98 99 using Window = nsPIDOMWindowOuter*; 100 using LoadInfo = nsILoadInfo*; 101 102 const Variant<LoadInfo, Window> mObj; 103 }; 104 105 class MozDocumentMatcher : public nsISupports, public nsWrapperCache { 106 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 107 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MozDocumentMatcher) 108 109 using MatchGlobArray = nsTArray<RefPtr<MatchGlob>>; 110 111 static already_AddRefed<MozDocumentMatcher> Constructor( 112 dom::GlobalObject& aGlobal, const dom::MozDocumentMatcherInit& aInit, 113 ErrorResult& aRv); 114 115 bool Matches(const DocInfo& aDoc) const; 116 bool MatchesURI(const URLInfo& aURL) const; 117 MatchesLoadInfo(const URLInfo & aURL,nsILoadInfo * aLoadInfo)118 bool MatchesLoadInfo(const URLInfo& aURL, nsILoadInfo* aLoadInfo) const { 119 return Matches({aURL, aLoadInfo}); 120 } 121 122 bool MatchesWindowGlobal(dom::WindowGlobalChild& aWindow) const; 123 GetExtension()124 WebExtensionPolicy* GetExtension() { return mExtension; } 125 Extension()126 WebExtensionPolicy* Extension() { return mExtension; } Extension()127 const WebExtensionPolicy* Extension() const { return mExtension; } 128 AllFrames()129 bool AllFrames() const { return mAllFrames; } MatchAboutBlank()130 bool MatchAboutBlank() const { return mMatchAboutBlank; } 131 Matches()132 MatchPatternSet* Matches() { return mMatches; } GetMatches()133 const MatchPatternSet* GetMatches() const { return mMatches; } 134 GetExcludeMatches()135 MatchPatternSet* GetExcludeMatches() { return mExcludeMatches; } GetExcludeMatches()136 const MatchPatternSet* GetExcludeMatches() const { return mExcludeMatches; } 137 GetIncludeGlobs(Nullable<MatchGlobArray> & aGlobs)138 void GetIncludeGlobs(Nullable<MatchGlobArray>& aGlobs) { 139 ToNullable(mExcludeGlobs, aGlobs); 140 } GetExcludeGlobs(Nullable<MatchGlobArray> & aGlobs)141 void GetExcludeGlobs(Nullable<MatchGlobArray>& aGlobs) { 142 ToNullable(mExcludeGlobs, aGlobs); 143 } 144 GetFrameID()145 Nullable<uint64_t> GetFrameID() const { return mFrameID; } 146 GetParentObject()147 WebExtensionPolicy* GetParentObject() const { return mExtension; } 148 virtual JSObject* WrapObject(JSContext* aCx, 149 JS::HandleObject aGivenProto) override; 150 151 protected: 152 friend class WebExtensionPolicy; 153 154 virtual ~MozDocumentMatcher() = default; 155 156 MozDocumentMatcher(dom::GlobalObject& aGlobal, 157 const dom::MozDocumentMatcherInit& aInit, bool aRestricted, 158 ErrorResult& aRv); 159 160 RefPtr<WebExtensionPolicy> mExtension; 161 162 bool mHasActiveTabPermission; 163 bool mRestricted; 164 165 RefPtr<MatchPatternSet> mMatches; 166 RefPtr<MatchPatternSet> mExcludeMatches; 167 168 Nullable<MatchGlobSet> mIncludeGlobs; 169 Nullable<MatchGlobSet> mExcludeGlobs; 170 171 bool mAllFrames; 172 Nullable<uint64_t> mFrameID; 173 bool mMatchAboutBlank; 174 175 private: 176 template <typename T, typename U> ToNullable(const Nullable<T> & aInput,Nullable<U> & aOutput)177 void ToNullable(const Nullable<T>& aInput, Nullable<U>& aOutput) { 178 if (aInput.IsNull()) { 179 aOutput.SetNull(); 180 } else { 181 aOutput.SetValue(aInput.Value()); 182 } 183 } 184 185 template <typename T, typename U> ToNullable(const Nullable<T> & aInput,Nullable<nsTArray<U>> & aOutput)186 void ToNullable(const Nullable<T>& aInput, Nullable<nsTArray<U>>& aOutput) { 187 if (aInput.IsNull()) { 188 aOutput.SetNull(); 189 } else { 190 aOutput.SetValue(aInput.Value().Clone()); 191 } 192 } 193 }; 194 195 class WebExtensionContentScript final : public MozDocumentMatcher { 196 public: 197 using RunAtEnum = dom::ContentScriptRunAt; 198 199 static already_AddRefed<WebExtensionContentScript> Constructor( 200 dom::GlobalObject& aGlobal, WebExtensionPolicy& aExtension, 201 const ContentScriptInit& aInit, ErrorResult& aRv); 202 RunAt()203 RunAtEnum RunAt() const { return mRunAt; } 204 GetCssPaths(nsTArray<nsString> & aPaths)205 void GetCssPaths(nsTArray<nsString>& aPaths) const { 206 aPaths.AppendElements(mCssPaths); 207 } GetJsPaths(nsTArray<nsString> & aPaths)208 void GetJsPaths(nsTArray<nsString>& aPaths) const { 209 aPaths.AppendElements(mJsPaths); 210 } 211 212 virtual JSObject* WrapObject(JSContext* aCx, 213 JS::HandleObject aGivenProto) override; 214 215 protected: 216 friend class WebExtensionPolicy; 217 218 virtual ~WebExtensionContentScript() = default; 219 220 WebExtensionContentScript(dom::GlobalObject& aGlobal, 221 WebExtensionPolicy& aExtension, 222 const ContentScriptInit& aInit, ErrorResult& aRv); 223 224 private: 225 nsTArray<nsString> mCssPaths; 226 nsTArray<nsString> mJsPaths; 227 228 RunAtEnum mRunAt; 229 }; 230 231 } // namespace extensions 232 } // namespace mozilla 233 234 #endif // mozilla_extensions_WebExtensionContentScript_h 235