Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / caps / OriginAttributes.h
blob52f7afa9427de0856fa5d235cc459ddff09d1527
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(const OriginAttributesDictionary& aOther)
21 : OriginAttributesDictionary(aOther) {}
23 void SetFirstPartyDomain(const bool aIsTopLevelDocument, nsIURI* aURI,
24 bool aForced = false);
25 void SetFirstPartyDomain(const bool aIsTopLevelDocument,
26 const nsACString& aDomain);
27 void SetFirstPartyDomain(const bool aIsTopLevelDocument,
28 const nsAString& aDomain, bool aForced = false);
30 void SetPartitionKey(nsIURI* aURI, bool aForeignByAncestorContext);
31 void SetPartitionKey(const nsACString& aOther);
32 void SetPartitionKey(const nsAString& aOther);
34 enum {
35 STRIP_FIRST_PARTY_DOMAIN = 0x01,
36 STRIP_USER_CONTEXT_ID = 0x02,
37 STRIP_PRIVATE_BROWSING_ID = 0x04,
38 STRIP_PARITION_KEY = 0x08,
41 inline void StripAttributes(uint32_t aFlags) {
42 if (aFlags & STRIP_FIRST_PARTY_DOMAIN) {
43 mFirstPartyDomain.Truncate();
46 if (aFlags & STRIP_USER_CONTEXT_ID) {
47 mUserContextId = nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID;
50 if (aFlags & STRIP_PRIVATE_BROWSING_ID) {
51 mPrivateBrowsingId =
52 nsIScriptSecurityManager::DEFAULT_PRIVATE_BROWSING_ID;
55 if (aFlags & STRIP_PARITION_KEY) {
56 mPartitionKey.Truncate();
60 bool operator==(const OriginAttributes& aOther) const {
61 return EqualsIgnoringFPD(aOther) &&
62 mFirstPartyDomain == aOther.mFirstPartyDomain &&
63 // FIXME(emilio, bug 1667440): Should this be part of
64 // EqualsIgnoringFPD instead?
65 mPartitionKey == aOther.mPartitionKey;
68 bool operator!=(const OriginAttributes& aOther) const {
69 return !(*this == aOther);
72 [[nodiscard]] bool EqualsIgnoringFPD(const OriginAttributes& aOther) const {
73 return mUserContextId == aOther.mUserContextId &&
74 mPrivateBrowsingId == aOther.mPrivateBrowsingId &&
75 mGeckoViewSessionContextId == aOther.mGeckoViewSessionContextId;
78 [[nodiscard]] bool EqualsIgnoringPartitionKey(
79 const OriginAttributes& aOther) const {
80 return EqualsIgnoringFPD(aOther) &&
81 mFirstPartyDomain == aOther.mFirstPartyDomain;
84 // Serializes/Deserializes non-default values into the suffix format, i.e.
85 // |^key1=value1&key2=value2|. If there are no non-default attributes, this
86 // returns an empty string.
87 void CreateSuffix(nsACString& aStr) const;
89 // Like CreateSuffix, but returns an atom instead of producing a string.
90 already_AddRefed<nsAtom> CreateSuffixAtom() const;
92 // Don't use this method for anything else than debugging!
93 void CreateAnonymizedSuffix(nsACString& aStr) const;
95 [[nodiscard]] bool PopulateFromSuffix(const nsACString& aStr);
97 // Populates the attributes from a string like
98 // |uri^key1=value1&key2=value2| and returns the uri without the suffix.
99 [[nodiscard]] bool PopulateFromOrigin(const nsACString& aOrigin,
100 nsACString& aOriginNoSuffix);
102 // Helper function to match mIsPrivateBrowsing to existing private browsing
103 // flags. Once all other flags are removed, this can be removed too.
104 void SyncAttributesWithPrivateBrowsing(bool aInPrivateBrowsing);
106 // check if "privacy.firstparty.isolate" is enabled.
107 static inline bool IsFirstPartyEnabled() {
108 return StaticPrefs::privacy_firstparty_isolate();
111 // check if the access of window.opener across different FPDs is restricted.
112 // We only restrict the access of window.opener when first party isolation
113 // is enabled and "privacy.firstparty.isolate.restrict_opener_access" is on.
114 static inline bool IsRestrictOpenerAccessForFPI() {
115 // We always want to restrict window.opener if first party isolation is
116 // disabled.
117 return !StaticPrefs::privacy_firstparty_isolate() ||
118 StaticPrefs::privacy_firstparty_isolate_restrict_opener_access();
121 // Check whether we block the postMessage across different FPDs when the
122 // targetOrigin is '*'.
123 [[nodiscard]] static inline bool IsBlockPostMessageForFPI() {
124 return StaticPrefs::privacy_firstparty_isolate() &&
125 StaticPrefs::privacy_firstparty_isolate_block_post_message();
128 // returns true if the originAttributes suffix has mPrivateBrowsingId value
129 // different than 0.
130 static bool IsPrivateBrowsing(const nsACString& aOrigin);
132 // Parse a partitionKey of the format
133 // "(<scheme>,<baseDomain>,[port],[ancestorbit])" into its components. Returns
134 // false if the partitionKey cannot be parsed because the format is invalid.
135 static bool ParsePartitionKey(const nsAString& aPartitionKey,
136 nsAString& outScheme, nsAString& outBaseDomain,
137 int32_t& outPort,
138 bool& outForeignByAncestorContext);
141 class OriginAttributesPattern : public dom::OriginAttributesPatternDictionary {
142 public:
143 // To convert a JSON string to an OriginAttributesPattern, do the following:
145 // OriginAttributesPattern pattern;
146 // if (!pattern.Init(aJSONString)) {
147 // ... // handle failure.
148 // }
149 OriginAttributesPattern() = default;
151 explicit OriginAttributesPattern(
152 const OriginAttributesPatternDictionary& aOther)
153 : OriginAttributesPatternDictionary(aOther) {}
155 // Performs a match of |aAttrs| against this pattern.
156 bool Matches(const OriginAttributes& aAttrs) const {
157 if (mUserContextId.WasPassed() &&
158 mUserContextId.Value() != aAttrs.mUserContextId) {
159 return false;
162 if (mPrivateBrowsingId.WasPassed() &&
163 mPrivateBrowsingId.Value() != aAttrs.mPrivateBrowsingId) {
164 return false;
167 if (mFirstPartyDomain.WasPassed() &&
168 mFirstPartyDomain.Value() != aAttrs.mFirstPartyDomain) {
169 return false;
172 if (mGeckoViewSessionContextId.WasPassed() &&
173 mGeckoViewSessionContextId.Value() !=
174 aAttrs.mGeckoViewSessionContextId) {
175 return false;
178 // If both mPartitionKey and mPartitionKeyPattern are passed, mPartitionKey
179 // takes precedence.
180 if (mPartitionKey.WasPassed()) {
181 if (mPartitionKey.Value() != aAttrs.mPartitionKey) {
182 return false;
184 } else if (mPartitionKeyPattern.WasPassed()) {
185 auto& pkPattern = mPartitionKeyPattern.Value();
187 if (pkPattern.mScheme.WasPassed() || pkPattern.mBaseDomain.WasPassed() ||
188 pkPattern.mPort.WasPassed()) {
189 if (aAttrs.mPartitionKey.IsEmpty()) {
190 return false;
193 nsString scheme;
194 nsString baseDomain;
195 int32_t port;
196 bool ancestor;
197 bool success = OriginAttributes::ParsePartitionKey(
198 aAttrs.mPartitionKey, scheme, baseDomain, port, ancestor);
199 if (!success) {
200 return false;
203 if (pkPattern.mScheme.WasPassed() &&
204 pkPattern.mScheme.Value() != scheme) {
205 return false;
207 if (pkPattern.mBaseDomain.WasPassed() &&
208 pkPattern.mBaseDomain.Value() != baseDomain) {
209 return false;
211 if (pkPattern.mPort.WasPassed() && pkPattern.mPort.Value() != port) {
212 return false;
214 if (pkPattern.mForeignByAncestorContext.WasPassed() &&
215 pkPattern.mForeignByAncestorContext.Value() != ancestor) {
216 return false;
221 return true;
224 bool Overlaps(const OriginAttributesPattern& aOther) const {
225 if (mUserContextId.WasPassed() && aOther.mUserContextId.WasPassed() &&
226 mUserContextId.Value() != aOther.mUserContextId.Value()) {
227 return false;
230 if (mPrivateBrowsingId.WasPassed() &&
231 aOther.mPrivateBrowsingId.WasPassed() &&
232 mPrivateBrowsingId.Value() != aOther.mPrivateBrowsingId.Value()) {
233 return false;
236 if (mFirstPartyDomain.WasPassed() && aOther.mFirstPartyDomain.WasPassed() &&
237 mFirstPartyDomain.Value() != aOther.mFirstPartyDomain.Value()) {
238 return false;
241 if (mGeckoViewSessionContextId.WasPassed() &&
242 aOther.mGeckoViewSessionContextId.WasPassed() &&
243 mGeckoViewSessionContextId.Value() !=
244 aOther.mGeckoViewSessionContextId.Value()) {
245 return false;
248 if (mPartitionKey.WasPassed() && aOther.mPartitionKey.WasPassed() &&
249 mPartitionKey.Value() != aOther.mPartitionKey.Value()) {
250 return false;
253 if (mPartitionKeyPattern.WasPassed() &&
254 aOther.mPartitionKeyPattern.WasPassed()) {
255 auto& self = mPartitionKeyPattern.Value();
256 auto& other = aOther.mPartitionKeyPattern.Value();
258 if (self.mScheme.WasPassed() && other.mScheme.WasPassed() &&
259 self.mScheme.Value() != other.mScheme.Value()) {
260 return false;
262 if (self.mBaseDomain.WasPassed() && other.mBaseDomain.WasPassed() &&
263 self.mBaseDomain.Value() != other.mBaseDomain.Value()) {
264 return false;
266 if (self.mPort.WasPassed() && other.mPort.WasPassed() &&
267 self.mPort.Value() != other.mPort.Value()) {
268 return false;
270 if (self.mForeignByAncestorContext.WasPassed() &&
271 other.mForeignByAncestorContext.WasPassed() &&
272 self.mForeignByAncestorContext.Value() !=
273 other.mForeignByAncestorContext.Value()) {
274 return false;
278 return true;
282 } // namespace mozilla
284 #endif /* mozilla_OriginAttributes_h */