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)#include "net/cookies/cookie_util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstdio>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstdlib>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_tokenizer.h"
125e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace cookie_util {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DomainIsHostOnly(const std::string& domain_string) {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (domain_string.empty() || domain_string[0] != '.');
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetEffectiveDomain(const std::string& scheme,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const std::string& host) {
27a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (scheme == "http" || scheme == "https") {
28a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return registry_controlled_domains::GetDomainAndRegistry(
29a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        host, net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
30a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!DomainIsHostOnly(host))
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return host.substr(1);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return host;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetCookieDomainWithString(const GURL& url,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const std::string& domain_string,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               std::string* result) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string url_host(url.host());
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If no domain was specified in the domain string, default to a host cookie.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We match IE/Firefox in allowing a domain=IPADDR if it matches the url
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ip address hostname exactly.  It should be treated as a host cookie.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (domain_string.empty() ||
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (url.HostIsIPAddress() && url_host == domain_string)) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *result = url_host;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(DomainIsHostOnly(*result));
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the normalized domain specified in cookie line.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_canon::CanonHostInfo ignored;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cookie_domain(CanonicalizeHost(domain_string, &ignored));
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cookie_domain.empty())
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cookie_domain[0] != '.')
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cookie_domain = "." + cookie_domain;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure |url| and |cookie_domain| have the same domain+registry.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string url_scheme(url.scheme());
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string url_domain_and_registry(
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetEffectiveDomain(url_scheme, url_host));
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url_domain_and_registry.empty())
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;  // IP addresses/intranet hosts can't set domain cookies.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string cookie_domain_and_registry(
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetEffectiveDomain(url_scheme, cookie_domain));
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url_domain_and_registry != cookie_domain_and_registry)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;  // Can't set a cookie on a different domain + registry.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure |url_host| is |cookie_domain| or one of its subdomains.  Given that
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we know the domain+registry are the same from the above checks, this is
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // basically a simple string suffix check.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool is_suffix = (url_host.length() < cookie_domain.length()) ?
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (cookie_domain != ("." + url_host)) :
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (url_host.compare(url_host.length() - cookie_domain.length(),
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        cookie_domain.length(), cookie_domain) != 0);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_suffix)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *result = cookie_domain;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parse a cookie expiration time.  We try to be lenient, but we need to
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// assume some order to distinguish the fields.  The basic rules:
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - The month name must be present and prefix the first 3 letters of the
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    full month name (jan for January, jun for June).
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - If the year is <= 2 digits, it must occur after the day of month.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - The time must be of the format hh:mm:ss.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An average cookie expiration will look something like this:
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Sat, 15-Apr-17 21:01:22 GMT
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::Time ParseCookieTime(const std::string& time_string) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* kMonths[] = { "jan", "feb", "mar", "apr", "may", "jun",
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   "jul", "aug", "sep", "oct", "nov", "dec" };
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kMonthsLen = arraysize(kMonths);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We want to be pretty liberal, and support most non-ascii and non-digit
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // characters as a delimiter.  We can't treat : as a delimiter, because it
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is the delimiter for hh:mm:ss, and we want to keep this field together.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We make sure to include - and +, since they could prefix numbers.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the cookie attribute came in in quotes (ex expires="XXX"), the quotes
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will be preserved, and we will get them here.  So we make sure to include
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // quote characters, and also \ for anything that was internally escaped.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* kDelimiters = "\t !\"#$%&'()*+,-./;<=>?@[\\]^_`{|}~";
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time::Exploded exploded = {0};
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::StringTokenizer tokenizer(time_string, kDelimiters);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool found_day_of_month = false;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool found_month = false;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool found_time = false;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool found_year = false;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (tokenizer.GetNext()) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string token = tokenizer.token();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!token.empty());
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool numerical = IsAsciiDigit(token[0]);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // String field
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!numerical) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!found_month) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (int i = 0; i < kMonthsLen; ++i) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Match prefix, so we could match January, etc
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (base::strncasecmp(token.c_str(), kMonths[i], 3) == 0) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            exploded.month = i + 1;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            found_month = true;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If we've gotten here, it means we've already found and parsed our
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // month, and we have another string, which we would expect to be the
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the time zone name.  According to the RFC and my experiments with
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // how sites format their expirations, we don't have much of a reason
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // to support timezones.  We don't want to ever barf on user input,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // but this DCHECK should pass for well-formed data.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // DCHECK(token == "GMT");
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Numeric field w/ a colon
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (token.find(':') != std::string::npos) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!found_time &&
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef COMPILER_MSVC
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          sscanf_s(
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          sscanf(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 token.c_str(), "%2u:%2u:%2u", &exploded.hour,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 &exploded.minute, &exploded.second) == 3) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found_time = true;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We should only ever encounter one time-like thing.  If we're here,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // it means we've found a second, which shouldn't happen.  We keep
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the first.  This check should be ok for well-formed input:
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // NOTREACHED();
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Numeric field
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Overflow with atoi() is unspecified, so we enforce a max length.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!found_day_of_month && token.length() <= 2) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        exploded.day_of_month = atoi(token.c_str());
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found_day_of_month = true;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (!found_year && token.length() <= 5) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        exploded.year = atoi(token.c_str());
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found_year = true;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If we're here, it means we've either found an extra numeric field,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // or a numeric field which was too long.  For well-formed input, the
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // following check would be reasonable:
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // NOTREACHED();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!found_day_of_month || !found_month || !found_time || !found_year) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We didn't find all of the fields we need.  For well-formed input, the
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // following check would be reasonable:
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // NOTREACHED() << "Cookie parse expiration failed: " << time_string;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::Time();
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Normalize the year to expand abbreviated years to the full year.
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (exploded.year >= 69 && exploded.year <= 99)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exploded.year += 1900;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (exploded.year >= 0 && exploded.year <= 68)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exploded.year += 2000;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If our values are within their correct ranges, we got our time.
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (exploded.day_of_month >= 1 && exploded.day_of_month <= 31 &&
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      exploded.month >= 1 && exploded.month <= 12 &&
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      exploded.year >= 1601 && exploded.year <= 30827 &&
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      exploded.hour <= 23 && exploded.minute <= 59 && exploded.second <= 59) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::Time::FromUTCExploded(exploded);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // One of our values was out of expected range.  For well-formed input,
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the following check would be reasonable:
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTREACHED() << "Cookie exploded expiration failed: " << time_string;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::Time();
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL CookieOriginToURL(const std::string& domain, bool is_https) {
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (domain.empty())
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return GURL();
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string scheme = is_https ? "https" : "http";
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string host = domain[0] == '.' ? domain.substr(1) : domain;
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return GURL(scheme + "://" + host);
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace cookie_utils
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215