tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

OriginAttributes.h (10511B)


      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/ChromeUtilsBinding.h"
     11 #include "mozilla/StaticPrefs_privacy.h"
     12 #include "nsIScriptSecurityManager.h"
     13 
     14 namespace mozilla {
     15 
     16 class OriginAttributes : public dom::OriginAttributesDictionary {
     17 public:
     18  OriginAttributes() = default;
     19 
     20  explicit OriginAttributes(const OriginAttributesDictionary& aOther)
     21      : OriginAttributesDictionary(aOther) {}
     22 
     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);
     29 
     30  void SetPartitionKey(nsIURI* aURI, bool aForeignByAncestorContext);
     31  void SetPartitionKey(const nsACString& aOther);
     32  void SetPartitionKey(const nsAString& aOther);
     33 
     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,
     39  };
     40 
     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    if (aFlags & STRIP_PARITION_KEY) {
     56      mPartitionKey.Truncate();
     57    }
     58  }
     59 
     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;
     66  }
     67 
     68  bool operator!=(const OriginAttributes& aOther) const {
     69    return !(*this == aOther);
     70  }
     71 
     72  [[nodiscard]] bool EqualsIgnoringFPD(const OriginAttributes& aOther) const {
     73    return mUserContextId == aOther.mUserContextId &&
     74           mPrivateBrowsingId == aOther.mPrivateBrowsingId &&
     75           mGeckoViewSessionContextId == aOther.mGeckoViewSessionContextId;
     76  }
     77 
     78  [[nodiscard]] bool EqualsIgnoringPartitionKey(
     79      const OriginAttributes& aOther) const {
     80    return EqualsIgnoringFPD(aOther) &&
     81           mFirstPartyDomain == aOther.mFirstPartyDomain;
     82  }
     83 
     84  [[nodiscard]] inline bool IsPrivateBrowsing() const {
     85    return mPrivateBrowsingId !=
     86           nsIScriptSecurityManager::DEFAULT_PRIVATE_BROWSING_ID;
     87  }
     88 
     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;
     93 
     94  // Like CreateSuffix, but returns an atom instead of producing a string.
     95  already_AddRefed<nsAtom> CreateSuffixAtom() const;
     96 
     97  // Don't use this method for anything else than debugging!
     98  void CreateAnonymizedSuffix(nsACString& aStr) const;
     99 
    100  [[nodiscard]] bool PopulateFromSuffix(const nsACString& aStr);
    101 
    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);
    106 
    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);
    110 
    111  // check if "privacy.firstparty.isolate" is enabled.
    112  static inline bool IsFirstPartyEnabled() {
    113    return StaticPrefs::privacy_firstparty_isolate();
    114  }
    115 
    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();
    124  }
    125 
    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();
    131  }
    132 
    133  // returns true if the originAttributes suffix has mPrivateBrowsingId value
    134  // different than 0.
    135  static bool IsPrivateBrowsing(const nsACString& aOrigin);
    136 
    137  // Parse a partitionKey of the format
    138  // "(<scheme>,<baseDomain>,[port],[ancestorbit])" into its components. Returns
    139  // false if the partitionKey cannot be parsed because the format is invalid.
    140  static bool ParsePartitionKey(const nsAString& aPartitionKey,
    141                                nsAString& outScheme, nsAString& outBaseDomain,
    142                                int32_t& outPort,
    143                                bool& outForeignByAncestorContext);
    144 
    145  // Parse a partitionKey and extract the site from it. Returns false if the
    146  // partitionKey cannot be parsed because the format is invalid.
    147  static bool ExtractSiteFromPartitionKey(const nsAString& aPartitionKey,
    148                                          nsAString& aOutSite);
    149 };
    150 
    151 class OriginAttributesPattern : public dom::OriginAttributesPatternDictionary {
    152 public:
    153  // To convert a JSON string to an OriginAttributesPattern, do the following:
    154  //
    155  // OriginAttributesPattern pattern;
    156  // if (!pattern.Init(aJSONString)) {
    157  //   ... // handle failure.
    158  // }
    159  OriginAttributesPattern() = default;
    160 
    161  explicit OriginAttributesPattern(
    162      const OriginAttributesPatternDictionary& aOther)
    163      : OriginAttributesPatternDictionary(aOther) {}
    164 
    165  // Performs a match of |aAttrs| against this pattern.
    166  bool Matches(const OriginAttributes& aAttrs) const {
    167    if (mUserContextId.WasPassed() &&
    168        mUserContextId.Value() != aAttrs.mUserContextId) {
    169      return false;
    170    }
    171 
    172    if (mPrivateBrowsingId.WasPassed() &&
    173        mPrivateBrowsingId.Value() != aAttrs.mPrivateBrowsingId) {
    174      return false;
    175    }
    176 
    177    if (mFirstPartyDomain.WasPassed() &&
    178        mFirstPartyDomain.Value() != aAttrs.mFirstPartyDomain) {
    179      return false;
    180    }
    181 
    182    if (mGeckoViewSessionContextId.WasPassed() &&
    183        mGeckoViewSessionContextId.Value() !=
    184            aAttrs.mGeckoViewSessionContextId) {
    185      return false;
    186    }
    187 
    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;
    193      }
    194    } else if (mPartitionKeyPattern.WasPassed()) {
    195      auto& pkPattern = mPartitionKeyPattern.Value();
    196 
    197      if (pkPattern.mScheme.WasPassed() || pkPattern.mBaseDomain.WasPassed() ||
    198          pkPattern.mPort.WasPassed()) {
    199        if (aAttrs.mPartitionKey.IsEmpty()) {
    200          return false;
    201        }
    202 
    203        nsString scheme;
    204        nsString baseDomain;
    205        int32_t port;
    206        bool ancestor;
    207        bool success = OriginAttributes::ParsePartitionKey(
    208            aAttrs.mPartitionKey, scheme, baseDomain, port, ancestor);
    209        if (!success) {
    210          return false;
    211        }
    212 
    213        if (pkPattern.mScheme.WasPassed() &&
    214            pkPattern.mScheme.Value() != scheme) {
    215          return false;
    216        }
    217        if (pkPattern.mBaseDomain.WasPassed() &&
    218            pkPattern.mBaseDomain.Value() != baseDomain) {
    219          return false;
    220        }
    221        if (pkPattern.mPort.WasPassed() && pkPattern.mPort.Value() != port) {
    222          return false;
    223        }
    224        if (pkPattern.mForeignByAncestorContext.WasPassed() &&
    225            pkPattern.mForeignByAncestorContext.Value() != ancestor) {
    226          return false;
    227        }
    228      }
    229    }
    230 
    231    return true;
    232  }
    233 
    234  bool Overlaps(const OriginAttributesPattern& aOther) const {
    235    if (mUserContextId.WasPassed() && aOther.mUserContextId.WasPassed() &&
    236        mUserContextId.Value() != aOther.mUserContextId.Value()) {
    237      return false;
    238    }
    239 
    240    if (mPrivateBrowsingId.WasPassed() &&
    241        aOther.mPrivateBrowsingId.WasPassed() &&
    242        mPrivateBrowsingId.Value() != aOther.mPrivateBrowsingId.Value()) {
    243      return false;
    244    }
    245 
    246    if (mFirstPartyDomain.WasPassed() && aOther.mFirstPartyDomain.WasPassed() &&
    247        mFirstPartyDomain.Value() != aOther.mFirstPartyDomain.Value()) {
    248      return false;
    249    }
    250 
    251    if (mGeckoViewSessionContextId.WasPassed() &&
    252        aOther.mGeckoViewSessionContextId.WasPassed() &&
    253        mGeckoViewSessionContextId.Value() !=
    254            aOther.mGeckoViewSessionContextId.Value()) {
    255      return false;
    256    }
    257 
    258    if (mPartitionKey.WasPassed() && aOther.mPartitionKey.WasPassed() &&
    259        mPartitionKey.Value() != aOther.mPartitionKey.Value()) {
    260      return false;
    261    }
    262 
    263    if (mPartitionKeyPattern.WasPassed() &&
    264        aOther.mPartitionKeyPattern.WasPassed()) {
    265      auto& self = mPartitionKeyPattern.Value();
    266      auto& other = aOther.mPartitionKeyPattern.Value();
    267 
    268      if (self.mScheme.WasPassed() && other.mScheme.WasPassed() &&
    269          self.mScheme.Value() != other.mScheme.Value()) {
    270        return false;
    271      }
    272      if (self.mBaseDomain.WasPassed() && other.mBaseDomain.WasPassed() &&
    273          self.mBaseDomain.Value() != other.mBaseDomain.Value()) {
    274        return false;
    275      }
    276      if (self.mPort.WasPassed() && other.mPort.WasPassed() &&
    277          self.mPort.Value() != other.mPort.Value()) {
    278        return false;
    279      }
    280      if (self.mForeignByAncestorContext.WasPassed() &&
    281          other.mForeignByAncestorContext.WasPassed() &&
    282          self.mForeignByAncestorContext.Value() !=
    283              other.mForeignByAncestorContext.Value()) {
    284        return false;
    285      }
    286    }
    287 
    288    return true;
    289  }
    290 };
    291 
    292 }  // namespace mozilla
    293 
    294 #endif /* mozilla_OriginAttributes_h */