Bug 1846847 [wpt PR 41301] - [FedCM] Don't omit schemes when formatting URLs, a=testonly
[gecko.git] / caps / OriginAttributes.h
blob02e52f0799f8cfb3aea1dd065e7b13acafb61486
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/. */
7 #ifndef mozilla_OriginAttributes_h
8 #define mozilla_OriginAttributes_h
10 #include "mozilla/dom/ChromeUtilsBinding.h"
11 #include "mozilla/StaticPrefs_privacy.h"
12 #include "nsIScriptSecurityManager.h"
14 namespace mozilla {
16 class OriginAttributes : public dom::OriginAttributesDictionary {
17 public:
18 OriginAttributes() = default;
20 explicit OriginAttributes(bool aInIsolatedMozBrowser) {
21 mInIsolatedMozBrowser = aInIsolatedMozBrowser;
24 explicit OriginAttributes(const OriginAttributesDictionary& aOther)
25 : OriginAttributesDictionary(aOther) {}
27 void SetFirstPartyDomain(const bool aIsTopLevelDocument, nsIURI* aURI,
28 bool aForced = false);
29 void SetFirstPartyDomain(const bool aIsTopLevelDocument,
30 const nsACString& aDomain);
31 void SetFirstPartyDomain(const bool aIsTopLevelDocument,
32 const nsAString& aDomain, bool aForced = false);
34 void SetPartitionKey(nsIURI* aURI);
35 void SetPartitionKey(const nsACString& aDomain);
36 void SetPartitionKey(const nsAString& aDomain);
38 enum {
39 STRIP_FIRST_PARTY_DOMAIN = 0x01,
40 STRIP_USER_CONTEXT_ID = 0x02,
41 STRIP_PRIVATE_BROWSING_ID = 0x04,
42 STRIP_PARITION_KEY = 0x08,
45 inline void StripAttributes(uint32_t aFlags) {
46 if (aFlags & STRIP_FIRST_PARTY_DOMAIN) {
47 mFirstPartyDomain.Truncate();
50 if (aFlags & STRIP_USER_CONTEXT_ID) {
51 mUserContextId = nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID;
54 if (aFlags & STRIP_PRIVATE_BROWSING_ID) {
55 mPrivateBrowsingId =
56 nsIScriptSecurityManager::DEFAULT_PRIVATE_BROWSING_ID;
59 if (aFlags & STRIP_PARITION_KEY) {
60 mPartitionKey.Truncate();
64 bool operator==(const OriginAttributes& aOther) const {
65 return EqualsIgnoringFPD(aOther) &&
66 mFirstPartyDomain == aOther.mFirstPartyDomain &&
67 // FIXME(emilio, bug 1667440): Should this be part of
68 // EqualsIgnoringFPD instead?
69 mPartitionKey == aOther.mPartitionKey;
72 bool operator!=(const OriginAttributes& aOther) const {
73 return !(*this == aOther);
76 [[nodiscard]] bool EqualsIgnoringFPD(const OriginAttributes& aOther) const {
77 return mInIsolatedMozBrowser == aOther.mInIsolatedMozBrowser &&
78 mUserContextId == aOther.mUserContextId &&
79 mPrivateBrowsingId == aOther.mPrivateBrowsingId &&
80 mGeckoViewSessionContextId == aOther.mGeckoViewSessionContextId;
83 [[nodiscard]] bool EqualsIgnoringPartitionKey(
84 const OriginAttributes& aOther) const {
85 return EqualsIgnoringFPD(aOther) &&
86 mFirstPartyDomain == aOther.mFirstPartyDomain;
89 // Serializes/Deserializes non-default values into the suffix format, i.e.
90 // |^key1=value1&key2=value2|. If there are no non-default attributes, this
91 // returns an empty string.
92 void CreateSuffix(nsACString& aStr) const;
94 // Like CreateSuffix, but returns an atom instead of producing a string.
95 already_AddRefed<nsAtom> CreateSuffixAtom() const;
97 // Don't use this method for anything else than debugging!
98 void CreateAnonymizedSuffix(nsACString& aStr) const;
100 [[nodiscard]] bool PopulateFromSuffix(const nsACString& aStr);
102 // Populates the attributes from a string like
103 // |uri^key1=value1&key2=value2| and returns the uri without the suffix.
104 [[nodiscard]] bool PopulateFromOrigin(const nsACString& aOrigin,
105 nsACString& aOriginNoSuffix);
107 // Helper function to match mIsPrivateBrowsing to existing private browsing
108 // flags. Once all other flags are removed, this can be removed too.
109 void SyncAttributesWithPrivateBrowsing(bool aInPrivateBrowsing);
111 // check if "privacy.firstparty.isolate" is enabled.
112 static inline bool IsFirstPartyEnabled() {
113 return StaticPrefs::privacy_firstparty_isolate();
116 // check if the access of window.opener across different FPDs is restricted.
117 // We only restrict the access of window.opener when first party isolation
118 // is enabled and "privacy.firstparty.isolate.restrict_opener_access" is on.
119 static inline bool IsRestrictOpenerAccessForFPI() {
120 // We always want to restrict window.opener if first party isolation is
121 // disabled.
122 return !StaticPrefs::privacy_firstparty_isolate() ||
123 StaticPrefs::privacy_firstparty_isolate_restrict_opener_access();
126 // Check whether we block the postMessage across different FPDs when the
127 // targetOrigin is '*'.
128 [[nodiscard]] static inline bool IsBlockPostMessageForFPI() {
129 return StaticPrefs::privacy_firstparty_isolate() &&
130 StaticPrefs::privacy_firstparty_isolate_block_post_message();
133 // returns true if the originAttributes suffix has mPrivateBrowsingId value
134 // different than 0.
135 static bool IsPrivateBrowsing(const nsACString& aOrigin);
137 // Parse a partitionKey of the format "(<scheme>,<baseDomain>,[port])" into
138 // its components.
139 // Returns false if the partitionKey cannot be parsed because the format is
140 // invalid.
141 static bool ParsePartitionKey(const nsAString& aPartitionKey,
142 nsAString& outScheme, nsAString& outBaseDomain,
143 int32_t& outPort);
146 class OriginAttributesPattern : public dom::OriginAttributesPatternDictionary {
147 public:
148 // To convert a JSON string to an OriginAttributesPattern, do the following:
150 // OriginAttributesPattern pattern;
151 // if (!pattern.Init(aJSONString)) {
152 // ... // handle failure.
153 // }
154 OriginAttributesPattern() = default;
156 explicit OriginAttributesPattern(
157 const OriginAttributesPatternDictionary& aOther)
158 : OriginAttributesPatternDictionary(aOther) {}
160 // Performs a match of |aAttrs| against this pattern.
161 bool Matches(const OriginAttributes& aAttrs) const {
162 if (mInIsolatedMozBrowser.WasPassed() &&
163 mInIsolatedMozBrowser.Value() != aAttrs.mInIsolatedMozBrowser) {
164 return false;
167 if (mUserContextId.WasPassed() &&
168 mUserContextId.Value() != aAttrs.mUserContextId) {
169 return false;
172 if (mPrivateBrowsingId.WasPassed() &&
173 mPrivateBrowsingId.Value() != aAttrs.mPrivateBrowsingId) {
174 return false;
177 if (mFirstPartyDomain.WasPassed() &&
178 mFirstPartyDomain.Value() != aAttrs.mFirstPartyDomain) {
179 return false;
182 if (mGeckoViewSessionContextId.WasPassed() &&
183 mGeckoViewSessionContextId.Value() !=
184 aAttrs.mGeckoViewSessionContextId) {
185 return false;
188 // If both mPartitionKey and mPartitionKeyPattern are passed, mPartitionKey
189 // takes precedence.
190 if (mPartitionKey.WasPassed()) {
191 if (mPartitionKey.Value() != aAttrs.mPartitionKey) {
192 return false;
194 } else if (mPartitionKeyPattern.WasPassed()) {
195 auto& pkPattern = mPartitionKeyPattern.Value();
197 if (pkPattern.mScheme.WasPassed() || pkPattern.mBaseDomain.WasPassed() ||
198 pkPattern.mPort.WasPassed()) {
199 if (aAttrs.mPartitionKey.IsEmpty()) {
200 return false;
203 nsString scheme;
204 nsString baseDomain;
205 int32_t port;
206 bool success = OriginAttributes::ParsePartitionKey(
207 aAttrs.mPartitionKey, scheme, baseDomain, port);
208 if (!success) {
209 return false;
212 if (pkPattern.mScheme.WasPassed() &&
213 pkPattern.mScheme.Value() != scheme) {
214 return false;
216 if (pkPattern.mBaseDomain.WasPassed() &&
217 pkPattern.mBaseDomain.Value() != baseDomain) {
218 return false;
220 if (pkPattern.mPort.WasPassed() && pkPattern.mPort.Value() != port) {
221 return false;
226 return true;
229 bool Overlaps(const OriginAttributesPattern& aOther) const {
230 if (mInIsolatedMozBrowser.WasPassed() &&
231 aOther.mInIsolatedMozBrowser.WasPassed() &&
232 mInIsolatedMozBrowser.Value() != aOther.mInIsolatedMozBrowser.Value()) {
233 return false;
236 if (mUserContextId.WasPassed() && aOther.mUserContextId.WasPassed() &&
237 mUserContextId.Value() != aOther.mUserContextId.Value()) {
238 return false;
241 if (mPrivateBrowsingId.WasPassed() &&
242 aOther.mPrivateBrowsingId.WasPassed() &&
243 mPrivateBrowsingId.Value() != aOther.mPrivateBrowsingId.Value()) {
244 return false;
247 if (mFirstPartyDomain.WasPassed() && aOther.mFirstPartyDomain.WasPassed() &&
248 mFirstPartyDomain.Value() != aOther.mFirstPartyDomain.Value()) {
249 return false;
252 if (mGeckoViewSessionContextId.WasPassed() &&
253 aOther.mGeckoViewSessionContextId.WasPassed() &&
254 mGeckoViewSessionContextId.Value() !=
255 aOther.mGeckoViewSessionContextId.Value()) {
256 return false;
259 if (mPartitionKey.WasPassed() && aOther.mPartitionKey.WasPassed() &&
260 mPartitionKey.Value() != aOther.mPartitionKey.Value()) {
261 return false;
264 if (mPartitionKeyPattern.WasPassed() &&
265 aOther.mPartitionKeyPattern.WasPassed()) {
266 auto& self = mPartitionKeyPattern.Value();
267 auto& other = aOther.mPartitionKeyPattern.Value();
269 if (self.mScheme.WasPassed() && other.mScheme.WasPassed() &&
270 self.mScheme.Value() != other.mScheme.Value()) {
271 return false;
273 if (self.mBaseDomain.WasPassed() && other.mBaseDomain.WasPassed() &&
274 self.mBaseDomain.Value() != other.mBaseDomain.Value()) {
275 return false;
277 if (self.mPort.WasPassed() && other.mPort.WasPassed() &&
278 self.mPort.Value() != other.mPort.Value()) {
279 return false;
283 return true;
287 } // namespace mozilla
289 #endif /* mozilla_OriginAttributes_h */