OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
642 | 642 |
643 *result = cookie_domain; | 643 *result = cookie_domain; |
644 return true; | 644 return true; |
645 } | 645 } |
646 | 646 |
647 // Determine the cookie domain to use for setting the specified cookie. | 647 // Determine the cookie domain to use for setting the specified cookie. |
648 static bool GetCookieDomain(const GURL& url, | 648 static bool GetCookieDomain(const GURL& url, |
649 const CookieMonster::ParsedCookie& pc, | 649 const CookieMonster::ParsedCookie& pc, |
650 std::string* result) { | 650 std::string* result) { |
651 std::string domain_string; | 651 std::string domain_string; |
652 if (pc.HasDomain()) | 652 if (pc.HasDomain() && !pc.IsOrigin()) |
653 domain_string = pc.Domain(); | 653 domain_string = pc.Domain(); |
654 return GetCookieDomainWithString(url, domain_string, result); | 654 return GetCookieDomainWithString(url, domain_string, result); |
655 } | 655 } |
656 | 656 |
657 static std::string CanonPathWithString(const GURL& url, | 657 static std::string CanonPathWithString(const GURL& url, |
658 const std::string& path_string) { | 658 const std::string& path_string) { |
659 // The RFC says the path should be a prefix of the current URL path. | 659 // The RFC says the path should be a prefix of the current URL path. |
660 // However, Mozilla allows you to set any path for compatibility with | 660 // However, Mozilla allows you to set any path for compatibility with |
661 // broken websites. We unfortunately will mimic this behavior. We try | 661 // broken websites. We unfortunately will mimic this behavior. We try |
662 // to be generous and accept cookies with an invalid path attribute, and | 662 // to be generous and accept cookies with an invalid path attribute, and |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
776 return false; | 776 return false; |
777 } | 777 } |
778 | 778 |
779 std::string cookie_domain; | 779 std::string cookie_domain; |
780 if (!GetCookieDomain(url, pc, &cookie_domain)) { | 780 if (!GetCookieDomain(url, pc, &cookie_domain)) { |
781 return false; | 781 return false; |
782 } | 782 } |
783 | 783 |
784 std::string cookie_path = CanonPath(url, pc); | 784 std::string cookie_path = CanonPath(url, pc); |
785 | 785 |
| 786 bool cookie_secure = pc.IsOrigin() ? url.SchemeIsSecure() : pc.IsSecure(); |
| 787 |
786 scoped_ptr<CanonicalCookie> cc; | 788 scoped_ptr<CanonicalCookie> cc; |
787 Time cookie_expires = CanonExpiration(pc, creation_time, options); | 789 Time cookie_expires = CanonExpiration(pc, creation_time, options); |
788 | 790 |
789 cc.reset(new CanonicalCookie(pc.Name(), pc.Value(), cookie_domain, | 791 cc.reset(new CanonicalCookie(pc.Name(), pc.Value(), cookie_domain, |
790 cookie_path, | 792 cookie_path, cookie_secure, |
791 pc.IsSecure(), pc.IsHttpOnly(), | 793 pc.IsHttpOnly(), pc.IsOrigin(), |
792 creation_time, creation_time, | 794 creation_time, creation_time, |
793 !cookie_expires.is_null(), cookie_expires)); | 795 !cookie_expires.is_null(), cookie_expires)); |
794 | 796 |
795 if (!cc.get()) { | 797 if (!cc.get()) { |
796 VLOG(kVlogSetCookies) << "WARNING: Failed to allocate CanonicalCookie"; | 798 VLOG(kVlogSetCookies) << "WARNING: Failed to allocate CanonicalCookie"; |
797 return false; | 799 return false; |
798 } | 800 } |
799 return SetCanonicalCookie(&cc, creation_time, options); | 801 return SetCanonicalCookie(&cc, creation_time, options); |
800 } | 802 } |
801 | 803 |
802 bool CookieMonster::SetCookieWithCreationTime(const GURL& url, | 804 bool CookieMonster::SetCookieWithCreationTime(const GURL& url, |
803 const std::string& cookie_line, | 805 const std::string& cookie_line, |
804 const base::Time& creation_time) { | 806 const base::Time& creation_time) { |
805 AutoLock autolock(lock_); | 807 AutoLock autolock(lock_); |
806 | 808 |
807 if (!HasCookieableScheme(url)) { | 809 if (!HasCookieableScheme(url)) { |
808 return false; | 810 return false; |
809 } | 811 } |
810 | 812 |
811 InitIfNecessary(); | 813 InitIfNecessary(); |
812 return SetCookieWithCreationTimeAndOptions(url, cookie_line, creation_time, | 814 return SetCookieWithCreationTimeAndOptions(url, cookie_line, creation_time, |
813 CookieOptions()); | 815 CookieOptions()); |
814 } | 816 } |
815 | 817 |
816 bool CookieMonster::SetCookieWithDetails( | 818 bool CookieMonster::SetCookieWithDetails( |
817 const GURL& url, const std::string& name, const std::string& value, | 819 const GURL& url, const std::string& name, const std::string& value, |
818 const std::string& domain, const std::string& path, | 820 const std::string& domain, const std::string& path, |
819 const base::Time& expiration_time, bool secure, bool http_only) { | 821 const base::Time& expiration_time, |
| 822 bool secure, bool http_only, bool origin) { |
820 | 823 |
821 AutoLock autolock(lock_); | 824 AutoLock autolock(lock_); |
822 | 825 |
823 if (!HasCookieableScheme(url)) | 826 if (!HasCookieableScheme(url)) |
824 return false; | 827 return false; |
825 | 828 |
826 InitIfNecessary(); | 829 InitIfNecessary(); |
827 | 830 |
828 Time creation_time = CurrentTime(); | 831 Time creation_time = CurrentTime(); |
829 last_time_seen_ = creation_time; | 832 last_time_seen_ = creation_time; |
830 | 833 |
831 scoped_ptr<CanonicalCookie> cc; | 834 scoped_ptr<CanonicalCookie> cc; |
832 cc.reset(CanonicalCookie::Create( | 835 cc.reset(CanonicalCookie::Create( |
833 url, name, value, domain, path, | 836 url, name, value, domain, path, |
834 creation_time, expiration_time, | 837 creation_time, expiration_time, |
835 secure, http_only)); | 838 secure, http_only, origin)); |
836 | 839 |
837 if (!cc.get()) | 840 if (!cc.get()) |
838 return false; | 841 return false; |
839 | 842 |
840 CookieOptions options; | 843 CookieOptions options; |
841 options.set_include_httponly(); | 844 options.set_include_httponly(); |
842 return SetCanonicalCookie(&cc, creation_time, options); | 845 return SetCanonicalCookie(&cc, creation_time, options); |
843 } | 846 } |
844 | 847 |
845 bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc, | 848 bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc, |
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1431 // If the cookie is expired, delete it. | 1434 // If the cookie is expired, delete it. |
1432 if (cc->IsExpired(current)) { | 1435 if (cc->IsExpired(current)) { |
1433 InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED); | 1436 InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED); |
1434 continue; | 1437 continue; |
1435 } | 1438 } |
1436 | 1439 |
1437 // Filter out HttpOnly cookies, per options. | 1440 // Filter out HttpOnly cookies, per options. |
1438 if (options.exclude_httponly() && cc->IsHttpOnly()) | 1441 if (options.exclude_httponly() && cc->IsHttpOnly()) |
1439 continue; | 1442 continue; |
1440 | 1443 |
| 1444 if (options.read_origin() != cc->IsOrigin()) |
| 1445 continue; |
| 1446 |
1441 // Filter out secure cookies unless we're https. | 1447 // Filter out secure cookies unless we're https. |
1442 if (!secure && cc->IsSecure()) | 1448 if (!secure && cc->IsSecure()) |
1443 continue; | 1449 continue; |
1444 | 1450 |
1445 // Filter out cookies that don't apply to this domain. | 1451 // Filter out cookies that don't apply to this domain. |
1446 if (expiry_and_key_scheme_ == EKS_KEEP_RECENT_AND_PURGE_ETLDP1 | 1452 if (expiry_and_key_scheme_ == EKS_KEEP_RECENT_AND_PURGE_ETLDP1 |
1447 && !cc->IsDomainMatch(scheme, host)) | 1453 && !cc->IsDomainMatch(scheme, host)) |
1448 continue; | 1454 continue; |
1449 | 1455 |
1450 if (!cc->IsOnPath(url.path())) | 1456 if (!cc->IsOnPath(url.path())) |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1514 last_statistic_record_time_ = current_time; | 1520 last_statistic_record_time_ = current_time; |
1515 } | 1521 } |
1516 | 1522 |
1517 CookieMonster::ParsedCookie::ParsedCookie(const std::string& cookie_line) | 1523 CookieMonster::ParsedCookie::ParsedCookie(const std::string& cookie_line) |
1518 : is_valid_(false), | 1524 : is_valid_(false), |
1519 path_index_(0), | 1525 path_index_(0), |
1520 domain_index_(0), | 1526 domain_index_(0), |
1521 expires_index_(0), | 1527 expires_index_(0), |
1522 maxage_index_(0), | 1528 maxage_index_(0), |
1523 secure_index_(0), | 1529 secure_index_(0), |
1524 httponly_index_(0) { | 1530 httponly_index_(0), |
| 1531 origin_index_(0) { |
1525 | 1532 |
1526 if (cookie_line.size() > kMaxCookieSize) { | 1533 if (cookie_line.size() > kMaxCookieSize) { |
1527 VLOG(1) << "Not parsing cookie, too large: " << cookie_line.size(); | 1534 VLOG(1) << "Not parsing cookie, too large: " << cookie_line.size(); |
1528 return; | 1535 return; |
1529 } | 1536 } |
1530 | 1537 |
1531 ParseTokenValuePairs(cookie_line); | 1538 ParseTokenValuePairs(cookie_line); |
1532 if (pairs_.size() > 0) { | 1539 if (pairs_.size() > 0) { |
1533 is_valid_ = true; | 1540 is_valid_ = true; |
1534 SetupAttributes(); | 1541 SetupAttributes(); |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1749 } | 1756 } |
1750 } | 1757 } |
1751 | 1758 |
1752 void CookieMonster::ParsedCookie::SetupAttributes() { | 1759 void CookieMonster::ParsedCookie::SetupAttributes() { |
1753 static const char kPathTokenName[] = "path"; | 1760 static const char kPathTokenName[] = "path"; |
1754 static const char kDomainTokenName[] = "domain"; | 1761 static const char kDomainTokenName[] = "domain"; |
1755 static const char kExpiresTokenName[] = "expires"; | 1762 static const char kExpiresTokenName[] = "expires"; |
1756 static const char kMaxAgeTokenName[] = "max-age"; | 1763 static const char kMaxAgeTokenName[] = "max-age"; |
1757 static const char kSecureTokenName[] = "secure"; | 1764 static const char kSecureTokenName[] = "secure"; |
1758 static const char kHttpOnlyTokenName[] = "httponly"; | 1765 static const char kHttpOnlyTokenName[] = "httponly"; |
| 1766 static const char kOriginTokenName[] = "origin"; |
1759 | 1767 |
1760 // We skip over the first token/value, the user supplied one. | 1768 // We skip over the first token/value, the user supplied one. |
1761 for (size_t i = 1; i < pairs_.size(); ++i) { | 1769 for (size_t i = 1; i < pairs_.size(); ++i) { |
1762 if (pairs_[i].first == kPathTokenName) { | 1770 if (pairs_[i].first == kPathTokenName) { |
1763 path_index_ = i; | 1771 path_index_ = i; |
1764 } else if (pairs_[i].first == kDomainTokenName) { | 1772 } else if (pairs_[i].first == kDomainTokenName) { |
1765 domain_index_ = i; | 1773 domain_index_ = i; |
1766 } else if (pairs_[i].first == kExpiresTokenName) { | 1774 } else if (pairs_[i].first == kExpiresTokenName) { |
1767 expires_index_ = i; | 1775 expires_index_ = i; |
1768 } else if (pairs_[i].first == kMaxAgeTokenName) { | 1776 } else if (pairs_[i].first == kMaxAgeTokenName) { |
1769 maxage_index_ = i; | 1777 maxage_index_ = i; |
1770 } else if (pairs_[i].first == kSecureTokenName) { | 1778 } else if (pairs_[i].first == kSecureTokenName) { |
1771 secure_index_ = i; | 1779 secure_index_ = i; |
1772 } else if (pairs_[i].first == kHttpOnlyTokenName) { | 1780 } else if (pairs_[i].first == kHttpOnlyTokenName) { |
1773 httponly_index_ = i; | 1781 httponly_index_ = i; |
| 1782 } else if (pairs_[i].first == kOriginTokenName) { |
| 1783 origin_index_ = i; |
1774 } else { | 1784 } else { |
1775 /* some attribute we don't know or don't care about. */ | 1785 /* some attribute we don't know or don't care about. */ |
1776 } | 1786 } |
1777 } | 1787 } |
1778 } | 1788 } |
1779 | 1789 |
1780 // Create a cookie-line for the cookie. For debugging only! | 1790 // Create a cookie-line for the cookie. For debugging only! |
1781 // If we want to use this for something more than debugging, we | 1791 // If we want to use this for something more than debugging, we |
1782 // should rewrite it better... | 1792 // should rewrite it better... |
1783 std::string CookieMonster::ParsedCookie::DebugString() const { | 1793 std::string CookieMonster::ParsedCookie::DebugString() const { |
1784 std::string out; | 1794 std::string out; |
1785 for (PairList::const_iterator it = pairs_.begin(); | 1795 for (PairList::const_iterator it = pairs_.begin(); |
1786 it != pairs_.end(); ++it) { | 1796 it != pairs_.end(); ++it) { |
1787 out.append(it->first); | 1797 out.append(it->first); |
1788 out.append("="); | 1798 out.append("="); |
1789 out.append(it->second); | 1799 out.append(it->second); |
1790 out.append("; "); | 1800 out.append("; "); |
1791 } | 1801 } |
1792 return out; | 1802 return out; |
1793 } | 1803 } |
1794 | 1804 |
| 1805 // TODO(abarth): Do we need to initialize the boolean members here? |
1795 CookieMonster::CanonicalCookie::CanonicalCookie() { | 1806 CookieMonster::CanonicalCookie::CanonicalCookie() { |
1796 } | 1807 } |
1797 | 1808 |
1798 CookieMonster::CanonicalCookie::CanonicalCookie(const std::string& name, | 1809 CookieMonster::CanonicalCookie::CanonicalCookie(const std::string& name, |
1799 const std::string& value, | 1810 const std::string& value, |
1800 const std::string& domain, | 1811 const std::string& domain, |
1801 const std::string& path, | 1812 const std::string& path, |
1802 bool secure, | 1813 bool secure, |
1803 bool httponly, | 1814 bool httponly, |
| 1815 bool origin, |
1804 const base::Time& creation, | 1816 const base::Time& creation, |
1805 const base::Time& last_access, | 1817 const base::Time& last_access, |
1806 bool has_expires, | 1818 bool has_expires, |
1807 const base::Time& expires) | 1819 const base::Time& expires) |
1808 : name_(name), | 1820 : name_(name), |
1809 value_(value), | 1821 value_(value), |
1810 domain_(domain), | 1822 domain_(domain), |
1811 path_(path), | 1823 path_(path), |
1812 creation_date_(creation), | 1824 creation_date_(creation), |
1813 last_access_date_(last_access), | 1825 last_access_date_(last_access), |
1814 expiry_date_(expires), | 1826 expiry_date_(expires), |
1815 has_expires_(has_expires), | 1827 has_expires_(has_expires), |
1816 secure_(secure), | 1828 secure_(secure), |
1817 httponly_(httponly) { | 1829 httponly_(httponly), |
| 1830 origin_(origin) { |
1818 } | 1831 } |
1819 | 1832 |
1820 CookieMonster::CanonicalCookie::CanonicalCookie(const GURL& url, | 1833 CookieMonster::CanonicalCookie::CanonicalCookie(const GURL& url, |
1821 const ParsedCookie& pc) | 1834 const ParsedCookie& pc) |
1822 : name_(pc.Name()), | 1835 : name_(pc.Name()), |
1823 value_(pc.Value()), | 1836 value_(pc.Value()), |
1824 path_(CanonPath(url, pc)), | 1837 path_(CanonPath(url, pc)), |
1825 creation_date_(Time::Now()), | 1838 creation_date_(Time::Now()), |
1826 last_access_date_(Time()), | 1839 last_access_date_(Time()), |
1827 has_expires_(pc.HasExpires()), | 1840 has_expires_(pc.HasExpires()), |
1828 secure_(pc.IsSecure()), | 1841 secure_(pc.IsSecure()), |
1829 httponly_(pc.IsHttpOnly()) { | 1842 httponly_(pc.IsHttpOnly()), |
| 1843 origin_(pc.IsOrigin()) { |
1830 if (has_expires_) | 1844 if (has_expires_) |
1831 expiry_date_ = CanonExpiration(pc, creation_date_, CookieOptions()); | 1845 expiry_date_ = CanonExpiration(pc, creation_date_, CookieOptions()); |
1832 | 1846 |
1833 // Do the best we can with the domain. | 1847 // Do the best we can with the domain. |
1834 std::string cookie_domain; | 1848 std::string cookie_domain; |
1835 std::string domain_string; | 1849 std::string domain_string; |
1836 if (pc.HasDomain()) { | 1850 if (pc.HasDomain()) { |
1837 domain_string = pc.Domain(); | 1851 domain_string = pc.Domain(); |
1838 } | 1852 } |
1839 bool result | 1853 bool result |
(...skipping 18 matching lines...) Expand all Loading... |
1858 SetDefaultCookieableSchemes(); | 1872 SetDefaultCookieableSchemes(); |
1859 } | 1873 } |
1860 | 1874 |
1861 CookieMonster::CanonicalCookie::~CanonicalCookie() { | 1875 CookieMonster::CanonicalCookie::~CanonicalCookie() { |
1862 } | 1876 } |
1863 | 1877 |
1864 CookieMonster::CanonicalCookie* CookieMonster::CanonicalCookie::Create( | 1878 CookieMonster::CanonicalCookie* CookieMonster::CanonicalCookie::Create( |
1865 const GURL& url, const std::string& name, const std::string& value, | 1879 const GURL& url, const std::string& name, const std::string& value, |
1866 const std::string& domain, const std::string& path, | 1880 const std::string& domain, const std::string& path, |
1867 const base::Time& creation_time, const base::Time& expiration_time, | 1881 const base::Time& creation_time, const base::Time& expiration_time, |
1868 bool secure, bool http_only) { | 1882 bool secure, bool http_only, bool origin) { |
1869 // Expect valid attribute tokens and values, as defined by the ParsedCookie | 1883 // Expect valid attribute tokens and values, as defined by the ParsedCookie |
1870 // logic, otherwise don't create the cookie. | 1884 // logic, otherwise don't create the cookie. |
1871 std::string parsed_name = ParsedCookie::ParseTokenString(name); | 1885 std::string parsed_name = ParsedCookie::ParseTokenString(name); |
1872 if (parsed_name != name) | 1886 if (parsed_name != name) |
1873 return NULL; | 1887 return NULL; |
1874 std::string parsed_value = ParsedCookie::ParseValueString(value); | 1888 std::string parsed_value = ParsedCookie::ParseValueString(value); |
1875 if (parsed_value != value) | 1889 if (parsed_value != value) |
1876 return NULL; | 1890 return NULL; |
1877 | 1891 |
1878 std::string parsed_domain = ParsedCookie::ParseValueString(domain); | 1892 std::string parsed_domain = ParsedCookie::ParseValueString(domain); |
(...skipping 14 matching lines...) Expand all Loading... |
1893 // Canonicalize path again to make sure it escapes characters as needed. | 1907 // Canonicalize path again to make sure it escapes characters as needed. |
1894 url_parse::Component path_component(0, cookie_path.length()); | 1908 url_parse::Component path_component(0, cookie_path.length()); |
1895 url_canon::RawCanonOutputT<char> canon_path; | 1909 url_canon::RawCanonOutputT<char> canon_path; |
1896 url_parse::Component canon_path_component; | 1910 url_parse::Component canon_path_component; |
1897 url_canon::CanonicalizePath(cookie_path.data(), path_component, | 1911 url_canon::CanonicalizePath(cookie_path.data(), path_component, |
1898 &canon_path, &canon_path_component); | 1912 &canon_path, &canon_path_component); |
1899 cookie_path = std::string(canon_path.data() + canon_path_component.begin, | 1913 cookie_path = std::string(canon_path.data() + canon_path_component.begin, |
1900 canon_path_component.len); | 1914 canon_path_component.len); |
1901 | 1915 |
1902 return new CanonicalCookie(parsed_name, parsed_value, cookie_domain, | 1916 return new CanonicalCookie(parsed_name, parsed_value, cookie_domain, |
1903 cookie_path, secure, http_only, | 1917 cookie_path, secure, http_only, origin, |
1904 creation_time, creation_time, | 1918 creation_time, creation_time, |
1905 !expiration_time.is_null(), expiration_time); | 1919 !expiration_time.is_null(), expiration_time); |
1906 } | 1920 } |
1907 | 1921 |
1908 bool CookieMonster::CanonicalCookie::IsOnPath( | 1922 bool CookieMonster::CanonicalCookie::IsOnPath( |
1909 const std::string& url_path) const { | 1923 const std::string& url_path) const { |
1910 | 1924 |
1911 // A zero length would be unsafe for our trailing '/' checks, and | 1925 // A zero length would be unsafe for our trailing '/' checks, and |
1912 // would also make no sense for our prefix match. The code that | 1926 // would also make no sense for our prefix match. The code that |
1913 // creates a CanonicalCookie should make sure the path is never zero length, | 1927 // creates a CanonicalCookie should make sure the path is never zero length, |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1980 return base::StringPrintf( | 1994 return base::StringPrintf( |
1981 "name: %s value: %s domain: %s path: %s creation: %" | 1995 "name: %s value: %s domain: %s path: %s creation: %" |
1982 PRId64, | 1996 PRId64, |
1983 name_.c_str(), value_.c_str(), | 1997 name_.c_str(), value_.c_str(), |
1984 domain_.c_str(), path_.c_str(), | 1998 domain_.c_str(), path_.c_str(), |
1985 static_cast<int64>(creation_date_.ToTimeT())); | 1999 static_cast<int64>(creation_date_.ToTimeT())); |
1986 } | 2000 } |
1987 | 2001 |
1988 } // namespace | 2002 } // namespace |
1989 | 2003 |
OLD | NEW |