*** aside
"In the beginning the Universe was cookies were created. This has
made a lot of people very angry and has been widely regarded as a bad move."
"Sometimes me think, what is friend? And then me say: a friend is someone to share last cookie with."
This directory is concerned with the management of cookies, as specified by RFC 6265bis. Cookies are implemented mostly in this directory, but also elsewhere, as described below.
*** promo
-
Those who wish to work with the implementation of cookies may refer to Life of a cookie and Cookie implementation classes.
-
Those who wish to make use of cookies elsewhere in Chromium may refer to Main interfaces for finding, setting, deleting, and observing cookies.
[TOC]
This section describes the lifecycle of a typical/simple cookie on most platforms, and serves as an overview of some important classes involved in managing cookies.
This only covers cookie accesses via
HTTP requests.
Other APIs for accessing cookies include JavaScript
(document.cookie
and CookieStore API) or Chrome
extensions
(chrome.cookies
).
*** note Summary:
- An HTTP response containing a
Set-Cookie
header is received. - The
Set-Cookie
header is processed byURLRequestHttpJob
. - The header contents are parsed into a
CanonicalCookie
and passed to theCookieStore
for storage.
A cookie starts as a Set-Cookie
header sent in the server's response to an
HTTP request:
HTTP/1.1 200 OK
Date: ...
Server: ...
...
Set-Cookie: chocolate_chip=tasty; Secure; SameSite=Lax; Max-Age=3600
The response passes through the HttpNetworkTransaction
and
HttpCache::Transaction
to the URLRequestHttpJob
. (See
Life of a URLRequest
for more details.) The URLRequestHttpJob
then reads any Set-Cookie
headers
in the response (there may be multiple) and processes each Set-Cookie
header
by calling into //net/cookies
classes for parsing and storing:
First, the cookie, which has been provided as a string, is parsed into a
ParsedCookie
. This struct simply records all the token-value pairs present in
the Set-Cookie
header and keeps track of which cookie attribute each
corresponds to. The first token-value pair is always treated as the cookie's
name and value.
The ParsedCookie
is then converted into a CanonicalCookie
. This is the main
data type representing cookies. Any cookie consumer that does not deal directly
with HTTP headers operates on CanonicalCookie
s. A CanonicalCookie
has some
additional guarantees of validity over a ParsedCookie
, such as valid
expiration times, valid domain and path attributes, etc. Once a
CanonicalCookie
is created, you will almost never see a ParsedCookie
used
for anything else.
If a valid CanonicalCookie
could not be created (due to some illegal syntax,
inconsistent attribute values, or other circumstances preventing parsing), then
we stop here, and URLRequestHttpJob
moves on to the next Set-Cookie
header.
The NetworkDelegate
also gets a chance to block the setting of the cookie,
based on the user's third-party cookie blocking settings. If it is blocked,
URLRequestHttpJob
likewise moves on to the next Set-Cookie
header.
If this did result in a valid and not-blocked CanonicalCookie
, it is then
passed to the CookieStore
to be stored.
*** note Summary:
- The
CookieStore
receives theCanonicalCookie
and validates some additional criteria before updating its in-memory cache of cookies. - The
CookieStore
may also update its on-disk backing store via theCookieMonster::PersistentCookieStore
interface. - The result of the cookie storage attempt is reported back to the
URLRequestHttpJob
.
The CookieStore
lives in the URLRequestContext
and its main implementation,
used for most platforms, is CookieMonster
. (The rest of this section assumes
that we are using a CookieMonster
.) It exposes an asynchronous interface for
storing and retrieving cookies.
When CookieMonster
receives a CanonicalCookie
to be set, it queues a task to
validate and set the cookie. Most of the time this runs immediately, but it may
be delayed if the network service has just started up, and the contents of the
PersistentCookieStore
are still being loaded from disk. It checks some
criteria against the cookie's source URL and a CookieOptions
object (which
contains some other parameters describing the "context" in which the cookie is
being set, such as whether it's being accessed in a same-site or cross-site
context).
If everything checks out, the CookieMonster
proceeds with setting the cookie.
If an equivalent cookie is present in the store, then it may be deleted.
Equivalent is defined as sharing a name, domain, and path, based on the
invariant specified by the RFC that no two such cookies may exist at a given
time. CookieMonster
stores its CanonicalCookie
s in a multimap keyed on the
registrable domain (eTLD+1) of the cookie's domain attribute.
The cookie may also be persisted to disk by a
CookieMonster::PersistentCookieStore
depending on factors like whether the
cookie is a persistent cookie (has an expiration date), whether session cookies
should also be persisted (e.g. if the browser is set to restore the previous
browsing session), and whether the profile should have persistent storage (e.g.
yes for normal profiles, but not for Incognito profiles). The
SQLitePersistentCookieStore
is the main implementation of
CookieMonster::PersistentCookieStore
. It stores cookies in a SQLite database
on disk, at a filepath specified by the user's profile.
After the cookie has been stored (or rejected), the CookieMonster
calls back
to the URLRequestHttpJob
with the outcome of the storage attempt. The
URLRequestHttpJob
stashes away the outcomes and stores them in the
URLRequest
after all Set-Cookie
headers in the response are processed, so
that interested parties (e.g. DevTools) can subsequently be notified of cookie
activity.
*** note Summary:
- A network request reaches the net stack and generates a
URLRequestHttpJob
, which queries theCookieStore
for cookies to include with the request. - The
CookieStore
evaluates each of its candidate cookies for whether it can be included in the request, and reports back to theURLRequestHttpJob
with included and excluded cookies. URLRequestHttpJob
serializes the included cookies into aCookie
request header and attaches it to the outgoing request.
Some time later, a (credentialed) request to the same eTLD+1 triggers a cookie
access in order to retrieve the relevant cookies to include in the outgoing
Cookie
request header. The request makes its way to the net stack and causes a
URLRequestHttpJob
to be created. (See
Life of a URLRequest
for more details.) Upon being started, the URLRequestHttpJob
asks the
CookieStore
to retrieve the correct cookies for the URL being requested.
The CookieMonster
queues a task to retrieve the cookies. Most of the time this
runs immediately, except if the contents of the PersistentCookieStore
are
still being loaded from disk. The CookieMonster
examines each of the cookies
it has stored for that URL's registrable domain and decides whether it should be
included or excluded for that request based on the requested URL and the
CookieOptions
, by computing a CookieInclusionStatus
. Criteria for inclusion
are described in
RFC 6265bis
and include: the URL matching the cookie's Domain
and Path
attributes, the
URL being secure if the cookie has the Secure
attribute, the request context
(i.e. CookieOptions
) being same-site if the cookie is subject to SameSite
enforcement, etc. If any of the requirements are not met, a
CookieInclusionStatus::ExclusionReason
is recorded.
After the exclusion reasons have been tallied up for each cookie, the cookies
without any exclusion reasons are deemed suitable for inclusion, and are
returned to the URLRequestHttpJob
. The excluded cookies are also returned,
along with the CookieInclusionStatus
describing why each cookie was excluded.
The included cookies are serialized into a Cookie
header string (if the
NetworkDelegate
is ok with it, based on the user's third-party cookie blocking
settings). The URLRequestHttpJob
attaches this Cookie
header to the outgoing
request headers:
GET /me/want/cookie/omnomnomnom HTTP/1.1
Host: ...
User-Agent: ...
Cookie: chocolate_chip=tasty
...
The included cookies, excluded cookies, and their corresponding
CookieInclusionStatus
es are also stored in the URLRequest
to notify
consumers of cookie activity notifications.
This section lists classes involved in cookie management and access.
The core classes are highlighted.
*** note
-
The main data type representing cookies. Basically everything that's not directly dealing with HTTP headers or their equivalents operates on these.
These are generally obtained via
CanonicalCookie::Create()
, which parses a string (aSet-Cookie
header) into an intermediateParsedCookie
, whose fields it canonicalizes/validates and then copies into aCanonicalCookie
.
*** note
-
The main interface for a given platform's cookie handling. Provides asynchronous methods for setting and retrieving cookies.
Its implementations are responsible for keeping track of all the cookies, finding cookies relevant for given HTTP requests, saving cookies received in HTTP responses, etc., and need to know quite a bit about cookie semantics.
*** note
-
The implementation of
CookieStore
used on most platforms.It stores all cookies in a multimap keyed on the eTLD+1 of the cookie's domain. Also manages storage limits by evicting cookies when per-eTLD+1 or global cookie counts are exceeded.
It can optionally take an implementation of
CookieMonster::PersistentCookieStore
to load and store cookies persisently.
-
Contains parameters for a given attempt to access cookies via
CookieStore
, such as whether the access is for an HTTP request (as opposed to a JavaScript API), and the same-site or cross-site context of the request (relevant to enforcement of theSameSite
cookie attribute). -
Represents which origins should be considered "same-site" for a given context (e.g. frame). This is used to compute the same-site or cross-site context of a cookie access attempt (which is then conveyed to the
CookieStore
via aCookieOptions
).It is generally the eTLD+1 and scheme of the top-level frame. It may also be empty, in which case it represents a context that is cross-site to everything (e.g. a nested iframe whose ancestor frames don't all belong to the same site).
-
Records the outcome of a given attempt to access a cookie. Various reasons for cookie exclusion are recorded (
CookieInclusionStatus::ExclusionReason
), as well as informational statuses (CookieInclusionStatus::WarningReason
) typically used to emit warnings in DevTools.May be used as a member of a
CookieAccessResult
, which includes even more metadata about the outcome of a cookie access attempt. -
Interface for a
CookieStore
to query information from its embedder that may modify its decisions on cookie inclusion/exclusion. Its main implementation allowsCookieMonster
to access data from the network service layer (e.g.CookieManager
). -
Interface for subscribing to changes in the contents of the
CookieStore
. The main implementation isCookieMonsterChangeDispatcher
.
*** note
-
Implementation of
CookieMonster::PersistentCookieStore
used on most platforms. Uses a SQLite database to load and store cookies, potentially using an optional delegate to encrypt and decrypt their at-rest versions. This class is refcounted.CookieMonster
loads cookies from here on startup. All other operations attempting to access cookies in the process of being loaded are blocked until loading of those cookies completes. Thus, it fast-tracks loading of cookies for an eTLD+1 with pending requests, to decrease latency for cookie access operations made soon after browser startup (by decreasing the number of cookies whose loading is blocking requests).
*** note
-
A
URLRequestJob
implementation that handles HTTP requests; most relevantly, theCookie
andSet-Cookie
HTTP headers. It drives the process for storing cookies and retrieving cookies for HTTP requests.Also logs cookie events to the NetLog for each request.
-
Mostly relevant for its two members,
maybe_sent_cookies_
andmaybe_stored_cookies_
, which are vectors in whichURLRequestHttpJob
stashes the cookies it considered sending/storing and theirCookieInclusionStatus
es. These then get mojo'ed over to the browser process to notify observers of cookie activity.
*** note
-
The network service API to cookies. Basically exports a
CookieStore
via mojo IPC.Owned by the
NetworkContext
.
*** note
-
Mojo interface for accessing cookies for a specific origin. This can be handed out to untrusted (i.e. renderer) processes, as inputs are assumed to be unsafe.
It is primarily used for accessing cookies via JavaScript. It provides a synchronous interface for
document.cookie
, as well as an asynchronous one for the CookieStore API.
-
Keeps track of the content settings (per-profile permissions for types of content that a given origin is allowed to use) for cookies, such as the user's third-party cookie blocking settings, origins/domains with third-party cookie blocking exceptions or "legacy" access settings.
It is not to be confused with
content_settings::CookieSettings
, which manages the browser's version of the cookie content settings, of whichnetwork::ContentSettings
is approximately a copy/mirror. TheProfileNetworkContextService
populates its contents uponNetworkContext
construction from the browser-side content settings, and also updates it whenever the browser-side content settings change. -
Implements
CookieMonster::PersistentCookieStore
, by wrapping aSQLitePersistentCookieStore
. Keeps an in-memory map of cookies per eTLD+1 to allow deletion of cookies for sites whose cookie content setting is "session-only" from the persistent store when the session ends.
-
CookieAccessObserver
andWebContentsObserver
CookieAccessObserver
is a mojo interface used to observe attempts to access (read or write) cookies. It is implemented byNavigationHandle
andRenderFrameHost
.The cookie accesses are attributable to a committed document that called
document.cookie
or made a network request (if notified throughRenderFrameHost
), or a not-yet-committed navigation that resulted in a network request (if notified throughNavigationHandle
).The
CookieAccessObserver
s forward the notifications toWebContents
, which then notifies itsWebContentsObserver
s. One suchWebContentsObserver
that cares about this information isPageSpecificContentSettings
, which displays information about allowed and blocked cookies in UI surfaces (see next item). -
Stores cookie information for use in settings UI (the Page Info Bubble and various
chrome://settings
pages). Populated with info fromPageSpecificContentSettings
. -
Implements the
document.cookie
API in the renderer by requesting aRestrictedCookieManager
from the browser. -
Implements the JavaScript CookieStore API in the renderer by requesting a
RestrictedCookieManager
from the browser. (Not to be confused withnet::CookieStore
.) -
Implements the
chrome.cookies
API for Chrome extensions. Gives extensions with the proper permissions essentially unfettered access to theCookieStore
.
-
CookieStoreIOS
andCookieStoreIOSPersistent
iOS-specific
CookieStore
implementations, mainly relying on the iOS native cookie implementation (NSHTTPCookie
). -
android_webview::CookieManager
Manages cookies for Android WebView. It typically wraps a
network::mojom::CookieManager
, but it can also be used before aNetworkContext
even exists, thanks to Android WebView's cookie API, which means it is sometimes initialized with a barenet::CookieStore
.Also notable for allowing cookies for
file://
scheme URLs (normally they are only allowed for HTTP and websocket schemes andchrome-extension://
), though this is non-default and deprecated.
This section summarizes interfaces for interacting with cookies from various parts of the codebase.
*** note
Use net::CookieStore
to save and retrieve
CanonicalCookie
s.
-
CanonicalCookie
s are the main data type representing cookies. Get one usingCanonicalCookie::Create()
. -
The
CookieStore
can be accessed via its owningURLRequestContext
, which can be accessed throughNetworkContext
. -
To access cookies, you need a
CookieOptions
. The main things in this object are theHttpOnly
access permission and theSameSite
context. The latter can be obtained fromcookie_util
functions. -
Retrieve cookies using
GetCookieListWithOptionsAsync()
. -
Save cookies using
SetCanonicalCookieAsync()
.
*** note
Use CookieStore
to selectively delete cookies.
-
DeleteCanonicalCookieAsync()
deletes a single cookie. -
DeleteAllCreatedInTimeRangeAsync()
deletes cookies created in a time range. -
DeleteAllMatchingInfoAsync()
deletes cookies that match a filter.
*** note
Use the CookieChangeDispatcher
interface to subscribe to changes.
-
Use
AddCallbackForCookie()
to observe changes to cookies with a given name that would be sent with a request to a specific URL. -
Use
AddCallbackForUrl()
to observe changes to all cookies that would be sent with a request to a specific URL. -
Use
AddCallbackForAllChanges()
to observe changes to all cookies in theCookieStore
.
*** note
Use CookieManager
(which basically exports a net::CookieStore
interface via mojo) to save
and retrieve CanonicalCookie
s.
-
The profile's
CookieManager
can be accessed from the browser process throughStoragePartition::GetCookieManagerForBrowserProcess()
. -
You can also get get a
CookieManager
pipe from theNetworkContext
usingGetCookieManager()
. -
Retrieve cookies using
CookieManager::GetCookieList()
. -
Save cookies using
CookieManager::SetCanonicalCookie()
.
*** note
Use CookieManager
to selectively delete cookies.
-
If you have a copy of the
CanonicalCookie
to delete (e.g. a cookie previously fetched from the store), useCookieManager::DeleteCanonicalCookie()
. -
To delete cookies with certain characteristics, construct a
CookieDeletionFilter
and useCookieManager::DeleteCookies()
.
*** note
Use CookieManager
's change listener interface to subscribe to changes (this
parallels the net::CookieChangeDispatcher
interface).
-
Add a
CookieChangeListener
registration for a URL (and optionally a cookie name) viaAddCookieChangeListener()
-
Add a
CookieChangeListener
registration for all cookies viaAddGlobalChangeListener()
.
*** note
Use a
network::mojom::RestrictedCookieManager
interface to access cookies for a particular origin.
-
Request a
RestrictedCookieManager
interface from the browser. This creates aRestrictedCookieManager
bound to aRenderFrameHost
, which can only access cookies on behalf of the corresponding origin. -
Cookies can be read and written asynchronously (
GetAllForUrl()
,SetCanonicalCookie()
) or synchronously (SetCookieFromString()
,GetCookiesString()
). -
Compromised renderers shouldn't be able to access cookies of another site, or
HttpOnly
cookies (even from the same site).