1 // Copyright 2021 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_COOKIES_COOKIE_PARTITION_KEY_H_ 6 #define NET_COOKIES_COOKIE_PARTITION_KEY_H_ 7 8 #include <string> 9 10 #include "net/base/net_export.h" 11 #include "net/base/network_isolation_key.h" 12 #include "net/base/schemeful_site.h" 13 #include "third_party/abseil-cpp/absl/types/optional.h" 14 #include "url/gurl.h" 15 16 namespace net { 17 18 class NET_EXPORT CookiePartitionKey { 19 public: 20 CookiePartitionKey(); 21 CookiePartitionKey(const CookiePartitionKey& other); 22 CookiePartitionKey(CookiePartitionKey&& other); 23 CookiePartitionKey& operator=(const CookiePartitionKey& other); 24 CookiePartitionKey& operator=(CookiePartitionKey&& other); 25 ~CookiePartitionKey(); 26 27 bool operator==(const CookiePartitionKey& other) const; 28 bool operator!=(const CookiePartitionKey& other) const; 29 bool operator<(const CookiePartitionKey& other) const; 30 31 // Methods for serializing and deserializing a partition key to/from a string. 32 // This is currently used for: 33 // - Storing persistent partitioned cookies 34 // - Loading partitioned cookies into Java code 35 // - Sending cookie partition keys as strings in the DevTools protocol 36 // 37 // This function returns true if the partition key is not opaque and if nonce_ 38 // is not present. We do not want to serialize cookies with opaque origins or 39 // nonce in their partition key to disk, because if the browser session ends 40 // we will not be able to attach the saved cookie to any future requests. This 41 // is because opaque origins' nonces are only stored in volatile memory. 42 // 43 // TODO(crbug.com/1225444) Investigate ways to persist partition keys with 44 // opaque origins if a browser session is restored. 45 [[nodiscard]] static bool Serialize( 46 const absl::optional<CookiePartitionKey>& in, 47 std::string& out); 48 // Deserializes the result of the method above. 49 // If the result is absl::nullopt, the resulting cookie is not partitioned. 50 // 51 // Returns if the resulting partition key is valid. 52 [[nodiscard]] static bool Deserialize( 53 const std::string& in, 54 absl::optional<CookiePartitionKey>& out); 55 56 static CookiePartitionKey FromURLForTesting( 57 const GURL& url, 58 const absl::optional<base::UnguessableToken> nonce = absl::nullopt) { 59 return nonce ? CookiePartitionKey(SchemefulSite(url), nonce) 60 : CookiePartitionKey(url); 61 } 62 63 // Create a partition key from a network isolation key. Partition key is 64 // derived from the key's top-frame site. 65 static absl::optional<CookiePartitionKey> FromNetworkIsolationKey( 66 const NetworkIsolationKey& network_isolation_key); 67 68 // Create a new CookiePartitionKey from the site of an existing 69 // CookiePartitionKey. This should only be used for sites of partition keys 70 // which were already created using Deserialize or FromNetworkIsolationKey. 71 static CookiePartitionKey FromWire( 72 const SchemefulSite& site, 73 absl::optional<base::UnguessableToken> nonce = absl::nullopt) { 74 return CookiePartitionKey(site, nonce); 75 } 76 77 // Create a new CookiePartitionKey in a script running in a renderer. We do 78 // not trust the renderer to provide us with a cookie partition key, so we let 79 // the renderer use this method to indicate the cookie is partitioned but the 80 // key still needs to be determined. 81 // 82 // When the browser is ingesting cookie partition keys from the renderer, 83 // either the `from_script_` flag should be set or the cookie partition key 84 // should match the browser's. Otherwise the renderer may be compromised. 85 // 86 // TODO(crbug.com/1225444) Consider removing this factory method and 87 // `from_script_` flag when BlinkStorageKey is available in 88 // ServiceWorkerGlobalScope. FromScript()89 static absl::optional<CookiePartitionKey> FromScript() { 90 return absl::make_optional(CookiePartitionKey(true)); 91 } 92 93 // Create a new CookiePartitionKey from the components of a StorageKey. 94 // Forwards to FromWire, but unlike that method in this one the optional nonce 95 // argument has no default. It also checks that cookie partitioning is enabled 96 // before returning a valid key, which FromWire does not check. 97 static absl::optional<CookiePartitionKey> FromStorageKeyComponents( 98 const SchemefulSite& top_level_site, 99 const absl::optional<base::UnguessableToken>& nonce); 100 site()101 const SchemefulSite& site() const { return site_; } 102 from_script()103 bool from_script() const { return from_script_; } 104 105 // Returns true if the current partition key can be serialized to a string. 106 // Cookie partition keys whose internal site is opaque cannot be serialized. 107 bool IsSerializeable() const; 108 nonce()109 const absl::optional<base::UnguessableToken>& nonce() const { return nonce_; } 110 HasNonce(const absl::optional<CookiePartitionKey> & key)111 static bool HasNonce(const absl::optional<CookiePartitionKey>& key) { 112 return key && key->nonce(); 113 } 114 115 private: 116 explicit CookiePartitionKey(const SchemefulSite& site, 117 absl::optional<base::UnguessableToken> nonce); 118 explicit CookiePartitionKey(const GURL& url); 119 explicit CookiePartitionKey(bool from_script); 120 121 SchemefulSite site_; 122 bool from_script_ = false; 123 124 // Having a nonce is a way to force a transient opaque `CookiePartitionKey` 125 // for non-opaque origins. 126 absl::optional<base::UnguessableToken> nonce_; 127 }; 128 129 // Used so that CookiePartitionKeys can be the arguments of DCHECK_EQ. 130 NET_EXPORT std::ostream& operator<<(std::ostream& os, 131 const CookiePartitionKey& cpk); 132 133 } // namespace net 134 135 #endif // NET_COOKIES_COOKIE_PARTITION_KEY_H_ 136