| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Portions of this code based on Mozilla: | 5 // Portions of this code based on Mozilla: |
| 6 // (netwerk/cookie/src/nsCookieService.cpp) | 6 // (netwerk/cookie/src/nsCookieService.cpp) |
| 7 /* ***** BEGIN LICENSE BLOCK ***** | 7 /* ***** BEGIN LICENSE BLOCK ***** |
| 8 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 8 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 9 * | 9 * |
| 10 * The contents of this file are subject to the Mozilla Public License Version | 10 * The contents of this file are subject to the Mozilla Public License Version |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 #include "base/logging.h" | 54 #include "base/logging.h" |
| 55 #include "base/memory/scoped_ptr.h" | 55 #include "base/memory/scoped_ptr.h" |
| 56 #include "base/message_loop.h" | 56 #include "base/message_loop.h" |
| 57 #include "base/message_loop_proxy.h" | 57 #include "base/message_loop_proxy.h" |
| 58 #include "base/metrics/histogram.h" | 58 #include "base/metrics/histogram.h" |
| 59 #include "base/string_tokenizer.h" | 59 #include "base/string_tokenizer.h" |
| 60 #include "base/string_util.h" | 60 #include "base/string_util.h" |
| 61 #include "base/stringprintf.h" | 61 #include "base/stringprintf.h" |
| 62 #include "googleurl/src/gurl.h" | 62 #include "googleurl/src/gurl.h" |
| 63 #include "googleurl/src/url_canon.h" | 63 #include "googleurl/src/url_canon.h" |
| 64 #include "net/base/net_util.h" | 64 #include "net/base/cookie_utils.h" |
| 65 #include "net/base/registry_controlled_domain.h" | 65 #include "net/base/registry_controlled_domain.h" |
| 66 | 66 |
| 67 using base::Time; | 67 using base::Time; |
| 68 using base::TimeDelta; | 68 using base::TimeDelta; |
| 69 using base::TimeTicks; | 69 using base::TimeTicks; |
| 70 | 70 |
| 71 // In steady state, most cookie requests can be satisfied by the in memory | 71 // In steady state, most cookie requests can be satisfied by the in memory |
| 72 // cookie monster store. However, if a request comes in during the initial | 72 // cookie monster store. However, if a request comes in during the initial |
| 73 // cookie load, it must be delayed until that load completes. That is done by | 73 // cookie load, it must be delayed until that load completes. That is done by |
| 74 // queueing it on CookieMonster::queue_ and running it when notification of | 74 // queueing it on CookieMonster::queue_ and running it when notification of |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 return diff < 0; | 181 return diff < 0; |
| 182 | 182 |
| 183 return path.compare(cs.path) < 0; | 183 return path.compare(cs.path) < 0; |
| 184 } | 184 } |
| 185 | 185 |
| 186 std::string name; | 186 std::string name; |
| 187 std::string domain; | 187 std::string domain; |
| 188 std::string path; | 188 std::string path; |
| 189 }; | 189 }; |
| 190 | 190 |
| 191 // Returns the effective TLD+1 for a given host. This only makes sense for http | |
| 192 // and https schemes. For other schemes, the host will be returned unchanged | |
| 193 // (minus any leading period). | |
| 194 std::string GetEffectiveDomain(const std::string& scheme, | |
| 195 const std::string& host) { | |
| 196 if (scheme == "http" || scheme == "https") | |
| 197 return RegistryControlledDomainService::GetDomainAndRegistry(host); | |
| 198 | |
| 199 if (!CookieMonster::DomainIsHostOnly(host)) | |
| 200 return host.substr(1); | |
| 201 return host; | |
| 202 } | |
| 203 | |
| 204 // Determine the actual cookie domain based on the domain string passed | |
| 205 // (if any) and the URL from which the cookie came. | |
| 206 // On success returns true, and sets cookie_domain to either a | |
| 207 // -host cookie domain (ex: "google.com") | |
| 208 // -domain cookie domain (ex: ".google.com") | |
| 209 bool GetCookieDomainWithString(const GURL& url, | |
| 210 const std::string& domain_string, | |
| 211 std::string* result) { | |
| 212 const std::string url_host(url.host()); | |
| 213 | |
| 214 // If no domain was specified in the domain string, default to a host cookie. | |
| 215 // We match IE/Firefox in allowing a domain=IPADDR if it matches the url | |
| 216 // ip address hostname exactly. It should be treated as a host cookie. | |
| 217 if (domain_string.empty() || | |
| 218 (url.HostIsIPAddress() && url_host == domain_string)) { | |
| 219 *result = url_host; | |
| 220 DCHECK(CookieMonster::DomainIsHostOnly(*result)); | |
| 221 return true; | |
| 222 } | |
| 223 | |
| 224 // Get the normalized domain specified in cookie line. | |
| 225 url_canon::CanonHostInfo ignored; | |
| 226 std::string cookie_domain(CanonicalizeHost(domain_string, &ignored)); | |
| 227 if (cookie_domain.empty()) | |
| 228 return false; | |
| 229 if (cookie_domain[0] != '.') | |
| 230 cookie_domain = "." + cookie_domain; | |
| 231 | |
| 232 // Ensure |url| and |cookie_domain| have the same domain+registry. | |
| 233 const std::string url_scheme(url.scheme()); | |
| 234 const std::string url_domain_and_registry( | |
| 235 GetEffectiveDomain(url_scheme, url_host)); | |
| 236 if (url_domain_and_registry.empty()) | |
| 237 return false; // IP addresses/intranet hosts can't set domain cookies. | |
| 238 const std::string cookie_domain_and_registry( | |
| 239 GetEffectiveDomain(url_scheme, cookie_domain)); | |
| 240 if (url_domain_and_registry != cookie_domain_and_registry) | |
| 241 return false; // Can't set a cookie on a different domain + registry. | |
| 242 | |
| 243 // Ensure |url_host| is |cookie_domain| or one of its subdomains. Given that | |
| 244 // we know the domain+registry are the same from the above checks, this is | |
| 245 // basically a simple string suffix check. | |
| 246 if ((url_host.length() < cookie_domain.length()) ? | |
| 247 (cookie_domain != ("." + url_host)) : | |
| 248 url_host.compare(url_host.length() - cookie_domain.length(), | |
| 249 cookie_domain.length(), cookie_domain)) | |
| 250 return false; | |
| 251 | |
| 252 *result = cookie_domain; | |
| 253 return true; | |
| 254 } | |
| 255 | |
| 256 // Determine the cookie domain to use for setting the specified cookie. | 191 // Determine the cookie domain to use for setting the specified cookie. |
| 257 bool GetCookieDomain(const GURL& url, | 192 bool GetCookieDomain(const GURL& url, |
| 258 const CookieMonster::ParsedCookie& pc, | 193 const CookieMonster::ParsedCookie& pc, |
| 259 std::string* result) { | 194 std::string* result) { |
| 260 std::string domain_string; | 195 std::string domain_string; |
| 261 if (pc.HasDomain()) | 196 if (pc.HasDomain()) |
| 262 domain_string = pc.Domain(); | 197 domain_string = pc.Domain(); |
| 263 return GetCookieDomainWithString(url, domain_string, result); | 198 return cookie_utils::GetCookieDomainWithString(url, domain_string, result); |
| 264 } | 199 } |
| 265 | 200 |
| 266 std::string CanonPathWithString(const GURL& url, | 201 std::string CanonPathWithString(const GURL& url, |
| 267 const std::string& path_string) { | 202 const std::string& path_string) { |
| 268 // The RFC says the path should be a prefix of the current URL path. | 203 // The RFC says the path should be a prefix of the current URL path. |
| 269 // However, Mozilla allows you to set any path for compatibility with | 204 // However, Mozilla allows you to set any path for compatibility with |
| 270 // broken websites. We unfortunately will mimic this behavior. We try | 205 // broken websites. We unfortunately will mimic this behavior. We try |
| 271 // to be generous and accept cookies with an invalid path attribute, and | 206 // to be generous and accept cookies with an invalid path attribute, and |
| 272 // default the path to something reasonable. | 207 // default the path to something reasonable. |
| 273 | 208 |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 582 return Time::FromUTCExploded(exploded); | 517 return Time::FromUTCExploded(exploded); |
| 583 } | 518 } |
| 584 | 519 |
| 585 // One of our values was out of expected range. For well-formed input, | 520 // One of our values was out of expected range. For well-formed input, |
| 586 // the following check would be reasonable: | 521 // the following check would be reasonable: |
| 587 // NOTREACHED() << "Cookie exploded expiration failed: " << time_string; | 522 // NOTREACHED() << "Cookie exploded expiration failed: " << time_string; |
| 588 | 523 |
| 589 return Time(); | 524 return Time(); |
| 590 } | 525 } |
| 591 | 526 |
| 592 bool CookieMonster::DomainIsHostOnly(const std::string& domain_string) { | |
| 593 return (domain_string.empty() || domain_string[0] != '.'); | |
| 594 } | |
| 595 | |
| 596 // Task classes for queueing the coming request. | 527 // Task classes for queueing the coming request. |
| 597 | 528 |
| 598 class CookieMonster::CookieMonsterTask | 529 class CookieMonster::CookieMonsterTask |
| 599 : public base::RefCountedThreadSafe<CookieMonsterTask> { | 530 : public base::RefCountedThreadSafe<CookieMonsterTask> { |
| 600 public: | 531 public: |
| 601 // Runs the task and invokes the client callback on the thread that | 532 // Runs the task and invokes the client callback on the thread that |
| 602 // originally constructed the task. | 533 // originally constructed the task. |
| 603 virtual void Run() = 0; | 534 virtual void Run() = 0; |
| 604 | 535 |
| 605 protected: | 536 protected: |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1136 void CookieMonster::DoCookieTaskForURL( | 1067 void CookieMonster::DoCookieTaskForURL( |
| 1137 const scoped_refptr<CookieMonsterTask>& task_item, | 1068 const scoped_refptr<CookieMonsterTask>& task_item, |
| 1138 const GURL& url) { | 1069 const GURL& url) { |
| 1139 { | 1070 { |
| 1140 base::AutoLock autolock(lock_); | 1071 base::AutoLock autolock(lock_); |
| 1141 InitIfNecessary(); | 1072 InitIfNecessary(); |
| 1142 // If cookies for the requested domain key (eTLD+1) have been loaded from DB | 1073 // If cookies for the requested domain key (eTLD+1) have been loaded from DB |
| 1143 // then run the task, otherwise load from DB. | 1074 // then run the task, otherwise load from DB. |
| 1144 if (!loaded_) { | 1075 if (!loaded_) { |
| 1145 // Checks if the domain key has been loaded. | 1076 // Checks if the domain key has been loaded. |
| 1146 std::string key(GetEffectiveDomain(url.scheme(), url.host())); | 1077 std::string key(cookie_utils::GetEffectiveDomain(url.scheme(), |
| 1078 url.host())); |
| 1147 if (keys_loaded_.find(key) == keys_loaded_.end()) { | 1079 if (keys_loaded_.find(key) == keys_loaded_.end()) { |
| 1148 std::map<std::string, std::deque<scoped_refptr<CookieMonsterTask> > > | 1080 std::map<std::string, std::deque<scoped_refptr<CookieMonsterTask> > > |
| 1149 ::iterator it = tasks_queued_.find(key); | 1081 ::iterator it = tasks_queued_.find(key); |
| 1150 if (it == tasks_queued_.end()) { | 1082 if (it == tasks_queued_.end()) { |
| 1151 store_->LoadCookiesForKey(key, | 1083 store_->LoadCookiesForKey(key, |
| 1152 base::Bind(&CookieMonster::OnKeyLoaded, this, key)); | 1084 base::Bind(&CookieMonster::OnKeyLoaded, this, key)); |
| 1153 it = tasks_queued_.insert(std::make_pair(key, | 1085 it = tasks_queued_.insert(std::make_pair(key, |
| 1154 std::deque<scoped_refptr<CookieMonsterTask> >())).first; | 1086 std::deque<scoped_refptr<CookieMonsterTask> >())).first; |
| 1155 } | 1087 } |
| 1156 it->second.push_back(task_item); | 1088 it->second.push_back(task_item); |
| (...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1742 } else { | 1674 } else { |
| 1743 // Need to probe for all domains that might have relevant | 1675 // Need to probe for all domains that might have relevant |
| 1744 // cookies for us. | 1676 // cookies for us. |
| 1745 | 1677 |
| 1746 // Query for the full host, For example: 'a.c.blah.com'. | 1678 // Query for the full host, For example: 'a.c.blah.com'. |
| 1747 std::string key(GetKey(url.host())); | 1679 std::string key(GetKey(url.host())); |
| 1748 FindCookiesForKey(key, url, options, current_time, update_access_time, | 1680 FindCookiesForKey(key, url, options, current_time, update_access_time, |
| 1749 cookies); | 1681 cookies); |
| 1750 | 1682 |
| 1751 // See if we can search for domain cookies, i.e. if the host has a TLD + 1. | 1683 // See if we can search for domain cookies, i.e. if the host has a TLD + 1. |
| 1752 const std::string domain(GetEffectiveDomain(url.scheme(), key)); | 1684 const std::string domain(cookie_utils::GetEffectiveDomain(url.scheme(), |
| 1685 key)); |
| 1753 if (domain.empty()) | 1686 if (domain.empty()) |
| 1754 return; | 1687 return; |
| 1755 DCHECK_LE(domain.length(), key.length()); | 1688 DCHECK_LE(domain.length(), key.length()); |
| 1756 DCHECK_EQ(0, key.compare(key.length() - domain.length(), domain.length(), | 1689 DCHECK_EQ(0, key.compare(key.length() - domain.length(), domain.length(), |
| 1757 domain)); | 1690 domain)); |
| 1758 | 1691 |
| 1759 // Walk through the string and query at the dot points (GURL should have | 1692 // Walk through the string and query at the dot points (GURL should have |
| 1760 // canonicalized the dots, so this should be safe). Stop once we reach the | 1693 // canonicalized the dots, so this should be safe). Stop once we reach the |
| 1761 // domain + registry; we can't write cookies past this point, and with some | 1694 // domain + registry; we can't write cookies past this point, and with some |
| 1762 // registrars other domains can, in which case we don't want to read their | 1695 // registrars other domains can, in which case we don't want to read their |
| (...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2642 else | 2575 else |
| 2643 SetSessionCookieExpiryTime(); | 2576 SetSessionCookieExpiryTime(); |
| 2644 | 2577 |
| 2645 // Do the best we can with the domain. | 2578 // Do the best we can with the domain. |
| 2646 std::string cookie_domain; | 2579 std::string cookie_domain; |
| 2647 std::string domain_string; | 2580 std::string domain_string; |
| 2648 if (pc.HasDomain()) { | 2581 if (pc.HasDomain()) { |
| 2649 domain_string = pc.Domain(); | 2582 domain_string = pc.Domain(); |
| 2650 } | 2583 } |
| 2651 bool result | 2584 bool result |
| 2652 = GetCookieDomainWithString(url, domain_string, | 2585 = cookie_utils::GetCookieDomainWithString(url, domain_string, |
| 2653 &cookie_domain); | 2586 &cookie_domain); |
| 2654 // Caller is responsible for passing in good arguments. | 2587 // Caller is responsible for passing in good arguments. |
| 2655 DCHECK(result); | 2588 DCHECK(result); |
| 2656 domain_ = cookie_domain; | 2589 domain_ = cookie_domain; |
| 2657 } | 2590 } |
| 2658 | 2591 |
| 2659 CookieMonster::CanonicalCookie::~CanonicalCookie() { | 2592 CookieMonster::CanonicalCookie::~CanonicalCookie() { |
| 2660 } | 2593 } |
| 2661 | 2594 |
| 2662 std::string CookieMonster::CanonicalCookie::GetCookieSourceFromURL( | 2595 std::string CookieMonster::CanonicalCookie::GetCookieSourceFromURL( |
| 2663 const GURL& url) { | 2596 const GURL& url) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2725 if (parsed_name != name) | 2658 if (parsed_name != name) |
| 2726 return NULL; | 2659 return NULL; |
| 2727 std::string parsed_value = ParsedCookie::ParseValueString(value); | 2660 std::string parsed_value = ParsedCookie::ParseValueString(value); |
| 2728 if (parsed_value != value) | 2661 if (parsed_value != value) |
| 2729 return NULL; | 2662 return NULL; |
| 2730 | 2663 |
| 2731 std::string parsed_domain = ParsedCookie::ParseValueString(domain); | 2664 std::string parsed_domain = ParsedCookie::ParseValueString(domain); |
| 2732 if (parsed_domain != domain) | 2665 if (parsed_domain != domain) |
| 2733 return NULL; | 2666 return NULL; |
| 2734 std::string cookie_domain; | 2667 std::string cookie_domain; |
| 2735 if (!GetCookieDomainWithString(url, parsed_domain, &cookie_domain)) | 2668 if (!cookie_utils::GetCookieDomainWithString(url, parsed_domain, |
| 2669 &cookie_domain)) { |
| 2736 return NULL; | 2670 return NULL; |
| 2671 } |
| 2737 | 2672 |
| 2738 std::string parsed_path = ParsedCookie::ParseValueString(path); | 2673 std::string parsed_path = ParsedCookie::ParseValueString(path); |
| 2739 if (parsed_path != path) | 2674 if (parsed_path != path) |
| 2740 return NULL; | 2675 return NULL; |
| 2741 | 2676 |
| 2742 std::string cookie_path = CanonPathWithString(url, parsed_path); | 2677 std::string cookie_path = CanonPathWithString(url, parsed_path); |
| 2743 // Expect that the path was either not specified (empty), or is valid. | 2678 // Expect that the path was either not specified (empty), or is valid. |
| 2744 if (!parsed_path.empty() && cookie_path != parsed_path) | 2679 if (!parsed_path.empty() && cookie_path != parsed_path) |
| 2745 return NULL; | 2680 return NULL; |
| 2746 // Canonicalize path again to make sure it escapes characters as needed. | 2681 // Canonicalize path again to make sure it escapes characters as needed. |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2832 std::string CookieMonster::CanonicalCookie::DebugString() const { | 2767 std::string CookieMonster::CanonicalCookie::DebugString() const { |
| 2833 return base::StringPrintf( | 2768 return base::StringPrintf( |
| 2834 "name: %s value: %s domain: %s path: %s creation: %" | 2769 "name: %s value: %s domain: %s path: %s creation: %" |
| 2835 PRId64, | 2770 PRId64, |
| 2836 name_.c_str(), value_.c_str(), | 2771 name_.c_str(), value_.c_str(), |
| 2837 domain_.c_str(), path_.c_str(), | 2772 domain_.c_str(), path_.c_str(), |
| 2838 static_cast<int64>(creation_date_.ToTimeT())); | 2773 static_cast<int64>(creation_date_.ToTimeT())); |
| 2839 } | 2774 } |
| 2840 | 2775 |
| 2841 } // namespace | 2776 } // namespace |
| OLD | NEW |