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