1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_dom_quota_originorpatternstring_h__
8 #define mozilla_dom_quota_originorpatternstring_h__
9 
10 #include <utility>
11 #include "mozilla/Assertions.h"
12 #include "mozilla/OriginAttributes.h"
13 #include "mozilla/UniquePtr.h"
14 #include "mozilla/Variant.h"
15 #include "nsStringFlags.h"
16 #include "nsStringFwd.h"
17 
18 namespace mozilla::dom::quota {
19 
20 class OriginScope {
21   class Origin {
22     nsCString mOrigin;
23     nsCString mOriginNoSuffix;
24     UniquePtr<OriginAttributes> mAttributes;
25 
26    public:
Origin(const nsACString & aOrigin)27     explicit Origin(const nsACString& aOrigin) : mOrigin(aOrigin) {
28       InitMembers();
29     }
30 
Origin(const Origin & aOther)31     Origin(const Origin& aOther)
32         : mOrigin(aOther.mOrigin),
33           mOriginNoSuffix(aOther.mOriginNoSuffix),
34           mAttributes(MakeUnique<OriginAttributes>(*aOther.mAttributes)) {}
35 
36     Origin(Origin&& aOther) = default;
37 
GetOrigin()38     const nsACString& GetOrigin() const { return mOrigin; }
39 
SetOrigin(const nsACString & aOrigin)40     void SetOrigin(const nsACString& aOrigin) {
41       mOrigin = aOrigin;
42 
43       InitMembers();
44     }
45 
GetOriginNoSuffix()46     const nsACString& GetOriginNoSuffix() const { return mOriginNoSuffix; }
47 
GetAttributes()48     const OriginAttributes& GetAttributes() const {
49       MOZ_ASSERT(mAttributes);
50 
51       return *mAttributes;
52     }
53 
54    private:
InitMembers()55     void InitMembers() {
56       mAttributes = MakeUnique<OriginAttributes>();
57 
58       MOZ_ALWAYS_TRUE(
59           mAttributes->PopulateFromOrigin(mOrigin, mOriginNoSuffix));
60     }
61   };
62 
63   class Prefix {
64     nsCString mOriginNoSuffix;
65 
66    public:
Prefix(const nsACString & aOriginNoSuffix)67     explicit Prefix(const nsACString& aOriginNoSuffix)
68         : mOriginNoSuffix(aOriginNoSuffix) {}
69 
GetOriginNoSuffix()70     const nsCString& GetOriginNoSuffix() const { return mOriginNoSuffix; }
71 
SetOriginNoSuffix(const nsACString & aOriginNoSuffix)72     void SetOriginNoSuffix(const nsACString& aOriginNoSuffix) {
73       mOriginNoSuffix = aOriginNoSuffix;
74     }
75   };
76 
77   class Pattern {
78     UniquePtr<OriginAttributesPattern> mPattern;
79 
80    public:
Pattern(const OriginAttributesPattern & aPattern)81     explicit Pattern(const OriginAttributesPattern& aPattern)
82         : mPattern(MakeUnique<OriginAttributesPattern>(aPattern)) {}
83 
Pattern(const nsAString & aJSONPattern)84     explicit Pattern(const nsAString& aJSONPattern)
85         : mPattern(MakeUnique<OriginAttributesPattern>()) {
86       MOZ_ALWAYS_TRUE(mPattern->Init(aJSONPattern));
87     }
88 
Pattern(const Pattern & aOther)89     Pattern(const Pattern& aOther)
90         : mPattern(MakeUnique<OriginAttributesPattern>(*aOther.mPattern)) {}
91 
92     Pattern(Pattern&& aOther) = default;
93 
GetPattern()94     const OriginAttributesPattern& GetPattern() const {
95       MOZ_ASSERT(mPattern);
96 
97       return *mPattern;
98     }
99 
SetPattern(const OriginAttributesPattern & aPattern)100     void SetPattern(const OriginAttributesPattern& aPattern) {
101       mPattern = MakeUnique<OriginAttributesPattern>(aPattern);
102     }
103 
GetJSONPattern()104     nsString GetJSONPattern() const {
105       MOZ_ASSERT(mPattern);
106 
107       nsString result;
108       MOZ_ALWAYS_TRUE(mPattern->ToJSON(result));
109 
110       return result;
111     }
112   };
113 
114   struct Null {};
115 
116   using DataType = Variant<Origin, Prefix, Pattern, Null>;
117 
118   DataType mData;
119 
120  public:
OriginScope()121   OriginScope() : mData(Null()) {}
122 
FromOrigin(const nsACString & aOrigin)123   static OriginScope FromOrigin(const nsACString& aOrigin) {
124     return OriginScope(std::move(Origin(aOrigin)));
125   }
126 
FromPrefix(const nsACString & aPrefix)127   static OriginScope FromPrefix(const nsACString& aPrefix) {
128     return OriginScope(std::move(Prefix(aPrefix)));
129   }
130 
FromPattern(const OriginAttributesPattern & aPattern)131   static OriginScope FromPattern(const OriginAttributesPattern& aPattern) {
132     return OriginScope(std::move(Pattern(aPattern)));
133   }
134 
FromJSONPattern(const nsAString & aJSONPattern)135   static OriginScope FromJSONPattern(const nsAString& aJSONPattern) {
136     return OriginScope(std::move(Pattern(aJSONPattern)));
137   }
138 
FromNull()139   static OriginScope FromNull() { return OriginScope(std::move(Null())); }
140 
IsOrigin()141   bool IsOrigin() const { return mData.is<Origin>(); }
142 
IsPrefix()143   bool IsPrefix() const { return mData.is<Prefix>(); }
144 
IsPattern()145   bool IsPattern() const { return mData.is<Pattern>(); }
146 
IsNull()147   bool IsNull() const { return mData.is<Null>(); }
148 
SetFromOrigin(const nsACString & aOrigin)149   void SetFromOrigin(const nsACString& aOrigin) {
150     mData = AsVariant(Origin(aOrigin));
151   }
152 
SetFromPrefix(const nsACString & aPrefix)153   void SetFromPrefix(const nsACString& aPrefix) {
154     mData = AsVariant(Prefix(aPrefix));
155   }
156 
SetFromPattern(const OriginAttributesPattern & aPattern)157   void SetFromPattern(const OriginAttributesPattern& aPattern) {
158     mData = AsVariant(Pattern(aPattern));
159   }
160 
SetFromJSONPattern(const nsAString & aJSONPattern)161   void SetFromJSONPattern(const nsAString& aJSONPattern) {
162     mData = AsVariant(Pattern(aJSONPattern));
163   }
164 
SetFromNull()165   void SetFromNull() { mData = AsVariant(Null()); }
166 
GetOrigin()167   const nsACString& GetOrigin() const {
168     MOZ_ASSERT(IsOrigin());
169 
170     return mData.as<Origin>().GetOrigin();
171   }
172 
SetOrigin(const nsACString & aOrigin)173   void SetOrigin(const nsACString& aOrigin) {
174     MOZ_ASSERT(IsOrigin());
175 
176     mData.as<Origin>().SetOrigin(aOrigin);
177   }
178 
GetOriginNoSuffix()179   const nsACString& GetOriginNoSuffix() const {
180     MOZ_ASSERT(IsOrigin() || IsPrefix());
181 
182     if (IsOrigin()) {
183       return mData.as<Origin>().GetOriginNoSuffix();
184     }
185     return mData.as<Prefix>().GetOriginNoSuffix();
186   }
187 
SetOriginNoSuffix(const nsACString & aOriginNoSuffix)188   void SetOriginNoSuffix(const nsACString& aOriginNoSuffix) {
189     MOZ_ASSERT(IsPrefix());
190 
191     mData.as<Prefix>().SetOriginNoSuffix(aOriginNoSuffix);
192   }
193 
GetPattern()194   const OriginAttributesPattern& GetPattern() const {
195     MOZ_ASSERT(IsPattern());
196 
197     return mData.as<Pattern>().GetPattern();
198   }
199 
GetJSONPattern()200   nsString GetJSONPattern() const {
201     MOZ_ASSERT(IsPattern());
202 
203     return mData.as<Pattern>().GetJSONPattern();
204   }
205 
SetPattern(const OriginAttributesPattern & aPattern)206   void SetPattern(const OriginAttributesPattern& aPattern) {
207     MOZ_ASSERT(IsPattern());
208 
209     mData.as<Pattern>().SetPattern(aPattern);
210   }
211 
Matches(const OriginScope & aOther)212   bool Matches(const OriginScope& aOther) const {
213     struct Matcher {
214       const OriginScope& mThis;
215 
216       explicit Matcher(const OriginScope& aThis) : mThis(aThis) {}
217 
218       bool operator()(const Origin& aOther) {
219         return mThis.MatchesOrigin(aOther);
220       }
221 
222       bool operator()(const Prefix& aOther) {
223         return mThis.MatchesPrefix(aOther);
224       }
225 
226       bool operator()(const Pattern& aOther) {
227         return mThis.MatchesPattern(aOther);
228       }
229 
230       bool operator()(const Null& aOther) { return true; }
231     };
232 
233     return aOther.mData.match(Matcher(*this));
234   }
235 
Clone()236   OriginScope Clone() { return OriginScope(mData); }
237 
238  private:
239   // Move constructors
OriginScope(const Origin && aOrigin)240   explicit OriginScope(const Origin&& aOrigin) : mData(aOrigin) {}
241 
OriginScope(const Prefix && aPrefix)242   explicit OriginScope(const Prefix&& aPrefix) : mData(aPrefix) {}
243 
OriginScope(const Pattern && aPattern)244   explicit OriginScope(const Pattern&& aPattern) : mData(aPattern) {}
245 
OriginScope(const Null && aNull)246   explicit OriginScope(const Null&& aNull) : mData(aNull) {}
247 
248   // Copy constructor
OriginScope(const DataType & aOther)249   explicit OriginScope(const DataType& aOther) : mData(aOther) {}
250 
MatchesOrigin(const Origin & aOther)251   bool MatchesOrigin(const Origin& aOther) const {
252     struct OriginMatcher {
253       const Origin& mOther;
254 
255       explicit OriginMatcher(const Origin& aOther) : mOther(aOther) {}
256 
257       bool operator()(const Origin& aThis) {
258         return aThis.GetOrigin().Equals(mOther.GetOrigin());
259       }
260 
261       bool operator()(const Prefix& aThis) {
262         return aThis.GetOriginNoSuffix().Equals(mOther.GetOriginNoSuffix());
263       }
264 
265       bool operator()(const Pattern& aThis) {
266         return aThis.GetPattern().Matches(mOther.GetAttributes());
267       }
268 
269       bool operator()(const Null& aThis) {
270         // Null covers everything.
271         return true;
272       }
273     };
274 
275     return mData.match(OriginMatcher(aOther));
276   }
277 
MatchesPrefix(const Prefix & aOther)278   bool MatchesPrefix(const Prefix& aOther) const {
279     struct PrefixMatcher {
280       const Prefix& mOther;
281 
282       explicit PrefixMatcher(const Prefix& aOther) : mOther(aOther) {}
283 
284       bool operator()(const Origin& aThis) {
285         return aThis.GetOriginNoSuffix().Equals(mOther.GetOriginNoSuffix());
286       }
287 
288       bool operator()(const Prefix& aThis) {
289         return aThis.GetOriginNoSuffix().Equals(mOther.GetOriginNoSuffix());
290       }
291 
292       bool operator()(const Pattern& aThis) {
293         // The match will be always true here because any origin attributes
294         // pattern overlaps any origin prefix (an origin prefix targets all
295         // origin attributes).
296         return true;
297       }
298 
299       bool operator()(const Null& aThis) {
300         // Null covers everything.
301         return true;
302       }
303     };
304 
305     return mData.match(PrefixMatcher(aOther));
306   }
307 
MatchesPattern(const Pattern & aOther)308   bool MatchesPattern(const Pattern& aOther) const {
309     struct PatternMatcher {
310       const Pattern& mOther;
311 
312       explicit PatternMatcher(const Pattern& aOther) : mOther(aOther) {}
313 
314       bool operator()(const Origin& aThis) {
315         return mOther.GetPattern().Matches(aThis.GetAttributes());
316       }
317 
318       bool operator()(const Prefix& aThis) {
319         // The match will be always true here because any origin attributes
320         // pattern overlaps any origin prefix (an origin prefix targets all
321         // origin attributes).
322         return true;
323       }
324 
325       bool operator()(const Pattern& aThis) {
326         return aThis.GetPattern().Overlaps(mOther.GetPattern());
327       }
328 
329       bool operator()(const Null& aThis) {
330         // Null covers everything.
331         return true;
332       }
333     };
334 
335     PatternMatcher patternMatcher(aOther);
336     return mData.match(PatternMatcher(aOther));
337   }
338 
339   bool operator==(const OriginScope& aOther) = delete;
340 };
341 
342 }  // namespace mozilla::dom::quota
343 
344 #endif  // mozilla_dom_quota_originorpatternstring_h__
345