Extract UniqueCookieKey type
This introduces a new class, UniqueCookieKey, to replace 4 distinct tuple aliases: StrictlyUniqueCookieKey, UniqueCookieKey, UniqueDomainCookieKey, and LegacyUniqueCookieKey. Turning these into dedicated types (rather than just aliases of tuples) has a few notable consequences: * Member accesses are more readable and maintainable, e.g. `signature.domain()` instead of `std::get<2>(signature)`. * CookieMonster's duplicate filtering logic no longer needs to be aware of host cookies vs domain cookies; it can just call UniqueKey() which will do the right thing instead of requiring the caller to know how to branch correctly. * We can now merge CookieBase::UniqueKey() and CookieBase::UniqueDomainKey() into a single function that is aware of what kind of key it should create. * We can now guarantee that these keys can only be created via the accessors in CookieBase. * The type system can no longer guarantee the usage of a Legacy key instead of a Strict key, or vice versa, since they're the same type. (This doesn't seem like a likely source of bugs to me, so I think this is fine. But we can also make Strict and Legacy keys their own types.) Fixed: 390345080 Change-Id: Iaebf4d34e854adbbfc4483ad4d2fc58794659199 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6175944 Reviewed-by: Steven Bingler <bingler@chromium.org> Auto-Submit: Chris Fredrickson <cfredric@chromium.org> Reviewed-by: David Song <wintermelons@google.com> Reviewed-by: Maks Orlovich <morlovich@chromium.org> Commit-Queue: Chris Fredrickson <cfredric@chromium.org> Reviewed-by: Jood Hajeer <jood@google.com> Cr-Commit-Position: refs/heads/main@{#1407461}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
651c992f3a
commit
c9dad5877d
chrome/browser/ash/floating_sso
fuchsia_web/webengine/browser
net
@ -19,6 +19,7 @@
|
||||
#include "net/cookies/canonical_cookie.h"
|
||||
#include "net/cookies/cookie_constants.h"
|
||||
#include "net/cookies/cookie_partition_key.h"
|
||||
#include "net/cookies/unique_cookie_key.h"
|
||||
|
||||
namespace ash::floating_sso {
|
||||
|
||||
@ -186,8 +187,16 @@ std::optional<std::string> SerializedKey(const net::CanonicalCookie& cookie) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto& [partition_key, name, domain, path, source_scheme, source_port] =
|
||||
cookie.StrictlyUniqueKey();
|
||||
const net::UniqueCookieKey strict_unique_key = cookie.StrictlyUniqueKey();
|
||||
const std::string& name = strict_unique_key.name();
|
||||
const std::string& domain = strict_unique_key.domain();
|
||||
const std::string& path = strict_unique_key.path();
|
||||
// `source_scheme()` and `port()` are guaranteed to return non-nullopt values,
|
||||
// since we created the key via StrictlyUniqueKey.
|
||||
const net::CookieSourceScheme source_scheme =
|
||||
strict_unique_key.source_scheme().value();
|
||||
const int source_port = strict_unique_key.port().value();
|
||||
|
||||
// We just concatenate all involved strings.
|
||||
std::string serialized_key = base::StrCat(
|
||||
{serialized_partition_key->TopLevelSite(),
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "mojo/public/cpp/bindings/receiver.h"
|
||||
#include "net/cookies/canonical_cookie.h"
|
||||
#include "net/cookies/cookie_change_dispatcher.h"
|
||||
#include "net/cookies/unique_cookie_key.h"
|
||||
#include "services/network/public/mojom/network_context.mojom.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
@ -150,8 +151,7 @@ class CookiesIteratorImpl final : public fuchsia::web::CookiesIterator,
|
||||
|
||||
// Map from "unique key"s (see net::CanonicalCookie::UniqueKey()) to the
|
||||
// corresponding fuchsia::web::Cookie.
|
||||
std::map<net::CanonicalCookie::UniqueCookieKey, fuchsia::web::Cookie>
|
||||
queued_cookies_;
|
||||
std::map<net::UniqueCookieKey, fuchsia::web::Cookie> queued_cookies_;
|
||||
};
|
||||
|
||||
void OnAllCookiesReceived(
|
||||
|
@ -432,6 +432,8 @@ component("net") {
|
||||
"cookies/site_for_cookies.h",
|
||||
"cookies/static_cookie_policy.cc",
|
||||
"cookies/static_cookie_policy.h",
|
||||
"cookies/unique_cookie_key.cc",
|
||||
"cookies/unique_cookie_key.h",
|
||||
"device_bound_sessions/session_key.cc",
|
||||
"device_bound_sessions/session_key.h",
|
||||
"disk_cache/backend_cleanup_tracker.cc",
|
||||
|
@ -240,17 +240,8 @@ class NET_EXPORT CanonicalCookie : public CookieBase {
|
||||
bool IsEquivalent(const CanonicalCookie& ecc) const {
|
||||
// It seems like it would make sense to take secure, httponly, and samesite
|
||||
// into account, but the RFC doesn't specify this.
|
||||
// NOTE: Keep this logic in-sync with TrimDuplicateCookiesForKey().
|
||||
|
||||
// A host cookie will never match a domain cookie or vice-versa, this is
|
||||
// because the "host-only-flag" is encoded within the `domain` field of the
|
||||
// respective keys. So we don't need to explicitly check if ecc is also host
|
||||
// or domain.
|
||||
if (IsHostCookie()) {
|
||||
return UniqueKey() == ecc.UniqueKey();
|
||||
}
|
||||
// Is domain cookie
|
||||
return UniqueDomainKey() == ecc.UniqueDomainKey();
|
||||
return UniqueKey() == ecc.UniqueKey();
|
||||
}
|
||||
|
||||
// Checks a looser set of equivalency rules than 'IsEquivalent()' in order
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/feature_list.h"
|
||||
#include "base/strings/strcat.h"
|
||||
#include "base/types/pass_key.h"
|
||||
#include "net/base/features.h"
|
||||
#include "net/cookies/cookie_constants.h"
|
||||
#include "net/cookies/cookie_inclusion_status.h"
|
||||
@ -553,30 +554,29 @@ std::string CookieBase::DomainWithoutDot() const {
|
||||
return cookie_util::CookieDomainAsHost(domain_);
|
||||
}
|
||||
|
||||
CookieBase::UniqueCookieKey CookieBase::UniqueKey() const {
|
||||
std::optional<CookieSourceScheme> source_scheme =
|
||||
cookie_util::IsSchemeBoundCookiesEnabled()
|
||||
? std::make_optional(source_scheme_)
|
||||
: std::nullopt;
|
||||
std::optional<int> source_port = cookie_util::IsPortBoundCookiesEnabled()
|
||||
? std::make_optional(source_port_)
|
||||
: std::nullopt;
|
||||
|
||||
return std::make_tuple(partition_key_, name_, domain_, path_, source_scheme,
|
||||
source_port);
|
||||
}
|
||||
|
||||
CookieBase::UniqueDomainCookieKey CookieBase::UniqueDomainKey() const {
|
||||
UniqueCookieKey CookieBase::UniqueKey() const {
|
||||
std::optional<CookieSourceScheme> source_scheme =
|
||||
cookie_util::IsSchemeBoundCookiesEnabled()
|
||||
? std::make_optional(source_scheme_)
|
||||
: std::nullopt;
|
||||
|
||||
return std::make_tuple(partition_key_, name_, domain_, path_, source_scheme);
|
||||
if (IsHostCookie()) {
|
||||
std::optional<int> source_port = cookie_util::IsPortBoundCookiesEnabled()
|
||||
? std::make_optional(source_port_)
|
||||
: std::nullopt;
|
||||
|
||||
return UniqueCookieKey::Host(base::PassKey<CookieBase>(), partition_key_,
|
||||
name_, domain_, path_, source_scheme,
|
||||
source_port);
|
||||
}
|
||||
|
||||
return UniqueCookieKey::Domain(base::PassKey<CookieBase>(), partition_key_,
|
||||
name_, domain_, path_, source_scheme);
|
||||
}
|
||||
|
||||
CookieBase::LegacyUniqueCookieKey CookieBase::LegacyUniqueKey() const {
|
||||
return std::make_tuple(partition_key_, name_, domain_, path_);
|
||||
UniqueCookieKey CookieBase::LegacyUniqueKey() const {
|
||||
return UniqueCookieKey::Legacy(base::PassKey<CookieBase>(), partition_key_,
|
||||
name_, domain_, path_);
|
||||
}
|
||||
|
||||
void CookieBase::SetSourcePort(int port) {
|
||||
|
@ -9,12 +9,14 @@
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
#include "base/types/pass_key.h"
|
||||
#include "net/base/net_export.h"
|
||||
#include "net/cookies/cookie_access_params.h"
|
||||
#include "net/cookies/cookie_access_result.h"
|
||||
#include "net/cookies/cookie_constants.h"
|
||||
#include "net/cookies/cookie_options.h"
|
||||
#include "net/cookies/cookie_partition_key.h"
|
||||
#include "net/cookies/unique_cookie_key.h"
|
||||
|
||||
class GURL;
|
||||
|
||||
@ -25,39 +27,6 @@ namespace net {
|
||||
// the request context.
|
||||
class NET_EXPORT CookieBase {
|
||||
public:
|
||||
// StrictlyUniqueCookieKey always populates the cookie's source scheme and
|
||||
// source port.
|
||||
using StrictlyUniqueCookieKey = std::tuple<std::optional<CookiePartitionKey>,
|
||||
/*name=*/std::string,
|
||||
/*domain=*/std::string,
|
||||
/*path=*/std::string,
|
||||
CookieSourceScheme,
|
||||
/*source_port=*/int>;
|
||||
|
||||
// Conditionally populates the source scheme and source port depending on the
|
||||
// state of their associated feature.
|
||||
using UniqueCookieKey = std::tuple<std::optional<CookiePartitionKey>,
|
||||
/*name=*/std::string,
|
||||
/*domain=*/std::string,
|
||||
/*path=*/std::string,
|
||||
std::optional<CookieSourceScheme>,
|
||||
/*source_port=*/std::optional<int>>;
|
||||
|
||||
// Same as UniqueCookieKey but for use with Domain cookies, which do not
|
||||
// consider the source_port.
|
||||
using UniqueDomainCookieKey = std::tuple<std::optional<CookiePartitionKey>,
|
||||
/*name=*/std::string,
|
||||
/*domain=*/std::string,
|
||||
/*path=*/std::string,
|
||||
std::optional<CookieSourceScheme>>;
|
||||
|
||||
// Same as UniqueCookieKey but for use with Legacy Scoped cookies, which do
|
||||
// not consider the source_port or source_scheme.
|
||||
using LegacyUniqueCookieKey = std::tuple<std::optional<CookiePartitionKey>,
|
||||
/*name=*/std::string,
|
||||
/*domain=*/std::string,
|
||||
/*path=*/std::string>;
|
||||
|
||||
// Returns if the cookie should be included (and if not, why) for the given
|
||||
// request |url| using the CookieInclusionStatus enum. HTTP only cookies can
|
||||
// be filter by using appropriate cookie |options|.
|
||||
@ -160,9 +129,12 @@ class NET_EXPORT CookieBase {
|
||||
// This corresponds to the "cookie's domain" as described in RFC 6265bis.
|
||||
std::string DomainWithoutDot() const;
|
||||
|
||||
StrictlyUniqueCookieKey StrictlyUniqueKey() const {
|
||||
return std::make_tuple(partition_key_, name_, domain_, path_,
|
||||
source_scheme_, source_port_);
|
||||
// StrictlyUniqueKey always includes the cookie's source scheme and source
|
||||
// port.
|
||||
UniqueCookieKey StrictlyUniqueKey() const {
|
||||
return UniqueCookieKey::Strict(base::PassKey<CookieBase>(), partition_key_,
|
||||
name_, domain_, path_, source_scheme_,
|
||||
source_port_);
|
||||
}
|
||||
|
||||
// Returns a key such that two cookies with the same UniqueKey() are
|
||||
@ -173,14 +145,10 @@ class NET_EXPORT CookieBase {
|
||||
// associated features are enabled.
|
||||
UniqueCookieKey UniqueKey() const;
|
||||
|
||||
// Same as UniqueKey() except it does not contain a source_port field. For use
|
||||
// with Domain cookies, which do not consider the source_port.
|
||||
UniqueDomainCookieKey UniqueDomainKey() const;
|
||||
|
||||
// Same as UniqueKey() except it does not contain a source_port or
|
||||
// source_scheme field. For use for determining aliasing cookies, which do not
|
||||
// consider the source_port or source_scheme.
|
||||
LegacyUniqueCookieKey LegacyUniqueKey() const;
|
||||
UniqueCookieKey LegacyUniqueKey() const;
|
||||
|
||||
void SetSourceScheme(CookieSourceScheme source_scheme) {
|
||||
source_scheme_ = source_scheme;
|
||||
|
@ -80,6 +80,7 @@
|
||||
#include "net/base/schemeful_site.h"
|
||||
#include "net/base/url_util.h"
|
||||
#include "net/cookies/canonical_cookie.h"
|
||||
#include "net/cookies/cookie_base.h"
|
||||
#include "net/cookies/cookie_constants.h"
|
||||
#include "net/cookies/cookie_monster_change_dispatcher.h"
|
||||
#include "net/cookies/cookie_monster_netlog_params.h"
|
||||
@ -1170,15 +1171,10 @@ void CookieMonster::TrimDuplicateCookiesForKey(
|
||||
typedef std::multiset<CookieMap::iterator, OrderByCreationTimeDesc> CookieSet;
|
||||
|
||||
// Helper map we populate to find the duplicates.
|
||||
typedef std::map<CanonicalCookie::UniqueCookieKey, CookieSet> EquivalenceMap;
|
||||
typedef std::map<CanonicalCookie::UniqueDomainCookieKey, CookieSet>
|
||||
DomainEquivalenceMap;
|
||||
EquivalenceMap equivalent_cookies;
|
||||
DomainEquivalenceMap equivalent_domain_cookies;
|
||||
std::map<UniqueCookieKey, CookieSet> equivalent_cookies;
|
||||
|
||||
// The number of duplicate cookies that have been found.
|
||||
int num_duplicates = 0;
|
||||
int num_domain_duplicates = 0;
|
||||
|
||||
// Iterate through all of the cookies in our range, and insert them into
|
||||
// the equivalence map.
|
||||
@ -1186,49 +1182,31 @@ void CookieMonster::TrimDuplicateCookiesForKey(
|
||||
DCHECK_EQ(key, it->first);
|
||||
CanonicalCookie* cookie = it->second.get();
|
||||
|
||||
if (cookie->IsHostCookie()) {
|
||||
CanonicalCookie::UniqueCookieKey signature(cookie->UniqueKey());
|
||||
CookieSet& set = equivalent_cookies[signature];
|
||||
UniqueCookieKey signature(cookie->UniqueKey());
|
||||
CookieSet& set = equivalent_cookies[signature];
|
||||
|
||||
// We found a duplicate!
|
||||
if (!set.empty()) {
|
||||
num_duplicates++;
|
||||
}
|
||||
|
||||
// We save the iterator into |cookies_| rather than the actual cookie
|
||||
// pointer, since we may need to delete it later.
|
||||
set.insert(it);
|
||||
// We found a duplicate!
|
||||
if (!set.empty()) {
|
||||
num_duplicates++;
|
||||
}
|
||||
// Is a domain cookie.
|
||||
else {
|
||||
CanonicalCookie::UniqueDomainCookieKey signature(
|
||||
cookie->UniqueDomainKey());
|
||||
CookieSet& domain_set = equivalent_domain_cookies[signature];
|
||||
|
||||
// We found a duplicate!
|
||||
if (!domain_set.empty()) {
|
||||
num_domain_duplicates++;
|
||||
}
|
||||
|
||||
// We save the iterator into |cookies_| rather than the actual cookie
|
||||
// pointer, since we may need to delete it later.
|
||||
domain_set.insert(it);
|
||||
}
|
||||
// We save the iterator into |cookies_| rather than the actual cookie
|
||||
// pointer, since we may need to delete it later.
|
||||
set.insert(it);
|
||||
}
|
||||
|
||||
// If there were no duplicates, we are done!
|
||||
if (num_duplicates == 0 && num_domain_duplicates == 0) {
|
||||
if (num_duplicates == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we find everything below that we did above.
|
||||
int num_duplicates_found = 0;
|
||||
|
||||
// Otherwise, delete all the duplicate host cookies, both from our in-memory
|
||||
// Otherwise, delete all the duplicate cookies, both from our in-memory
|
||||
// store and from the backing store.
|
||||
for (std::pair<const CanonicalCookie::UniqueCookieKey, CookieSet>&
|
||||
equivalent_cookie : equivalent_cookies) {
|
||||
const CanonicalCookie::UniqueCookieKey& signature = equivalent_cookie.first;
|
||||
for (auto& equivalent_cookie : equivalent_cookies) {
|
||||
const UniqueCookieKey& signature = equivalent_cookie.first;
|
||||
CookieSet& dupes = equivalent_cookie.second;
|
||||
|
||||
if (dupes.size() <= 1) {
|
||||
@ -1248,9 +1226,8 @@ void CookieMonster::TrimDuplicateCookiesForKey(
|
||||
LOG(ERROR) << base::StringPrintf(
|
||||
"Found %d duplicate cookies for key='%s', "
|
||||
"with {name='%s', domain='%s', path='%s'}",
|
||||
static_cast<int>(dupes.size()), key.c_str(),
|
||||
std::get<1>(signature).c_str(), std::get<2>(signature).c_str(),
|
||||
std::get<3>(signature).c_str());
|
||||
static_cast<int>(dupes.size()), key.c_str(), signature.name().c_str(),
|
||||
signature.domain().c_str(), signature.path().c_str());
|
||||
|
||||
// Remove all the cookies identified by |dupes|. It is valid to delete our
|
||||
// list of iterators one at a time, since |cookies_| is a multimap (they
|
||||
@ -1267,58 +1244,6 @@ void CookieMonster::TrimDuplicateCookiesForKey(
|
||||
}
|
||||
}
|
||||
CHECK_EQ(num_duplicates, num_duplicates_found);
|
||||
|
||||
// Do the same again for domain cookies.
|
||||
|
||||
if (num_domain_duplicates == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int num_domain_duplicates_found = 0;
|
||||
|
||||
for (std::pair<const CanonicalCookie::UniqueDomainCookieKey, CookieSet>&
|
||||
equivalent_domain_cookie : equivalent_domain_cookies) {
|
||||
const CanonicalCookie::UniqueDomainCookieKey& signature =
|
||||
equivalent_domain_cookie.first;
|
||||
CookieSet& dupes = equivalent_domain_cookie.second;
|
||||
|
||||
if (dupes.size() <= 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
num_domain_duplicates_found += dupes.size() - 1;
|
||||
|
||||
// Since |dupes| is sorted by creation time (descending), the first cookie
|
||||
// is the most recent one (or tied for it), so we will keep it. The rest are
|
||||
// duplicates.
|
||||
dupes.erase(dupes.begin());
|
||||
|
||||
// TODO(crbug.com/40188414) Include cookie partition key in this log
|
||||
// statement as well if needed.
|
||||
// TODO(crbug.com/40165805): Include source scheme and source port.
|
||||
LOG(ERROR) << base::StringPrintf(
|
||||
"Found %d duplicate domain cookies for key='%s', "
|
||||
"with {name='%s', domain='%s', path='%s'}",
|
||||
static_cast<int>(dupes.size()), key.c_str(),
|
||||
std::get<1>(signature).c_str(), std::get<2>(signature).c_str(),
|
||||
std::get<3>(signature).c_str());
|
||||
|
||||
// Remove all the cookies identified by |dupes|. It is valid to delete our
|
||||
// list of iterators one at a time, since |cookies_| is a multimap (they
|
||||
// don't invalidate existing iterators following deletion).
|
||||
for (const CookieMap::iterator& dupe : dupes) {
|
||||
if (cookie_partition_it) {
|
||||
InternalDeletePartitionedCookie(
|
||||
cookie_partition_it.value(), dupe, true,
|
||||
DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE);
|
||||
} else {
|
||||
InternalDeleteCookie(dupe, true,
|
||||
DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_EQ(num_domain_duplicates, num_domain_duplicates_found);
|
||||
}
|
||||
|
||||
std::vector<CanonicalCookie*>
|
||||
@ -1336,8 +1261,7 @@ CookieMonster::FindCookiesForRegistryControlledHost(
|
||||
// This map stores the most recently created cookie's creation time and if it
|
||||
// is expired or not. This is used to keep track if the entire group of
|
||||
// aliasing cookies should be deleted.
|
||||
std::map<CanonicalCookie::LegacyUniqueCookieKey, std::pair<Time, bool>>
|
||||
most_recent_cookie;
|
||||
std::map<UniqueCookieKey, std::pair<Time, bool>> most_recent_cookie;
|
||||
|
||||
bool legacy_mode_active = false;
|
||||
|
||||
@ -1477,9 +1401,8 @@ void CookieMonster::FilterCookiesWithOptions(
|
||||
}
|
||||
}
|
||||
|
||||
// Map to store the most recent aliasing cookie and it's CookieAccessResult
|
||||
std::map<CanonicalCookie::LegacyUniqueCookieKey, CookieAndAccessResult*>
|
||||
latest_aliasing_cookies;
|
||||
// Map to store the most recent aliasing cookie and its CookieAccessResult
|
||||
std::map<UniqueCookieKey, CookieAndAccessResult*> latest_aliasing_cookies;
|
||||
|
||||
for (auto& cookie_result : cookies_and_access_results) {
|
||||
CanonicalCookie* cookie_ptr = cookie_result.first;
|
||||
|
@ -170,8 +170,7 @@ class MockSimplePersistentCookieStore
|
||||
~MockSimplePersistentCookieStore() override;
|
||||
|
||||
private:
|
||||
typedef std::map<CanonicalCookie::UniqueCookieKey, CanonicalCookie>
|
||||
CanonicalCookieMap;
|
||||
typedef std::map<UniqueCookieKey, CanonicalCookie> CanonicalCookieMap;
|
||||
|
||||
CanonicalCookieMap cookies_;
|
||||
|
||||
|
106
net/cookies/unique_cookie_key.cc
Normal file
106
net/cookies/unique_cookie_key.cc
Normal file
@ -0,0 +1,106 @@
|
||||
// Copyright 2025 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "net/cookies/unique_cookie_key.h"
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "net/cookies/cookie_constants.h"
|
||||
#include "net/cookies/cookie_partition_key.h"
|
||||
|
||||
namespace net {
|
||||
|
||||
class CookieBase;
|
||||
|
||||
// static
|
||||
UniqueCookieKey UniqueCookieKey::Strict(
|
||||
base::PassKey<CookieBase>,
|
||||
std::optional<CookiePartitionKey> partition_key,
|
||||
std::string name,
|
||||
std::string domain,
|
||||
std::string path,
|
||||
CookieSourceScheme source_scheme,
|
||||
int source_port) {
|
||||
return UniqueCookieKey(KeyType::kStrict, std::move(partition_key),
|
||||
std::move(name), std::move(domain), std::move(path),
|
||||
source_scheme, source_port);
|
||||
}
|
||||
|
||||
// static
|
||||
UniqueCookieKey UniqueCookieKey::Host(
|
||||
base::PassKey<CookieBase>,
|
||||
std::optional<CookiePartitionKey> partition_key,
|
||||
std::string name,
|
||||
std::string domain,
|
||||
std::string path,
|
||||
std::optional<CookieSourceScheme> source_scheme,
|
||||
std::optional<int> source_port) {
|
||||
return UniqueCookieKey(KeyType::kHost, std::move(partition_key),
|
||||
std::move(name), std::move(domain), std::move(path),
|
||||
source_scheme, source_port);
|
||||
}
|
||||
|
||||
// static
|
||||
UniqueCookieKey UniqueCookieKey::Domain(
|
||||
base::PassKey<CookieBase>,
|
||||
std::optional<CookiePartitionKey> partition_key,
|
||||
std::string name,
|
||||
std::string domain,
|
||||
std::string path,
|
||||
std::optional<CookieSourceScheme> source_scheme) {
|
||||
return UniqueCookieKey(KeyType::kDomain, std::move(partition_key),
|
||||
std::move(name), std::move(domain), std::move(path),
|
||||
source_scheme, /*port=*/std::nullopt);
|
||||
}
|
||||
|
||||
// static
|
||||
UniqueCookieKey UniqueCookieKey::Legacy(
|
||||
base::PassKey<CookieBase>,
|
||||
std::optional<CookiePartitionKey> partition_key,
|
||||
std::string name,
|
||||
std::string domain,
|
||||
std::string path) {
|
||||
return UniqueCookieKey(KeyType::kLegacy, std::move(partition_key),
|
||||
std::move(name), std::move(domain), std::move(path),
|
||||
/*source_scheme=*/std::nullopt,
|
||||
/*port=*/std::nullopt);
|
||||
}
|
||||
|
||||
UniqueCookieKey::UniqueCookieKey(UniqueCookieKey&& other) = default;
|
||||
UniqueCookieKey::UniqueCookieKey(const UniqueCookieKey& other) = default;
|
||||
UniqueCookieKey& UniqueCookieKey::operator=(UniqueCookieKey&& other) = default;
|
||||
UniqueCookieKey& UniqueCookieKey::operator=(const UniqueCookieKey& other) =
|
||||
default;
|
||||
|
||||
UniqueCookieKey::~UniqueCookieKey() = default;
|
||||
|
||||
bool UniqueCookieKey::operator==(const UniqueCookieKey& other) const = default;
|
||||
|
||||
bool UniqueCookieKey::operator<(const UniqueCookieKey& other) const {
|
||||
return std::tie(key_type_, partition_key_, name_, domain_, path_,
|
||||
source_scheme_,
|
||||
port_) < std::tie(other.key_type_, other.partition_key_,
|
||||
other.name_, other.domain_, other.path_,
|
||||
other.source_scheme_, other.port_);
|
||||
}
|
||||
|
||||
UniqueCookieKey::UniqueCookieKey(
|
||||
KeyType key_type,
|
||||
std::optional<CookiePartitionKey> partition_key,
|
||||
std::string name,
|
||||
std::string domain,
|
||||
std::string path,
|
||||
std::optional<CookieSourceScheme> source_scheme,
|
||||
std::optional<int> port)
|
||||
: key_type_(key_type),
|
||||
partition_key_(std::move(partition_key)),
|
||||
name_(std::move(name)),
|
||||
domain_(std::move(domain)),
|
||||
path_(std::move(path)),
|
||||
source_scheme_(source_scheme),
|
||||
port_(port) {}
|
||||
|
||||
} // namespace net
|
108
net/cookies/unique_cookie_key.h
Normal file
108
net/cookies/unique_cookie_key.h
Normal file
@ -0,0 +1,108 @@
|
||||
// Copyright 2025 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef NET_COOKIES_UNIQUE_COOKIE_KEY_H_
|
||||
#define NET_COOKIES_UNIQUE_COOKIE_KEY_H_
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "base/types/pass_key.h"
|
||||
#include "net/base/net_export.h"
|
||||
#include "net/cookies/cookie_constants.h"
|
||||
#include "net/cookies/cookie_partition_key.h"
|
||||
|
||||
namespace net {
|
||||
|
||||
class CookieBase;
|
||||
|
||||
class NET_EXPORT UniqueCookieKey {
|
||||
public:
|
||||
// Always populates the cookie's source scheme and source port.
|
||||
static UniqueCookieKey Strict(base::PassKey<CookieBase>,
|
||||
std::optional<CookiePartitionKey> partition_key,
|
||||
std::string name,
|
||||
std::string domain,
|
||||
std::string path,
|
||||
CookieSourceScheme source_scheme,
|
||||
int source_port);
|
||||
|
||||
// Conditionally populates the source scheme and source port depending on the
|
||||
// state of their associated feature.
|
||||
static UniqueCookieKey Host(base::PassKey<CookieBase>,
|
||||
std::optional<CookiePartitionKey> partition_key,
|
||||
std::string name,
|
||||
std::string domain,
|
||||
std::string path,
|
||||
std::optional<CookieSourceScheme> source_scheme,
|
||||
std::optional<int> source_port);
|
||||
|
||||
// Same as Host but for use with Domain cookies, which do not
|
||||
// consider the source_port.
|
||||
static UniqueCookieKey Domain(
|
||||
base::PassKey<CookieBase>,
|
||||
std::optional<CookiePartitionKey> partition_key,
|
||||
std::string name,
|
||||
std::string domain,
|
||||
std::string path,
|
||||
std::optional<CookieSourceScheme> source_scheme);
|
||||
|
||||
// Same as Host but for use with Legacy Scoped cookies, which do
|
||||
// not consider the source_port or source_scheme.
|
||||
static UniqueCookieKey Legacy(base::PassKey<CookieBase>,
|
||||
std::optional<CookiePartitionKey> partition_key,
|
||||
std::string name,
|
||||
std::string domain,
|
||||
std::string path);
|
||||
|
||||
UniqueCookieKey(UniqueCookieKey&& other);
|
||||
UniqueCookieKey(const UniqueCookieKey& other);
|
||||
UniqueCookieKey& operator=(UniqueCookieKey&& other);
|
||||
UniqueCookieKey& operator=(const UniqueCookieKey& other);
|
||||
|
||||
~UniqueCookieKey();
|
||||
|
||||
bool operator==(const UniqueCookieKey& other) const;
|
||||
bool operator<(const UniqueCookieKey& other) const;
|
||||
|
||||
const std::string& name() const { return name_; }
|
||||
const std::string& domain() const { return domain_; }
|
||||
const std::string& path() const { return path_; }
|
||||
std::optional<CookieSourceScheme> source_scheme() const {
|
||||
return source_scheme_;
|
||||
}
|
||||
std::optional<int> port() const { return port_; }
|
||||
|
||||
private:
|
||||
enum class KeyType {
|
||||
kStrict,
|
||||
kHost,
|
||||
kDomain,
|
||||
kLegacy,
|
||||
};
|
||||
|
||||
UniqueCookieKey(KeyType key_type,
|
||||
std::optional<CookiePartitionKey> partition_key,
|
||||
std::string name,
|
||||
std::string domain,
|
||||
std::string path,
|
||||
std::optional<CookieSourceScheme> source_scheme,
|
||||
std::optional<int> port);
|
||||
|
||||
// Keys of different "types" (i.e., created by different factory functions)
|
||||
// are never considered equivalent.
|
||||
KeyType key_type_;
|
||||
std::optional<CookiePartitionKey> partition_key_;
|
||||
std::string name_;
|
||||
std::string domain_;
|
||||
std::string path_;
|
||||
// Nullopt in kLegacy keys; may be nullopt in kDomain and kHost keys.
|
||||
std::optional<CookieSourceScheme> source_scheme_;
|
||||
// Nullopt in kLegacy and kDomain keys; may be nullopt in kHost keys.
|
||||
std::optional<int> port_;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
|
||||
#endif // NET_COOKIES_UNIQUE_COOKIE_KEY_H_
|
@ -36,6 +36,7 @@
|
||||
#include "net/cookies/canonical_cookie.h"
|
||||
#include "net/cookies/cookie_constants.h"
|
||||
#include "net/cookies/cookie_util.h"
|
||||
#include "net/cookies/unique_cookie_key.h"
|
||||
#include "net/extras/sqlite/cookie_crypto_delegate.h"
|
||||
#include "net/extras/sqlite/sqlite_persistent_store_backend_base.h"
|
||||
#include "net/log/net_log.h"
|
||||
@ -488,8 +489,7 @@ class SQLitePersistentCookieStore::Backend
|
||||
}
|
||||
|
||||
typedef std::list<std::unique_ptr<PendingOperation>> PendingOperationsForKey;
|
||||
typedef std::map<CanonicalCookie::StrictlyUniqueCookieKey,
|
||||
PendingOperationsForKey>
|
||||
typedef std::map<UniqueCookieKey, PendingOperationsForKey>
|
||||
PendingOperationsMap;
|
||||
PendingOperationsMap pending_ GUARDED_BY(lock_);
|
||||
PendingOperationsMap::size_type num_pending_ GUARDED_BY(lock_) = 0;
|
||||
|
Reference in New Issue
Block a user