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 #include "net/cookies/cookie_partition_key.h"
6
7 #include <ostream>
8 #include <tuple>
9
10 #include "base/feature_list.h"
11 #include "base/logging.h"
12 #include "base/types/optional_util.h"
13 #include "net/base/features.h"
14 #include "net/cookies/cookie_constants.h"
15
16 namespace net {
17
18 CookiePartitionKey::CookiePartitionKey() = default;
19
CookiePartitionKey(const SchemefulSite & site,absl::optional<base::UnguessableToken> nonce)20 CookiePartitionKey::CookiePartitionKey(
21 const SchemefulSite& site,
22 absl::optional<base::UnguessableToken> nonce)
23 : site_(site), nonce_(nonce) {}
24
CookiePartitionKey(const GURL & url)25 CookiePartitionKey::CookiePartitionKey(const GURL& url)
26 : site_(SchemefulSite(url)) {}
27
CookiePartitionKey(bool from_script)28 CookiePartitionKey::CookiePartitionKey(bool from_script)
29 : from_script_(from_script) {}
30
31 CookiePartitionKey::CookiePartitionKey(const CookiePartitionKey& other) =
32 default;
33
34 CookiePartitionKey::CookiePartitionKey(CookiePartitionKey&& other) = default;
35
36 CookiePartitionKey& CookiePartitionKey::operator=(
37 const CookiePartitionKey& other) = default;
38
39 CookiePartitionKey& CookiePartitionKey::operator=(CookiePartitionKey&& other) =
40 default;
41
42 CookiePartitionKey::~CookiePartitionKey() = default;
43
operator ==(const CookiePartitionKey & other) const44 bool CookiePartitionKey::operator==(const CookiePartitionKey& other) const {
45 return site_ == other.site_ && nonce_ == other.nonce_;
46 }
47
operator !=(const CookiePartitionKey & other) const48 bool CookiePartitionKey::operator!=(const CookiePartitionKey& other) const {
49 return site_ != other.site_ || nonce_ != other.nonce_;
50 }
51
operator <(const CookiePartitionKey & other) const52 bool CookiePartitionKey::operator<(const CookiePartitionKey& other) const {
53 return std::tie(site_, nonce_) < std::tie(other.site_, other.nonce_);
54 }
55
56 // static
Serialize(const absl::optional<CookiePartitionKey> & in,std::string & out)57 bool CookiePartitionKey::Serialize(const absl::optional<CookiePartitionKey>& in,
58 std::string& out) {
59 if (!in) {
60 out = kEmptyCookiePartitionKey;
61 return true;
62 }
63 if (!in->IsSerializeable()) {
64 DLOG(WARNING) << "CookiePartitionKey is not serializeable";
65 return false;
66 }
67 out = in->site_.GetURL().SchemeIsFile()
68 ? in->site_.SerializeFileSiteWithHost()
69 : in->site_.Serialize();
70 return true;
71 }
72
73 // static
Deserialize(const std::string & in,absl::optional<CookiePartitionKey> & out)74 bool CookiePartitionKey::Deserialize(const std::string& in,
75 absl::optional<CookiePartitionKey>& out) {
76 if (in == kEmptyCookiePartitionKey) {
77 out = absl::nullopt;
78 return true;
79 }
80 if (!base::FeatureList::IsEnabled(features::kPartitionedCookies)) {
81 DLOG(WARNING) << "Attempting to deserialize CookiePartitionKey when "
82 "PartitionedCookies is disabled";
83 return false;
84 }
85 auto schemeful_site = SchemefulSite::Deserialize(in);
86 // SchemfulSite is opaque if the input is invalid.
87 if (schemeful_site.opaque()) {
88 DLOG(WARNING) << "Cannot deserialize opaque origin to CookiePartitionKey";
89 return false;
90 }
91 out = absl::make_optional(CookiePartitionKey(schemeful_site, absl::nullopt));
92 return true;
93 }
94
FromNetworkIsolationKey(const NetworkIsolationKey & network_isolation_key)95 absl::optional<CookiePartitionKey> CookiePartitionKey::FromNetworkIsolationKey(
96 const NetworkIsolationKey& network_isolation_key) {
97 if (!base::FeatureList::IsEnabled(features::kPartitionedCookies)) {
98 return absl::nullopt;
99 }
100
101 const absl::optional<base::UnguessableToken>& nonce =
102 network_isolation_key.GetNonce();
103
104 // Use frame site for nonced partitions. Since the nonce is unique, this still
105 // creates a unique partition key. The reason we use the frame site is to
106 // align CookiePartitionKey's implementation of nonced partitions with
107 // StorageKey's. See https://crbug.com/1440765.
108 const absl::optional<SchemefulSite>& partition_key_site =
109 nonce ? network_isolation_key.GetFrameSiteForCookiePartitionKey(
110 NetworkIsolationKey::CookiePartitionKeyPassKey())
111 : network_isolation_key.GetTopFrameSite();
112 if (!partition_key_site)
113 return absl::nullopt;
114
115 return net::CookiePartitionKey(*partition_key_site, nonce);
116 }
117
118 // static
119 absl::optional<net::CookiePartitionKey>
FromStorageKeyComponents(const SchemefulSite & site,const absl::optional<base::UnguessableToken> & nonce)120 CookiePartitionKey::FromStorageKeyComponents(
121 const SchemefulSite& site,
122 const absl::optional<base::UnguessableToken>& nonce) {
123 if (!base::FeatureList::IsEnabled(features::kPartitionedCookies)) {
124 return absl::nullopt;
125 }
126 return CookiePartitionKey::FromWire(site, nonce);
127 }
128
IsSerializeable() const129 bool CookiePartitionKey::IsSerializeable() const {
130 if (!base::FeatureList::IsEnabled(features::kPartitionedCookies)) {
131 DLOG(WARNING) << "Attempting to serialize CookiePartitionKey when "
132 "PartitionedCookies feature is disabled";
133 return false;
134 }
135 // We should not try to serialize a partition key created by a renderer.
136 DCHECK(!from_script_);
137 return !site_.opaque() && !nonce_.has_value();
138 }
139
operator <<(std::ostream & os,const CookiePartitionKey & cpk)140 std::ostream& operator<<(std::ostream& os, const CookiePartitionKey& cpk) {
141 os << cpk.site();
142 if (cpk.nonce().has_value()) {
143 os << ",nonced";
144 }
145 return os;
146 }
147
148 } // namespace net
149