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