• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
17 
PartitionedCookiesEnabled(const absl::optional<base::UnguessableToken> & nonce)18 bool PartitionedCookiesEnabled(
19     const absl::optional<base::UnguessableToken>& nonce) {
20   return base::FeatureList::IsEnabled(net::features::kPartitionedCookies) ||
21          (base::FeatureList::IsEnabled(
22               net::features::kNoncedPartitionedCookies) &&
23           nonce);
24 }
25 
26 }  // namespace
27 
28 namespace net {
29 
30 CookiePartitionKey::CookiePartitionKey() = default;
31 
CookiePartitionKey(const SchemefulSite & site,absl::optional<base::UnguessableToken> nonce)32 CookiePartitionKey::CookiePartitionKey(
33     const SchemefulSite& site,
34     absl::optional<base::UnguessableToken> nonce)
35     : site_(site), nonce_(nonce) {}
36 
CookiePartitionKey(const GURL & url)37 CookiePartitionKey::CookiePartitionKey(const GURL& url)
38     : site_(SchemefulSite(url)) {}
39 
CookiePartitionKey(bool from_script)40 CookiePartitionKey::CookiePartitionKey(bool from_script)
41     : from_script_(from_script) {}
42 
43 CookiePartitionKey::CookiePartitionKey(const CookiePartitionKey& other) =
44     default;
45 
46 CookiePartitionKey::CookiePartitionKey(CookiePartitionKey&& other) = default;
47 
48 CookiePartitionKey& CookiePartitionKey::operator=(
49     const CookiePartitionKey& other) = default;
50 
51 CookiePartitionKey& CookiePartitionKey::operator=(CookiePartitionKey&& other) =
52     default;
53 
54 CookiePartitionKey::~CookiePartitionKey() = default;
55 
operator ==(const CookiePartitionKey & other) const56 bool CookiePartitionKey::operator==(const CookiePartitionKey& other) const {
57   return site_ == other.site_ && nonce_ == other.nonce_;
58 }
59 
operator !=(const CookiePartitionKey & other) const60 bool CookiePartitionKey::operator!=(const CookiePartitionKey& other) const {
61   return site_ != other.site_ || nonce_ != other.nonce_;
62 }
63 
operator <(const CookiePartitionKey & other) const64 bool CookiePartitionKey::operator<(const CookiePartitionKey& other) const {
65   return std::tie(site_, nonce_) < std::tie(other.site_, other.nonce_);
66 }
67 
68 // static
Serialize(const absl::optional<CookiePartitionKey> & in,std::string & out)69 bool CookiePartitionKey::Serialize(const absl::optional<CookiePartitionKey>& in,
70                                    std::string& out) {
71   if (!in) {
72     out = kEmptyCookiePartitionKey;
73     return true;
74   }
75   if (!in->IsSerializeable()) {
76     DLOG(WARNING) << "CookiePartitionKey is not serializeable";
77     return false;
78   }
79   out = in->site_.GetURL().SchemeIsFile()
80             ? in->site_.SerializeFileSiteWithHost()
81             : in->site_.Serialize();
82   return true;
83 }
84 
85 // static
Deserialize(const std::string & in,absl::optional<CookiePartitionKey> & out)86 bool CookiePartitionKey::Deserialize(const std::string& in,
87                                      absl::optional<CookiePartitionKey>& out) {
88   if (in == kEmptyCookiePartitionKey) {
89     out = absl::nullopt;
90     return true;
91   }
92   if (!base::FeatureList::IsEnabled(features::kPartitionedCookies)) {
93     DLOG(WARNING) << "Attempting to deserialize CookiePartitionKey when "
94                      "PartitionedCookies is disabled";
95     return false;
96   }
97   auto schemeful_site = SchemefulSite::Deserialize(in);
98   // SchemfulSite is opaque if the input is invalid.
99   if (schemeful_site.opaque()) {
100     DLOG(WARNING) << "Cannot deserialize opaque origin to CookiePartitionKey";
101     return false;
102   }
103   out = absl::make_optional(CookiePartitionKey(schemeful_site, absl::nullopt));
104   return true;
105 }
106 
FromNetworkIsolationKey(const NetworkIsolationKey & network_isolation_key)107 absl::optional<CookiePartitionKey> CookiePartitionKey::FromNetworkIsolationKey(
108     const NetworkIsolationKey& network_isolation_key) {
109   absl::optional<base::UnguessableToken> nonce =
110       network_isolation_key.GetNonce();
111   // If PartitionedCookies is enabled, all partitioned cookies are allowed.
112   // If NoncedPartitionedCookies is enabled, only partitioned cookies whose
113   // partition key has a nonce are allowed.
114   if (!PartitionedCookiesEnabled(nonce))
115     return absl::nullopt;
116 
117   // TODO(crbug.com/1225444): Check if the top frame site is in a First-Party
118   // Set or if it is an extension URL.
119   const absl::optional<SchemefulSite>& partition_key_site =
120       nonce ? network_isolation_key.GetFrameSiteForCookiePartitionKey(
121                   NetworkIsolationKey::CookiePartitionKeyPasskey())
122             : network_isolation_key.GetTopFrameSite();
123   if (!partition_key_site)
124     return absl::nullopt;
125 
126   return net::CookiePartitionKey(*partition_key_site, nonce);
127 }
128 
129 // static
130 absl::optional<net::CookiePartitionKey>
FromStorageKeyComponents(const SchemefulSite & top_level_site,const absl::optional<base::UnguessableToken> & nonce)131 CookiePartitionKey::FromStorageKeyComponents(
132     const SchemefulSite& top_level_site,
133     const absl::optional<base::UnguessableToken>& nonce) {
134   if (!PartitionedCookiesEnabled(nonce))
135     return absl::nullopt;
136   return CookiePartitionKey::FromWire(top_level_site, nonce);
137 }
138 
IsSerializeable() const139 bool CookiePartitionKey::IsSerializeable() const {
140   if (!base::FeatureList::IsEnabled(features::kPartitionedCookies)) {
141     DLOG(WARNING) << "Attempting to serialize CookiePartitionKey when "
142                      "PartitionedCookies feature is disabled";
143     return false;
144   }
145   // We should not try to serialize a partition key created by a renderer.
146   DCHECK(!from_script_);
147   return !site_.opaque() && !nonce_.has_value();
148 }
149 
operator <<(std::ostream & os,const CookiePartitionKey & cpk)150 std::ostream& operator<<(std::ostream& os, const CookiePartitionKey& cpk) {
151   os << cpk.site();
152   if (cpk.nonce().has_value()) {
153     os << ",nonced";
154   }
155   return os;
156 }
157 
158 }  // namespace net
159