Coverage Report

Created: 2018-09-25 14:53

/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