15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Portions of this code based on Mozilla:
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   (netwerk/cookie/src/nsCookieService.cpp)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* ***** BEGIN LICENSE BLOCK *****
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Version: MPL 1.1/GPL 2.0/LGPL 2.1
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The contents of this file are subject to the Mozilla Public License Version
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1.1 (the "License"); you may not use this file except in compliance with
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the License. You may obtain a copy of the License at
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * http://www.mozilla.org/MPL/
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Software distributed under the License is distributed on an "AS IS" basis,
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * for the specific language governing rights and limitations under the
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * License.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The Original Code is mozilla.org code.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The Initial Developer of the Original Code is
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Netscape Communications Corporation.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Portions created by the Initial Developer are Copyright (C) 2003
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the Initial Developer. All Rights Reserved.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Contributor(s):
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   Daniel Witte (dwitte@stanford.edu)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   Michiel van Leeuwen (mvl@exedo.nl)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Alternatively, the contents of this file may be used under the terms of
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * either the GNU General Public License Version 2 or later (the "GPL"), or
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in which case the provisions of the GPL or the LGPL are applicable instead
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of those above. If you wish to allow use of your version of this file only
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * under the terms of either the GPL or the LGPL, and not to allow others to
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * use your version of this file under the terms of the MPL, indicate your
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * decision by deleting the provisions above and replace them with the notice
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and other provisions required by the GPL or the LGPL. If you do not delete
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the provisions above, a recipient may use your version of this file under
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the terms of any one of the MPL, the GPL or the LGPL.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ***** END LICENSE BLOCK ***** */
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/cookies/canonical_cookie.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
505e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/cookies/cookie_util.h"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/cookies/parsed_cookie.h"
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/url_canon.h"
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kVlogSetCookies = 7;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Determine the cookie domain to use for setting the specified cookie.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetCookieDomain(const GURL& url,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const ParsedCookie& pc,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     std::string* result) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string domain_string;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pc.HasDomain())
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    domain_string = pc.Domain();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return cookie_util::GetCookieDomainWithString(url, domain_string, result);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string CanonPathWithString(const GURL& url,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const std::string& path_string) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The RFC says the path should be a prefix of the current URL path.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // However, Mozilla allows you to set any path for compatibility with
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // broken websites.  We unfortunately will mimic this behavior.  We try
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to be generous and accept cookies with an invalid path attribute, and
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // default the path to something reasonable.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The path was supplied in the cookie, we'll take it.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!path_string.empty() && path_string[0] == '/')
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return path_string;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The path was not supplied in the cookie or invalid, we will default
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to the current URL path.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // """Defaults to the path of the request URL that generated the
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    Set-Cookie response, up to, but not including, the
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    right-most /."""
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // How would this work for a cookie on /?  We will include it then.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& url_path = url.path();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t idx = url_path.find_last_of('/');
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The cookie path was invalid or a single '/'.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (idx == 0 || idx == std::string::npos)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string("/");
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return up to the rightmost '/'.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url_path.substr(0, idx);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CanonicalCookie::CanonicalCookie()
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : secure_(false),
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      httponly_(false) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CanonicalCookie::CanonicalCookie(
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url, const std::string& name, const std::string& value,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& domain, const std::string& path,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Time& creation, const base::Time& expiration,
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Time& last_access, bool secure, bool httponly,
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CookiePriority priority)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : source_(GetCookieSourceFromURL(url)),
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name_(name),
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value_(value),
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      domain_(domain),
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      path_(path),
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      creation_date_(creation),
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      expiry_date_(expiration),
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_access_date_(last_access),
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      secure_(secure),
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      httponly_(httponly),
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      priority_(priority) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CanonicalCookie::CanonicalCookie(const GURL& url, const ParsedCookie& pc)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : source_(GetCookieSourceFromURL(url)),
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name_(pc.Name()),
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value_(pc.Value()),
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      path_(CanonPath(url, pc)),
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      creation_date_(Time::Now()),
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_access_date_(Time()),
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      secure_(pc.IsSecure()),
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      httponly_(pc.IsHttpOnly()),
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      priority_(pc.Priority()) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pc.HasExpires())
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    expiry_date_ = CanonExpiration(pc, creation_date_, creation_date_);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do the best we can with the domain.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cookie_domain;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string domain_string;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pc.HasDomain()) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    domain_string = pc.Domain();
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      = cookie_util::GetCookieDomainWithString(url, domain_string,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                &cookie_domain);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Caller is responsible for passing in good arguments.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(result);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  domain_ = cookie_domain;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CanonicalCookie::~CanonicalCookie() {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string CanonicalCookie::GetCookieSourceFromURL(const GURL& url) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url.SchemeIsFile())
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return url.spec();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::Replacements<char> replacements;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  replacements.ClearPort();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url.SchemeIsSecure())
1685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    replacements.SetScheme("http", url::Component(0, 4));
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url.GetOrigin().ReplaceComponents(replacements).spec();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string CanonicalCookie::CanonPath(const GURL& url,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const ParsedCookie& pc) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string path_string;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pc.HasPath())
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path_string = pc.Path();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CanonPathWithString(url, path_string);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Time CanonicalCookie::CanonExpiration(const ParsedCookie& pc,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const Time& current,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const Time& server_time) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First, try the Max-Age attribute.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64 max_age = 0;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pc.HasMaxAge() &&
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef COMPILER_MSVC
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sscanf_s(
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sscanf(
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             pc.MaxAge().c_str(), " %" PRIu64, &max_age) == 1) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return current + TimeDelta::FromSeconds(max_age);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try the Expires attribute.
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (pc.HasExpires() && !pc.Expires().empty()) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Adjust for clock skew between server and host.
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Time parsed_expiry = cookie_util::ParseCookieTime(pc.Expires());
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!parsed_expiry.is_null())
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return parsed_expiry + (current - server_time);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invalid or no expiration, persistent cookie.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Time();
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CanonicalCookie* CanonicalCookie::Create(const GURL& url,
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         const std::string& cookie_line,
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         const base::Time& creation_time,
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         const CookieOptions& options) {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ParsedCookie parsed_cookie(cookie_line);
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!parsed_cookie.IsValid()) {
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(kVlogSetCookies) << "WARNING: Couldn't parse cookie";
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (options.exclude_httponly() && parsed_cookie.IsHttpOnly()) {
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(kVlogSetCookies) << "Create() is not creating a httponly cookie";
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string cookie_domain;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!GetCookieDomain(url, parsed_cookie, &cookie_domain)) {
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string cookie_path = CanonicalCookie::CanonPath(url, parsed_cookie);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Time server_time(creation_time);
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (options.has_server_time())
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    server_time = options.server_time();
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Time cookie_expires = CanonicalCookie::CanonExpiration(parsed_cookie,
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                         creation_time,
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                         server_time);
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new CanonicalCookie(url, parsed_cookie.Name(), parsed_cookie.Value(),
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             cookie_domain, cookie_path, creation_time,
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             cookie_expires, creation_time,
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             parsed_cookie.IsSecure(),
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             parsed_cookie.IsHttpOnly(),
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             parsed_cookie.Priority());
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CanonicalCookie* CanonicalCookie::Create(const GURL& url,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const std::string& name,
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const std::string& value,
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const std::string& domain,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const std::string& path,
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const base::Time& creation,
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const base::Time& expiration,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         bool secure,
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         bool http_only,
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         CookiePriority priority) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Expect valid attribute tokens and values, as defined by the ParsedCookie
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // logic, otherwise don't create the cookie.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string parsed_name = ParsedCookie::ParseTokenString(name);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parsed_name != name)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string parsed_value = ParsedCookie::ParseValueString(value);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parsed_value != value)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string parsed_domain = ParsedCookie::ParseValueString(domain);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parsed_domain != domain)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cookie_domain;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cookie_util::GetCookieDomainWithString(url, parsed_domain,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               &cookie_domain)) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string parsed_path = ParsedCookie::ParseValueString(path);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parsed_path != path)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cookie_path = CanonPathWithString(url, parsed_path);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Expect that the path was either not specified (empty), or is valid.
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!parsed_path.empty() && cookie_path != parsed_path)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Canonicalize path again to make sure it escapes characters as needed.
2865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::Component path_component(0, cookie_path.length());
2875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::RawCanonOutputT<char> canon_path;
2885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::Component canon_path_component;
2895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::CanonicalizePath(cookie_path.data(), path_component, &canon_path,
2905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                        &canon_path_component);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cookie_path = std::string(canon_path.data() + canon_path_component.begin,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            canon_path_component.len);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new CanonicalCookie(url, parsed_name, parsed_value, cookie_domain,
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             cookie_path, creation, expiration, creation,
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             secure, http_only, priority);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CanonicalCookie::IsOnPath(const std::string& url_path) const {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A zero length would be unsafe for our trailing '/' checks, and
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // would also make no sense for our prefix match.  The code that
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // creates a CanonicalCookie should make sure the path is never zero length,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // but we double check anyway.
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (path_.empty())
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The Mozilla code broke this into three cases, based on if the cookie path
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // was longer, the same length, or shorter than the length of the url path.
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // I think the approach below is simpler.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure the cookie path is a prefix of the url path.  If the
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // url path is shorter than the cookie path, then the cookie path
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can't be a prefix.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url_path.find(path_) != 0)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now we know that url_path is >= cookie_path, and that cookie_path
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is a prefix of url_path.  If they are the are the same length then
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // they are identical, otherwise we need an additional check:
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In order to avoid in correctly matching a cookie path of /blah
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with a request path of '/blahblah/', we need to make sure that either
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the cookie path ends in a trailing '/', or that we prefix up to a '/'
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the url path.  Since we know that the url path length is greater
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // than the cookie path length, it's safe to index one byte past.
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (path_.length() != url_path.length() &&
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      path_[path_.length() - 1] != '/' &&
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url_path[path_.length()] != '/')
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CanonicalCookie::IsDomainMatch(const std::string& host) const {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Can domain match in two ways; as a domain cookie (where the cookie
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // domain begins with ".") or as a host cookie (where it doesn't).
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some consumers of the CookieMonster expect to set cookies on
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // URLs like http://.strange.url.  To retrieve cookies in this instance,
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we allow matching as a host cookie even when the domain_ starts with
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a period.
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host == domain_)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Domain cookie must have an initial ".".  To match, it must be
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // equal to url's host with initial period removed, or a suffix of
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it.
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Arguably this should only apply to "http" or "https" cookies, but
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension cookie tests currently use the funtionality, and if we
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ever decide to implement that it should be done by preventing
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // such cookies from being set.
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (domain_.empty() || domain_[0] != '.')
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The host with a "." prefixed.
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (domain_.compare(1, std::string::npos, host) == 0)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A pure suffix of the host (ok since we know the domain already
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // starts with a ".")
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (host.length() > domain_.length() &&
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          host.compare(host.length() - domain_.length(),
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       domain_.length(), domain_) == 0);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CanonicalCookie::IncludeForRequestURL(const GURL& url,
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           const CookieOptions& options) const {
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Filter out HttpOnly cookies, per options.
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (options.exclude_httponly() && IsHttpOnly())
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Secure cookies should not be included in requests for URLs with an
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // insecure scheme.
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (IsSecure() && !url.SchemeIsSecure())
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't include cookies for requests that don't apply to the cookie domain.
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!IsDomainMatch(url.host()))
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't include cookies for requests with a url path that does not path
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // match the cookie-path.
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!IsOnPath(url.path()))
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string CanonicalCookie::DebugString() const {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::StringPrintf(
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "name: %s value: %s domain: %s path: %s creation: %"
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PRId64,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name_.c_str(), value_.c_str(),
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      domain_.c_str(), path_.c_str(),
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<int64>(creation_date_.ToTimeT()));
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)CanonicalCookie* CanonicalCookie::Duplicate() {
398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CanonicalCookie* cc = new CanonicalCookie();
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cc->source_ = source_;
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cc->name_ = name_;
401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cc->value_ = value_;
402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cc->domain_ = domain_;
403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cc->path_ = path_;
404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cc->creation_date_ = creation_date_;
405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cc->expiry_date_ = expiry_date_;
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cc->last_access_date_ = last_access_date_;
407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cc->secure_ = secure_;
408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cc->httponly_ = httponly_;
409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cc->priority_ = priority_;
410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return cc;
411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
414