547 lines
23 KiB
Markdown
547 lines
23 KiB
Markdown
|
|
# Cookies
|
||
|
|
|
||
|
|
*** 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](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis).
|
||
|
|
Cookies are implemented mostly in this directory, but also elsewhere, as
|
||
|
|
described [below](#Cookie-implementation-classes).
|
||
|
|
|
||
|
|
*** promo
|
||
|
|
* Those who wish to work with the implementation of cookies may refer to
|
||
|
|
[Life of a cookie](#Life-of-a-cookie) and
|
||
|
|
[Cookie implementation classes](#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](#Main-interfaces-for-finding_setting_deleting_and-observing-cookies).
|
||
|
|
***
|
||
|
|
|
||
|
|
[TOC]
|
||
|
|
|
||
|
|
## Life of a cookie
|
||
|
|
|
||
|
|
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](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies).
|
||
|
|
Other APIs for accessing cookies include JavaScript
|
||
|
|
([`document.cookie`](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie)
|
||
|
|
and [CookieStore API](https://wicg.github.io/cookie-store/)) or Chrome
|
||
|
|
extensions
|
||
|
|
([`chrome.cookies`](https://developer.chrome.com/extensions/cookies)).
|
||
|
|
|
||
|
|
### Cookie is received and parsed
|
||
|
|
|
||
|
|
*** note
|
||
|
|
**Summary:**
|
||
|
|
|
||
|
|
1. An HTTP response containing a `Set-Cookie` header is received.
|
||
|
|
2. The `Set-Cookie` header is processed by `URLRequestHttpJob`.
|
||
|
|
3. The header contents are parsed into a `CanonicalCookie` and passed to the
|
||
|
|
`CookieStore` 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`](/net/docs/life-of-a-url-request.md#send-request-and-read-the-response-headers)
|
||
|
|
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.
|
||
|
|
|
||
|
|
### Cookie is stored
|
||
|
|
|
||
|
|
*** note
|
||
|
|
**Summary:**
|
||
|
|
|
||
|
|
1. The `CookieStore` receives the `CanonicalCookie` and validates some
|
||
|
|
additional criteria before updating its in-memory cache of cookies.
|
||
|
|
2. The `CookieStore` may also update its on-disk backing store via the
|
||
|
|
`CookieMonster::PersistentCookieStore` interface.
|
||
|
|
3. 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.
|
||
|
|
|
||
|
|
### Cookie is retrieved and sent
|
||
|
|
|
||
|
|
*** note
|
||
|
|
**Summary:**
|
||
|
|
|
||
|
|
1. A network request reaches the net stack and generates a `URLRequestHttpJob`,
|
||
|
|
which queries the `CookieStore` for cookies to include with the request.
|
||
|
|
2. The `CookieStore` evaluates each of its candidate cookies for whether it can
|
||
|
|
be included in the request, and reports back to the `URLRequestHttpJob` with
|
||
|
|
included and excluded cookies.
|
||
|
|
3. `URLRequestHttpJob` serializes the included cookies into a `Cookie` 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`](/net/docs/life-of-a-url-request.md#check-the-cache_request-an-httpstream)
|
||
|
|
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](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis#section-5.5)
|
||
|
|
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.
|
||
|
|
|
||
|
|
## Cookie implementation classes
|
||
|
|
|
||
|
|
This section lists classes involved in cookie management and access.
|
||
|
|
|
||
|
|
The core classes are highlighted.
|
||
|
|
|
||
|
|
### In this directory (//net/cookies)
|
||
|
|
|
||
|
|
*** note
|
||
|
|
* **[`CanonicalCookie`](/net/cookies/canonical_cookie.h)**
|
||
|
|
|
||
|
|
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 (a `Set-Cookie` header) into an intermediate `ParsedCookie`, whose
|
||
|
|
fields it canonicalizes/validates and then copies into a `CanonicalCookie`.
|
||
|
|
***
|
||
|
|
|
||
|
|
*** note
|
||
|
|
* **[`CookieStore`](/net/cookies/cookie_store.h)**
|
||
|
|
|
||
|
|
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
|
||
|
|
* **[`CookieMonster`](/net/cookies/cookie_monster.h)**
|
||
|
|
|
||
|
|
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.
|
||
|
|
***
|
||
|
|
|
||
|
|
* [`CookieOptions`](/net/cookies/cookie_options.h)
|
||
|
|
|
||
|
|
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 the `SameSite` cookie attribute).
|
||
|
|
|
||
|
|
* [`SiteForCookies`](/net/cookies/site_for_cookies.h)
|
||
|
|
|
||
|
|
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 a `CookieOptions`).
|
||
|
|
|
||
|
|
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).
|
||
|
|
|
||
|
|
* [`CookieInclusionStatus`](/net/cookies/cookie_inclusion_status.h)
|
||
|
|
|
||
|
|
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.
|
||
|
|
|
||
|
|
* [`CookieAccessDelegate`](/net/cookies/cookie_access_delegate.h)
|
||
|
|
|
||
|
|
Interface for a `CookieStore` to query information from its embedder that
|
||
|
|
may modify its decisions on cookie inclusion/exclusion. Its main
|
||
|
|
implementation allows `CookieMonster` to access data from the network
|
||
|
|
service layer (e.g. `CookieManager`).
|
||
|
|
|
||
|
|
* [`CookieChangeDispatcher`](/net/cookies/cookie_monster_change_dispatcher.h)
|
||
|
|
|
||
|
|
Interface for subscribing to changes in the contents of the `CookieStore`.
|
||
|
|
The main implementation is `CookieMonsterChangeDispatcher`.
|
||
|
|
|
||
|
|
### Elsewhere in //net
|
||
|
|
|
||
|
|
*** note
|
||
|
|
* **[`SQLitePersistentCookieStore`](/net/extras/sqlite/sqlite_persistent_cookie_store.h)**
|
||
|
|
|
||
|
|
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
|
||
|
|
* **[`URLRequestHttpJob`](/net/url_request/url_request_http_job.h)**
|
||
|
|
|
||
|
|
A `URLRequestJob` implementation that handles HTTP requests; most
|
||
|
|
relevantly, the `Cookie` and `Set-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.
|
||
|
|
***
|
||
|
|
|
||
|
|
* [`URLRequest`](/net/url_request/url_request.h)
|
||
|
|
|
||
|
|
Mostly relevant for its two members, `maybe_sent_cookies_` and
|
||
|
|
`maybe_stored_cookies_`, which are vectors in which `URLRequestHttpJob`
|
||
|
|
stashes the cookies it considered sending/storing and their
|
||
|
|
`CookieInclusionStatus`es. These then get mojo'ed over to the browser
|
||
|
|
process to notify observers of cookie activity.
|
||
|
|
|
||
|
|
### In //services/network
|
||
|
|
|
||
|
|
*** note
|
||
|
|
* **[`CookieManager`](/services/network/cookie_manager.h)**
|
||
|
|
|
||
|
|
The network service API to cookies. Basically exports a `CookieStore` via
|
||
|
|
mojo IPC.
|
||
|
|
|
||
|
|
Owned by the `NetworkContext`.
|
||
|
|
***
|
||
|
|
|
||
|
|
*** note
|
||
|
|
* **[`RestrictedCookieManager`](/services/network/restricted_cookie_manager.h)**
|
||
|
|
|
||
|
|
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`](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie),
|
||
|
|
as well as an asynchronous one for the [CookieStore API](https://wicg.github.io/cookie-store/).
|
||
|
|
***
|
||
|
|
|
||
|
|
* [`CookieSettings`](/services/network/cookie_settings.h)
|
||
|
|
|
||
|
|
Keeps track of the content settings (per-profile
|
||
|
|
[permissions](/components/permissions/README.md) 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 which
|
||
|
|
`network::ContentSettings` is approximately a copy/mirror. The
|
||
|
|
`ProfileNetworkContextService` populates its contents upon `NetworkContext`
|
||
|
|
construction from the browser-side content settings, and also updates it
|
||
|
|
whenever the browser-side content settings change.
|
||
|
|
|
||
|
|
* [`SessionCleanupCookieStore`](/services/network/session_cleanup_cookie_store.h)
|
||
|
|
|
||
|
|
Implements `CookieMonster::PersistentCookieStore`, by wrapping a
|
||
|
|
`SQLitePersistentCookieStore`. 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.
|
||
|
|
|
||
|
|
|
||
|
|
### Elsewhere
|
||
|
|
|
||
|
|
* [`CookieAccessObserver`](/services/network/public/mojom/cookie_access_observer.mojom)
|
||
|
|
and [`WebContentsObserver`](/content/public/browser/web_contents_observer.h)
|
||
|
|
|
||
|
|
`CookieAccessObserver` is a mojo interface used to observe attempts to
|
||
|
|
access (read or write) cookies. It is implemented by `NavigationHandle` and
|
||
|
|
`RenderFrameHost`.
|
||
|
|
|
||
|
|
The cookie accesses are attributable to a committed document that called
|
||
|
|
`document.cookie` or made a network request (if notified through
|
||
|
|
`RenderFrameHost`), or a not-yet-committed navigation that resulted in a
|
||
|
|
network request (if notified through `NavigationHandle`).
|
||
|
|
|
||
|
|
The `CookieAccessObserver`s forward the notifications to `WebContents`,
|
||
|
|
which then notifies its `WebContentsObserver`s. One such
|
||
|
|
`WebContentsObserver` that cares about this information is
|
||
|
|
`PageSpecificContentSettings`, which displays information about allowed and
|
||
|
|
blocked cookies in UI surfaces (see next item).
|
||
|
|
|
||
|
|
* [`CookiesTreeModel`](/chrome/browser/browsing_data/cookies_tree_model.h)
|
||
|
|
|
||
|
|
Stores cookie information for use in settings UI (the Page Info Bubble and
|
||
|
|
various `chrome://settings` pages). Populated with info from
|
||
|
|
`PageSpecificContentSettings`.
|
||
|
|
|
||
|
|
* [`CookieJar`](/third_party/blink/renderer/core/loader/cookie_jar.h)
|
||
|
|
|
||
|
|
Implements the `document.cookie` API in the renderer by requesting a
|
||
|
|
`RestrictedCookieManager` from the browser.
|
||
|
|
|
||
|
|
* [`CookieStore`](/third_party/blink/renderer/modules/cookie_store/cookie_store.h)
|
||
|
|
|
||
|
|
Implements the JavaScript
|
||
|
|
[CookieStore API](https://wicg.github.io/cookie-store/) in the renderer by
|
||
|
|
requesting a `RestrictedCookieManager` from the browser. (Not to be confused
|
||
|
|
with `net::CookieStore`.)
|
||
|
|
|
||
|
|
* [`CookiesAPI`](/chrome/browser/extensions/api/cookies/cookies_api.h)
|
||
|
|
|
||
|
|
Implements the
|
||
|
|
[`chrome.cookies`](https://developer.chrome.com/extensions/cookies) API for
|
||
|
|
Chrome extensions. Gives extensions with the proper permissions essentially
|
||
|
|
unfettered access to the `CookieStore`.
|
||
|
|
|
||
|
|
### Platform-specific
|
||
|
|
|
||
|
|
* [`CookieStoreIOS` and `CookieStoreIOSPersistent`](/ios/net/cookies)
|
||
|
|
|
||
|
|
iOS-specific `CookieStore` implementations, mainly relying on the iOS native
|
||
|
|
cookie implementation (`NSHTTPCookie`).
|
||
|
|
|
||
|
|
* [`android_webview::CookieManager`](/android_webview/browser/cookie_manager.h)
|
||
|
|
|
||
|
|
Manages cookies for Android WebView. It typically wraps a
|
||
|
|
`network::mojom::CookieManager`, but it can also be used before a
|
||
|
|
`NetworkContext` even exists, thanks to Android WebView's
|
||
|
|
[cookie API](https://developer.android.com/reference/kotlin/android/webkit/CookieManager),
|
||
|
|
which means it is sometimes initialized with a bare `net::CookieStore`.
|
||
|
|
|
||
|
|
Also notable for allowing cookies for `file://` scheme URLs (normally they
|
||
|
|
are only allowed for HTTP and websocket schemes and `chrome-extension://`),
|
||
|
|
though this is non-default and deprecated.
|
||
|
|
|
||
|
|
## Main interfaces for finding, setting, deleting, and observing cookies
|
||
|
|
|
||
|
|
This section summarizes interfaces for interacting with cookies from various
|
||
|
|
parts of the codebase.
|
||
|
|
|
||
|
|
### From //net or //services/network
|
||
|
|
|
||
|
|
*** note
|
||
|
|
Use [`net::CookieStore`](/net/cookies/cookie_store.h) to save and retrieve
|
||
|
|
[`CanonicalCookie`](/net/cookies/canonical_cookie.h)s.
|
||
|
|
***
|
||
|
|
|
||
|
|
* `CanonicalCookie`s are the main data type representing cookies. Get one using
|
||
|
|
`CanonicalCookie::Create()`.
|
||
|
|
|
||
|
|
* The `CookieStore` can be accessed via its owning `URLRequestContext`, which
|
||
|
|
can be accessed through `NetworkContext`.
|
||
|
|
|
||
|
|
* To access cookies, you need a `CookieOptions`. The main things in this object
|
||
|
|
are the `HttpOnly` access permission and the `SameSite` context. The latter
|
||
|
|
can be obtained from [`cookie_util`](/net/cookies/cookie_util.h) 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`](/net/cookies/cookie_change_dispatcher.h)
|
||
|
|
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 the
|
||
|
|
`CookieStore`.
|
||
|
|
|
||
|
|
### From the browser process
|
||
|
|
|
||
|
|
*** note
|
||
|
|
Use [`CookieManager`](/services/network/cookie_manager.h)
|
||
|
|
(which basically exports a `net::CookieStore` interface via mojo) to save
|
||
|
|
and retrieve [`CanonicalCookie`](/net/cookies/canonical_cookie.h)s.
|
||
|
|
***
|
||
|
|
|
||
|
|
* The profile's `CookieManager` can be accessed from the browser process through
|
||
|
|
`StoragePartition::GetCookieManagerForBrowserProcess()`.
|
||
|
|
|
||
|
|
* You can also get get a `CookieManager` pipe from the `NetworkContext` using
|
||
|
|
`GetCookieManager()`.
|
||
|
|
|
||
|
|
* 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), use
|
||
|
|
`CookieManager::DeleteCanonicalCookie()`.
|
||
|
|
|
||
|
|
* To delete cookies with certain characteristics, construct a
|
||
|
|
[`CookieDeletionFilter`](/services/network/public/mojom/cookie_manager.mojom)
|
||
|
|
and use `CookieManager::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) via `AddCookieChangeListener()`
|
||
|
|
|
||
|
|
* Add a `CookieChangeListener` registration for all cookies via
|
||
|
|
`AddGlobalChangeListener()`.
|
||
|
|
|
||
|
|
### From untrusted (e.g. renderer) processes
|
||
|
|
|
||
|
|
*** note
|
||
|
|
Use a
|
||
|
|
[`network::mojom::RestrictedCookieManager`](/services/network/public/mojom/restricted_cookie_manager.mojom)
|
||
|
|
interface to access cookies for a particular origin.
|
||
|
|
***
|
||
|
|
|
||
|
|
* Request a `RestrictedCookieManager` interface from the browser. This creates a
|
||
|
|
`RestrictedCookieManager` bound to a `RenderFrameHost`, 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](/docs/security/compromised-renderers.md#Cookies)
|
||
|
|
shouldn't be able to access cookies of another site, or `HttpOnly` cookies
|
||
|
|
(even from the same site).
|