author | Tim Taubert <ttaubert@mozilla.com> |
Thu, 15 Jan 2015 11:22:21 +0100 | |
changeset 224322 | 17b3a6d3ee1a126de2becd6bdc99798ef4898aa5 |
parent 224321 | f5053a5e716adcc612bf415cc23121f96381dc4f |
child 224323 | def4cd55d1f99ff281d5e4fdc732b49df6cf6df5 |
push id | 54190 |
push user | kwierso@gmail.com |
push date | Sat, 17 Jan 2015 02:06:29 +0000 |
treeherder | mozilla-inbound@369a8f14ccf8 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | yoric |
bugs | 950399 |
milestone | 38.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/components/sessionstore/SessionCookies.jsm +++ b/browser/components/sessionstore/SessionCookies.jsm @@ -256,16 +256,50 @@ let SessionCookiesInternal = { let iter = Services.cookies.enumerator; while (iter.hasMoreElements()) { this._updateCookie(iter.getNext()); } } }; /** + * Generates all possible subdomains for a given host and prepends a leading + * dot to all variants. + * + * See http://tools.ietf.org/html/rfc6265#section-5.1.3 + * http://en.wikipedia.org/wiki/HTTP_cookie#Domain_and_Path + * + * All cookies belonging to a web page will be internally represented by a + * nsICookie object. nsICookie.host will be the request host if no domain + * parameter was given when setting the cookie. If a specific domain was given + * then nsICookie.host will contain that specific domain and prepend a leading + * dot to it. + * + * We thus generate all possible subdomains for a given domain and prepend a + * leading dot to them as that is the value that was used as the map key when + * the cookie was set. + */ +function* getPossibleSubdomainVariants(host) { + // Try given domain with a leading dot (.www.example.com). + yield "." + host; + + // Stop if there are only two parts left (e.g. example.com was given). + let parts = host.split("."); + if (parts.length < 3) { + return; + } + + // Remove the first subdomain (www.example.com -> example.com). + let rest = parts.slice(1).join("."); + + // Try possible parent subdomains. + yield* getPossibleSubdomainVariants(rest); +} + +/** * The internal cookie storage that keeps track of every active session cookie. * These are stored using maps per host, path, and cookie name. */ let CookieStore = { /** * The internal structure holding all known cookies. * * Host => @@ -280,36 +314,54 @@ let CookieStore = { * "username": {name: "username", value: "my_name_is", etc...}, * "sessionid": {name: "sessionid", value: "1fdb3a", etc...} * } * }, * "tbpl.mozilla.org": { * "/path": { * "cookiename": {name: "cookiename", value: "value", etc...} * } + * }, + * ".example.com": { + * "/path": { + * "cookiename": {name: "cookiename", value: "value", etc...} + * } * } * }; */ _hosts: new Map(), /** * Returns the list of stored session cookies for a given host. * * @param host * A string containing the host name we want to get cookies for. */ getCookiesForHost: function (host) { - if (!this._hosts.has(host)) { - return []; + let cookies = []; + + let appendCookiesForHost = host => { + if (!this._hosts.has(host)) { + return; + } + + for (let pathToNamesMap of this._hosts.get(host).values()) { + cookies.push(...pathToNamesMap.values()); + } } - let cookies = []; - - for (let pathToNamesMap of this._hosts.get(host).values()) { - cookies.push(...pathToNamesMap.values()); + // Try to find cookies for the given host, e.g. <www.example.com>. + // The full hostname will be in the map if the Set-Cookie header did not + // have a domain= attribute, i.e. the cookie will only be stored for the + // request domain. Also, try to find cookies for subdomains, e.g. + // <.example.com>. We will find those variants with a leading dot in the + // map if the Set-Cookie header had a domain= attribute, i.e. the cookie + // will be stored for a parent domain and we send it for any subdomain. + for (let variant of [host, ...getPossibleSubdomainVariants(host)]) { + appendCookiesForHost(variant); } return cookies; }, /** * Stores a given cookie. *