/work/obj-fuzz/dist/include/mozilla/extensions/MatchPattern.h
Line | Count | Source (jump to first uncovered line) |
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_MatchPattern_h |
7 | | #define mozilla_extensions_MatchPattern_h |
8 | | |
9 | | #include "mozilla/dom/BindingDeclarations.h" |
10 | | #include "mozilla/dom/MatchPatternBinding.h" |
11 | | #include "mozilla/extensions/MatchGlob.h" |
12 | | |
13 | | #include "jspubtd.h" |
14 | | |
15 | | #include "mozilla/ClearOnShutdown.h" |
16 | | #include "mozilla/Likely.h" |
17 | | #include "mozilla/Maybe.h" |
18 | | #include "mozilla/RefCounted.h" |
19 | | #include "nsCOMPtr.h" |
20 | | #include "nsCycleCollectionParticipant.h" |
21 | | #include "nsTArray.h" |
22 | | #include "nsAtom.h" |
23 | | #include "nsICookie2.h" |
24 | | #include "nsISupports.h" |
25 | | #include "nsIURI.h" |
26 | | #include "nsWrapperCache.h" |
27 | | |
28 | | |
29 | | namespace mozilla { |
30 | | namespace extensions { |
31 | | |
32 | | using dom::MatchPatternOptions; |
33 | | |
34 | | |
35 | | // A sorted, binary-search-backed set of atoms, optimized for frequent lookups |
36 | | // and infrequent updates. |
37 | | class AtomSet final : public RefCounted<AtomSet> |
38 | | { |
39 | | using ArrayType = AutoTArray<RefPtr<nsAtom>, 1>; |
40 | | |
41 | | public: |
42 | | MOZ_DECLARE_REFCOUNTED_TYPENAME(AtomSet) |
43 | | |
44 | | explicit AtomSet(const nsTArray<nsString>& aElems); |
45 | | |
46 | | explicit AtomSet(const char** aElems); |
47 | | |
48 | | MOZ_IMPLICIT AtomSet(std::initializer_list<nsAtom*> aIL); |
49 | | |
50 | | bool Contains(const nsAString& elem) const |
51 | 0 | { |
52 | 0 | RefPtr<nsAtom> atom = NS_AtomizeMainThread(elem); |
53 | 0 | return Contains(atom); |
54 | 0 | } |
55 | | |
56 | | bool Contains(const nsACString& aElem) const |
57 | 0 | { |
58 | 0 | RefPtr<nsAtom> atom = NS_Atomize(aElem); |
59 | 0 | return Contains(atom); |
60 | 0 | } |
61 | | |
62 | | bool Contains(const nsAtom* aAtom) const |
63 | 0 | { |
64 | 0 | return mElems.ContainsSorted(aAtom); |
65 | 0 | } |
66 | | |
67 | | bool Intersects(const AtomSet& aOther) const; |
68 | | |
69 | | |
70 | | void Add(nsAtom* aElem); |
71 | | void Remove(nsAtom* aElem); |
72 | | |
73 | | void Add(const nsAString& aElem) |
74 | 0 | { |
75 | 0 | RefPtr<nsAtom> atom = NS_AtomizeMainThread(aElem); |
76 | 0 | return Add(atom); |
77 | 0 | } |
78 | | |
79 | | void Remove(const nsAString& aElem) |
80 | 0 | { |
81 | 0 | RefPtr<nsAtom> atom = NS_AtomizeMainThread(aElem); |
82 | 0 | return Remove(atom); |
83 | 0 | } |
84 | | |
85 | | // Returns a cached, statically-allocated matcher for the given set of |
86 | | // literal strings. |
87 | | template <const char** schemes> |
88 | | static already_AddRefed<AtomSet> |
89 | | Get() |
90 | 0 | { |
91 | 0 | static RefPtr<AtomSet> sMatcher; |
92 | 0 |
|
93 | 0 | if (MOZ_UNLIKELY(!sMatcher)) { |
94 | 0 | sMatcher = new AtomSet(schemes); |
95 | 0 | ClearOnShutdown(&sMatcher); |
96 | 0 | } |
97 | 0 |
|
98 | 0 | return do_AddRef(sMatcher); |
99 | 0 | } Unexecuted instantiation: already_AddRefed<mozilla::extensions::AtomSet> mozilla::extensions::AtomSet::Get<&mozilla::extensions::PERMITTED_SCHEMES>() Unexecuted instantiation: already_AddRefed<mozilla::extensions::AtomSet> mozilla::extensions::AtomSet::Get<&mozilla::extensions::WILDCARD_SCHEMES>() Unexecuted instantiation: already_AddRefed<mozilla::extensions::AtomSet> mozilla::extensions::AtomSet::Get<&mozilla::extensions::HOST_LOCATOR_SCHEMES>() |
100 | | |
101 | | void |
102 | | Get(nsTArray<nsString>& aResult) const |
103 | 0 | { |
104 | 0 | aResult.SetCapacity(mElems.Length()); |
105 | 0 |
|
106 | 0 | for (const auto& atom : mElems) { |
107 | 0 | aResult.AppendElement(nsDependentAtomString(atom)); |
108 | 0 | } |
109 | 0 | } |
110 | | |
111 | | auto begin() const |
112 | | -> decltype(DeclVal<const ArrayType>().begin()) |
113 | 0 | { |
114 | 0 | return mElems.begin(); |
115 | 0 | } |
116 | | |
117 | | auto end() const |
118 | | -> decltype(DeclVal<const ArrayType>().end()) |
119 | 0 | { |
120 | 0 | return mElems.end(); |
121 | 0 | } |
122 | | |
123 | | private: |
124 | | ArrayType mElems; |
125 | | |
126 | | void SortAndUniquify(); |
127 | | }; |
128 | | |
129 | | |
130 | | // A helper class to lazily retrieve, transcode, and atomize certain URI |
131 | | // properties the first time they're used, and cache the results, so that they |
132 | | // can be used across multiple match operations. |
133 | | class URLInfo final |
134 | | { |
135 | | public: |
136 | | MOZ_IMPLICIT URLInfo(nsIURI* aURI) |
137 | | : mURI(aURI) |
138 | 0 | { |
139 | 0 | mHost.SetIsVoid(true); |
140 | 0 | } |
141 | | |
142 | | URLInfo(nsIURI* aURI, bool aNoRef) |
143 | | : URLInfo(aURI) |
144 | 0 | { |
145 | 0 | if (aNoRef) { |
146 | 0 | mURINoRef = mURI; |
147 | 0 | } |
148 | 0 | } |
149 | | |
150 | | URLInfo(const URLInfo& aOther) |
151 | | : URLInfo(aOther.mURI.get()) |
152 | 0 | {} |
153 | | |
154 | 0 | nsIURI* URI() const { return mURI; } |
155 | | |
156 | | nsAtom* Scheme() const; |
157 | | const nsCString& Host() const; |
158 | | const nsAtom* HostAtom() const; |
159 | | const nsString& Path() const; |
160 | | const nsString& FilePath() const; |
161 | | const nsString& Spec() const; |
162 | | const nsCString& CSpec() const; |
163 | | |
164 | | bool InheritsPrincipal() const; |
165 | | |
166 | | private: |
167 | | nsIURI* URINoRef() const; |
168 | | |
169 | | nsCOMPtr<nsIURI> mURI; |
170 | | mutable nsCOMPtr<nsIURI> mURINoRef; |
171 | | |
172 | | mutable RefPtr<nsAtom> mScheme; |
173 | | mutable nsCString mHost; |
174 | | mutable RefPtr<nsAtom> mHostAtom; |
175 | | |
176 | | mutable nsString mPath; |
177 | | mutable nsString mFilePath; |
178 | | mutable nsString mSpec; |
179 | | mutable nsCString mCSpec; |
180 | | |
181 | | mutable Maybe<bool> mInheritsPrincipal; |
182 | | }; |
183 | | |
184 | | |
185 | | // Similar to URLInfo, but for cookies. |
186 | | class MOZ_STACK_CLASS CookieInfo final |
187 | | { |
188 | | public: |
189 | | MOZ_IMPLICIT CookieInfo(nsICookie2* aCookie) |
190 | | : mCookie(aCookie) |
191 | 0 | {} |
192 | | |
193 | | bool IsSecure() const; |
194 | | bool IsDomain() const; |
195 | | |
196 | | const nsCString& Host() const; |
197 | | const nsCString& RawHost() const; |
198 | | |
199 | | private: |
200 | | nsCOMPtr<nsICookie2> mCookie; |
201 | | |
202 | | mutable Maybe<bool> mIsSecure; |
203 | | mutable Maybe<bool> mIsDomain; |
204 | | |
205 | | mutable nsCString mHost; |
206 | | mutable nsCString mRawHost; |
207 | | }; |
208 | | |
209 | | |
210 | | class MatchPattern final : public nsISupports |
211 | | , public nsWrapperCache |
212 | | { |
213 | | NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
214 | | NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MatchPattern) |
215 | | |
216 | | static already_AddRefed<MatchPattern> |
217 | | Constructor(dom::GlobalObject& aGlobal, |
218 | | const nsAString& aPattern, |
219 | | const MatchPatternOptions& aOptions, |
220 | | ErrorResult& aRv); |
221 | | |
222 | | bool Matches(const nsAString& aURL, bool aExplicit, ErrorResult& aRv) const; |
223 | | |
224 | | bool Matches(const URLInfo& aURL, bool aExplicit = false) const; |
225 | | |
226 | | bool Matches(const URLInfo& aURL, bool aExplicit, ErrorResult& aRv) const |
227 | 0 | { |
228 | 0 | return Matches(aURL, aExplicit); |
229 | 0 | } |
230 | | |
231 | | |
232 | | bool MatchesCookie(const CookieInfo& aCookie) const; |
233 | | |
234 | | bool MatchesDomain(const nsACString& aDomain) const; |
235 | | |
236 | | bool Subsumes(const MatchPattern& aPattern) const; |
237 | | |
238 | | bool Overlaps(const MatchPattern& aPattern) const; |
239 | | |
240 | | bool DomainIsWildcard() const |
241 | 0 | { |
242 | 0 | return mMatchSubdomain && mDomain.IsEmpty(); |
243 | 0 | } |
244 | | |
245 | | void GetPattern(nsAString& aPattern) const |
246 | 0 | { |
247 | 0 | aPattern = mPattern; |
248 | 0 | } |
249 | | |
250 | 0 | nsISupports* GetParentObject() const { return mParent; } |
251 | | |
252 | | virtual JSObject* WrapObject(JSContext* aCx, JS::HandleObject aGivenProto) override; |
253 | | |
254 | | protected: |
255 | 0 | virtual ~MatchPattern() = default; |
256 | | |
257 | | private: |
258 | 0 | explicit MatchPattern(nsISupports* aParent) : mParent(aParent) {} |
259 | | |
260 | | void Init(JSContext* aCx, const nsAString& aPattern, bool aIgnorePath, |
261 | | bool aRestrictSchemes, ErrorResult& aRv); |
262 | | |
263 | | bool SubsumesDomain(const MatchPattern& aPattern) const; |
264 | | |
265 | | |
266 | | nsCOMPtr<nsISupports> mParent; |
267 | | |
268 | | // The normalized match pattern string that this object represents. |
269 | | nsString mPattern; |
270 | | |
271 | | // The set of atomized URI schemes that this pattern matches. |
272 | | RefPtr<AtomSet> mSchemes; |
273 | | |
274 | | // The domain that this matcher matches. If mMatchSubdomain is false, only |
275 | | // matches the exact domain. If it's true, matches the domain or any |
276 | | // subdomain. |
277 | | // |
278 | | // For instance, "*.foo.com" gives mDomain = "foo.com" and mMatchSubdomain = true, |
279 | | // and matches "foo.com" or "bar.foo.com" but not "barfoo.com". |
280 | | // |
281 | | // While "foo.com" gives mDomain = "foo.com" and mMatchSubdomain = false, |
282 | | // and matches "foo.com" but not "bar.foo.com". |
283 | | nsCString mDomain; |
284 | | bool mMatchSubdomain = false; |
285 | | |
286 | | // The glob against which the URL path must match. If null, the path is |
287 | | // ignored entirely. If non-null, the path must match this glob. |
288 | | RefPtr<MatchGlob> mPath; |
289 | | |
290 | | public: |
291 | | // A quick way to check if a particular URL matches <all_urls> without |
292 | | // actually instantiating a MatchPattern |
293 | | static bool MatchesAllURLs(const URLInfo& aURL); |
294 | | }; |
295 | | |
296 | | |
297 | | class MatchPatternSet final : public nsISupports |
298 | | , public nsWrapperCache |
299 | | { |
300 | | NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
301 | | NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MatchPatternSet) |
302 | | |
303 | | using ArrayType = nsTArray<RefPtr<MatchPattern>>; |
304 | | |
305 | | |
306 | | static already_AddRefed<MatchPatternSet> |
307 | | Constructor(dom::GlobalObject& aGlobal, |
308 | | const nsTArray<dom::OwningStringOrMatchPattern>& aPatterns, |
309 | | const MatchPatternOptions& aOptions, |
310 | | ErrorResult& aRv); |
311 | | |
312 | | |
313 | | bool Matches(const nsAString& aURL, bool aExplicit, ErrorResult& aRv) const; |
314 | | |
315 | | bool Matches(const URLInfo& aURL, bool aExplicit = false) const; |
316 | | |
317 | | bool Matches(const URLInfo& aURL, bool aExplicit, ErrorResult& aRv) const |
318 | 0 | { |
319 | 0 | return Matches(aURL, aExplicit); |
320 | 0 | } |
321 | | |
322 | | |
323 | | bool MatchesCookie(const CookieInfo& aCookie) const; |
324 | | |
325 | | bool Subsumes(const MatchPattern& aPattern) const; |
326 | | |
327 | | bool Overlaps(const MatchPattern& aPattern) const; |
328 | | |
329 | | bool Overlaps(const MatchPatternSet& aPatternSet) const; |
330 | | |
331 | | bool OverlapsAll(const MatchPatternSet& aPatternSet) const; |
332 | | |
333 | | void GetPatterns(ArrayType& aPatterns) |
334 | 0 | { |
335 | 0 | aPatterns.AppendElements(mPatterns); |
336 | 0 | } |
337 | | |
338 | | |
339 | 0 | nsISupports* GetParentObject() const { return mParent; } |
340 | | |
341 | | virtual JSObject* WrapObject(JSContext* aCx, JS::HandleObject aGivenProto) override; |
342 | | |
343 | | protected: |
344 | 0 | virtual ~MatchPatternSet() = default; |
345 | | |
346 | | private: |
347 | | explicit MatchPatternSet(nsISupports* aParent, ArrayType&& aPatterns) |
348 | | : mParent(aParent) |
349 | | , mPatterns(std::forward<ArrayType>(aPatterns)) |
350 | 0 | {} |
351 | | |
352 | | nsCOMPtr<nsISupports> mParent; |
353 | | |
354 | | ArrayType mPatterns; |
355 | | }; |
356 | | |
357 | | } // namespace extensions |
358 | | } // namespace mozilla |
359 | | |
360 | | #endif // mozilla_extensions_MatchPattern_h |