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
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_OriginAttributes_h
8 #define mozilla_OriginAttributes_h
9 
10 #include "mozilla/dom/ChromeUtils.h"
11 #include "mozilla/dom/ChromeUtilsBinding.h"
12 #include "mozilla/StaticPrefs_privacy.h"
13 #include "nsIScriptSecurityManager.h"
14 
15 namespace mozilla {
16 
17 class OriginAttributes : public dom::OriginAttributesDictionary {
18  public:
19   OriginAttributes() = default;
20 
OriginAttributes(bool aInIsolatedMozBrowser)21   explicit OriginAttributes(bool aInIsolatedMozBrowser) {
22     mInIsolatedMozBrowser = aInIsolatedMozBrowser;
23   }
24 
OriginAttributes(const OriginAttributesDictionary & aOther)25   explicit OriginAttributes(const OriginAttributesDictionary& aOther)
26       : OriginAttributesDictionary(aOther) {}
27 
28   void SetFirstPartyDomain(const bool aIsTopLevelDocument, nsIURI* aURI,
29                            bool aForced = false);
30   void SetFirstPartyDomain(const bool aIsTopLevelDocument,
31                            const nsACString& aDomain);
32   void SetFirstPartyDomain(const bool aIsTopLevelDocument,
33                            const nsAString& aDomain, bool aForced = false);
34 
35   enum {
36     STRIP_FIRST_PARTY_DOMAIN = 0x01,
37     STRIP_USER_CONTEXT_ID = 0x02,
38     STRIP_PRIVATE_BROWSING_ID = 0x04,
39   };
40 
StripAttributes(uint32_t aFlags)41   inline void StripAttributes(uint32_t aFlags) {
42     if (aFlags & STRIP_FIRST_PARTY_DOMAIN) {
43       mFirstPartyDomain.Truncate();
44     }
45 
46     if (aFlags & STRIP_USER_CONTEXT_ID) {
47       mUserContextId = nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID;
48     }
49 
50     if (aFlags & STRIP_PRIVATE_BROWSING_ID) {
51       mPrivateBrowsingId =
52           nsIScriptSecurityManager::DEFAULT_PRIVATE_BROWSING_ID;
53     }
54   }
55 
56   bool operator==(const OriginAttributes& aOther) const {
57     return mInIsolatedMozBrowser == aOther.mInIsolatedMozBrowser &&
58            mUserContextId == aOther.mUserContextId &&
59            mPrivateBrowsingId == aOther.mPrivateBrowsingId &&
60            mFirstPartyDomain == aOther.mFirstPartyDomain &&
61            mGeckoViewSessionContextId == aOther.mGeckoViewSessionContextId;
62   }
63 
64   bool operator!=(const OriginAttributes& aOther) const {
65     return !(*this == aOther);
66   }
67 
EqualsIgnoringFPD(const OriginAttributes & aOther)68   MOZ_MUST_USE bool EqualsIgnoringFPD(const OriginAttributes& aOther) const {
69     return mInIsolatedMozBrowser == aOther.mInIsolatedMozBrowser &&
70            mUserContextId == aOther.mUserContextId &&
71            mPrivateBrowsingId == aOther.mPrivateBrowsingId &&
72            mGeckoViewSessionContextId == aOther.mGeckoViewSessionContextId;
73   }
74 
75   // Serializes/Deserializes non-default values into the suffix format, i.e.
76   // |!key1=value1&key2=value2|. If there are no non-default attributes, this
77   // returns an empty string.
78   void CreateSuffix(nsACString& aStr) const;
79 
80   // Don't use this method for anything else than debugging!
81   void CreateAnonymizedSuffix(nsACString& aStr) const;
82 
83   MOZ_MUST_USE bool PopulateFromSuffix(const nsACString& aStr);
84 
85   // Populates the attributes from a string like
86   // |uri!key1=value1&key2=value2| and returns the uri without the suffix.
87   MOZ_MUST_USE bool PopulateFromOrigin(const nsACString& aOrigin,
88                                        nsACString& aOriginNoSuffix);
89 
90   // Helper function to match mIsPrivateBrowsing to existing private browsing
91   // flags. Once all other flags are removed, this can be removed too.
92   void SyncAttributesWithPrivateBrowsing(bool aInPrivateBrowsing);
93 
94   // check if "privacy.firstparty.isolate" is enabled.
IsFirstPartyEnabled()95   static inline bool IsFirstPartyEnabled() {
96     return StaticPrefs::privacy_firstparty_isolate();
97   }
98 
UseSiteForFirstPartyDomain()99   static inline bool UseSiteForFirstPartyDomain() {
100     if (IsFirstPartyEnabled()) {
101       return StaticPrefs::privacy_firstparty_isolate_use_site();
102     }
103     return StaticPrefs::privacy_dynamic_firstparty_use_site();
104   }
105 
106   // check if the access of window.opener across different FPDs is restricted.
107   // We only restrict the access of window.opener when first party isolation
108   // is enabled and "privacy.firstparty.isolate.restrict_opener_access" is on.
IsRestrictOpenerAccessForFPI()109   static inline bool IsRestrictOpenerAccessForFPI() {
110     // We always want to restrict window.opener if first party isolation is
111     // disabled.
112     return !StaticPrefs::privacy_firstparty_isolate() ||
113            StaticPrefs::privacy_firstparty_isolate_restrict_opener_access();
114   }
115 
116   // Check whether we block the postMessage across different FPDs when the
117   // targetOrigin is '*'.
IsBlockPostMessageForFPI()118   static inline MOZ_MUST_USE bool IsBlockPostMessageForFPI() {
119     return StaticPrefs::privacy_firstparty_isolate() &&
120            StaticPrefs::privacy_firstparty_isolate_block_post_message();
121   }
122 
123   // returns true if the originAttributes suffix has mPrivateBrowsingId value
124   // different than 0.
125   static bool IsPrivateBrowsing(const nsACString& aOrigin);
126 };
127 
128 class OriginAttributesPattern : public dom::OriginAttributesPatternDictionary {
129  public:
130   // To convert a JSON string to an OriginAttributesPattern, do the following:
131   //
132   // OriginAttributesPattern pattern;
133   // if (!pattern.Init(aJSONString)) {
134   //   ... // handle failure.
135   // }
136   OriginAttributesPattern() = default;
137 
OriginAttributesPattern(const OriginAttributesPatternDictionary & aOther)138   explicit OriginAttributesPattern(
139       const OriginAttributesPatternDictionary& aOther)
140       : OriginAttributesPatternDictionary(aOther) {}
141 
142   // Performs a match of |aAttrs| against this pattern.
Matches(const OriginAttributes & aAttrs)143   bool Matches(const OriginAttributes& aAttrs) const {
144     if (mInIsolatedMozBrowser.WasPassed() &&
145         mInIsolatedMozBrowser.Value() != aAttrs.mInIsolatedMozBrowser) {
146       return false;
147     }
148 
149     if (mUserContextId.WasPassed() &&
150         mUserContextId.Value() != aAttrs.mUserContextId) {
151       return false;
152     }
153 
154     if (mPrivateBrowsingId.WasPassed() &&
155         mPrivateBrowsingId.Value() != aAttrs.mPrivateBrowsingId) {
156       return false;
157     }
158 
159     if (mFirstPartyDomain.WasPassed() &&
160         mFirstPartyDomain.Value() != aAttrs.mFirstPartyDomain) {
161       return false;
162     }
163 
164     if (mGeckoViewSessionContextId.WasPassed() &&
165         mGeckoViewSessionContextId.Value() !=
166             aAttrs.mGeckoViewSessionContextId) {
167       return false;
168     }
169 
170     return true;
171   }
172 
Overlaps(const OriginAttributesPattern & aOther)173   bool Overlaps(const OriginAttributesPattern& aOther) const {
174     if (mInIsolatedMozBrowser.WasPassed() &&
175         aOther.mInIsolatedMozBrowser.WasPassed() &&
176         mInIsolatedMozBrowser.Value() != aOther.mInIsolatedMozBrowser.Value()) {
177       return false;
178     }
179 
180     if (mUserContextId.WasPassed() && aOther.mUserContextId.WasPassed() &&
181         mUserContextId.Value() != aOther.mUserContextId.Value()) {
182       return false;
183     }
184 
185     if (mPrivateBrowsingId.WasPassed() &&
186         aOther.mPrivateBrowsingId.WasPassed() &&
187         mPrivateBrowsingId.Value() != aOther.mPrivateBrowsingId.Value()) {
188       return false;
189     }
190 
191     if (mFirstPartyDomain.WasPassed() && aOther.mFirstPartyDomain.WasPassed() &&
192         mFirstPartyDomain.Value() != aOther.mFirstPartyDomain.Value()) {
193       return false;
194     }
195 
196     if (mGeckoViewSessionContextId.WasPassed() &&
197         aOther.mGeckoViewSessionContextId.WasPassed() &&
198         mGeckoViewSessionContextId.Value() !=
199             aOther.mGeckoViewSessionContextId.Value()) {
200       return false;
201     }
202 
203     return true;
204   }
205 };
206 
207 }  // namespace mozilla
208 
209 #endif /* mozilla_OriginAttributes_h */
210