| 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 30 matching lines...) Expand all Loading... |
| 41 * the terms of any one of the MPL, the GPL or the LGPL. | 41 * the terms of any one of the MPL, the GPL or the LGPL. |
| 42 * | 42 * |
| 43 * ***** END LICENSE BLOCK ***** */ | 43 * ***** END LICENSE BLOCK ***** */ |
| 44 | 44 |
| 45 #include "net/base/cookie_monster.h" | 45 #include "net/base/cookie_monster.h" |
| 46 | 46 |
| 47 #include <algorithm> | 47 #include <algorithm> |
| 48 | 48 |
| 49 #include "base/basictypes.h" | 49 #include "base/basictypes.h" |
| 50 #include "base/format_macros.h" | 50 #include "base/format_macros.h" |
| 51 #include "base/histogram.h" | |
| 52 #include "base/logging.h" | 51 #include "base/logging.h" |
| 53 #include "base/scoped_ptr.h" | 52 #include "base/scoped_ptr.h" |
| 54 #include "base/string_tokenizer.h" | 53 #include "base/string_tokenizer.h" |
| 55 #include "base/string_util.h" | 54 #include "base/string_util.h" |
| 56 #include "googleurl/src/gurl.h" | 55 #include "googleurl/src/gurl.h" |
| 57 #include "googleurl/src/url_canon.h" | 56 #include "googleurl/src/url_canon.h" |
| 58 #include "net/base/net_util.h" | 57 #include "net/base/net_util.h" |
| 59 #include "net/base/registry_controlled_domain.h" | 58 #include "net/base/registry_controlled_domain.h" |
| 60 | 59 |
| 61 // #define COOKIE_LOGGING_ENABLED | 60 // #define COOKIE_LOGGING_ENABLED |
| 62 #ifdef COOKIE_LOGGING_ENABLED | 61 #ifdef COOKIE_LOGGING_ENABLED |
| 63 #define COOKIE_DLOG(severity) DLOG_IF(INFO, 1) | 62 #define COOKIE_DLOG(severity) DLOG_IF(INFO, 1) |
| 64 #else | 63 #else |
| 65 #define COOKIE_DLOG(severity) DLOG_IF(INFO, 0) | 64 #define COOKIE_DLOG(severity) DLOG_IF(INFO, 0) |
| 66 #endif | 65 #endif |
| 67 | 66 |
| 68 using base::Time; | 67 using base::Time; |
| 69 using base::TimeDelta; | 68 using base::TimeDelta; |
| 70 | 69 |
| 70 static const int kMinutesInTenYears = 10 * 365 * 24 * 60; |
| 71 |
| 71 namespace net { | 72 namespace net { |
| 72 | 73 |
| 73 namespace { | 74 namespace { |
| 74 | 75 |
| 75 // Cookie garbage collection thresholds. Based off of the Mozilla defaults. | 76 // Cookie garbage collection thresholds. Based off of the Mozilla defaults. |
| 76 // It might seem scary to have a high purge value, but really it's not. You | 77 // It might seem scary to have a high purge value, but really it's not. You |
| 77 // just make sure that you increase the max to cover the increase in purge, | 78 // just make sure that you increase the max to cover the increase in purge, |
| 78 // and we would have been purging the same amount of cookies. We're just | 79 // and we would have been purging the same amount of cookies. We're just |
| 79 // going through the garbage collection process less often. | 80 // going through the garbage collection process less often. |
| 80 const size_t kNumCookiesPerHost = 70; // ~50 cookies | 81 const size_t kNumCookiesPerHost = 70; // ~50 cookies |
| (...skipping 22 matching lines...) Expand all Loading... |
| 103 // static | 104 // static |
| 104 void CookieMonster::EnableFileScheme() { | 105 void CookieMonster::EnableFileScheme() { |
| 105 enable_file_scheme_ = true; | 106 enable_file_scheme_ = true; |
| 106 } | 107 } |
| 107 | 108 |
| 108 CookieMonster::CookieMonster(PersistentCookieStore* store, Delegate* delegate) | 109 CookieMonster::CookieMonster(PersistentCookieStore* store, Delegate* delegate) |
| 109 : initialized_(false), | 110 : initialized_(false), |
| 110 store_(store), | 111 store_(store), |
| 111 last_access_threshold_( | 112 last_access_threshold_( |
| 112 TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)), | 113 TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)), |
| 113 delegate_(delegate) { | 114 delegate_(delegate), |
| 115 last_statistic_record_time_(Time::Now()) { |
| 114 SetDefaultCookieableSchemes(); | 116 SetDefaultCookieableSchemes(); |
| 115 } | 117 } |
| 116 | 118 |
| 117 CookieMonster::~CookieMonster() { | 119 CookieMonster::~CookieMonster() { |
| 118 DeleteAll(false); | 120 DeleteAll(false); |
| 119 } | 121 } |
| 120 | 122 |
| 121 void CookieMonster::InitStore() { | 123 void CookieMonster::InitStore() { |
| 122 DCHECK(store_) << "Store must exist to initialize"; | 124 DCHECK(store_) << "Store must exist to initialize"; |
| 123 | 125 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 key.c_str(), | 236 key.c_str(), |
| 235 signature.first.c_str(), | 237 signature.first.c_str(), |
| 236 signature.second.c_str()); | 238 signature.second.c_str()); |
| 237 | 239 |
| 238 // Remove all the cookies identified by |dupes|. It is valid to delete our | 240 // Remove all the cookies identified by |dupes|. It is valid to delete our |
| 239 // list of iterators one at a time, since |cookies_| is a multimap (they | 241 // list of iterators one at a time, since |cookies_| is a multimap (they |
| 240 // don't invalidate existing iterators following deletion). | 242 // don't invalidate existing iterators following deletion). |
| 241 for (CookieList::iterator dupes_it = dupes.begin(); | 243 for (CookieList::iterator dupes_it = dupes.begin(); |
| 242 dupes_it != dupes.end(); | 244 dupes_it != dupes.end(); |
| 243 ++dupes_it) { | 245 ++dupes_it) { |
| 244 InternalDeleteCookie(*dupes_it, true /*sync_to_store*/); | 246 InternalDeleteCookie(*dupes_it, true /*sync_to_store*/, |
| 247 kDeleteCookieDuplicateInBackingStore); |
| 245 } | 248 } |
| 246 } | 249 } |
| 247 | 250 |
| 248 return num_duplicates; | 251 return num_duplicates; |
| 249 } | 252 } |
| 250 | 253 |
| 251 void CookieMonster::SetDefaultCookieableSchemes() { | 254 void CookieMonster::SetDefaultCookieableSchemes() { |
| 252 // Note: file must be the last scheme. | 255 // Note: file must be the last scheme. |
| 253 static const char* kDefaultCookieableSchemes[] = { "http", "https", "file" }; | 256 static const char* kDefaultCookieableSchemes[] = { "http", "https", "file" }; |
| 254 int num_schemes = enable_file_scheme_ ? 3 : 2; | 257 int num_schemes = enable_file_scheme_ ? 3 : 2; |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 if (DeleteAnyEquivalentCookie(cookie_domain, **cc, | 661 if (DeleteAnyEquivalentCookie(cookie_domain, **cc, |
| 659 options.exclude_httponly())) { | 662 options.exclude_httponly())) { |
| 660 COOKIE_DLOG(INFO) << "SetCookie() not clobbering httponly cookie"; | 663 COOKIE_DLOG(INFO) << "SetCookie() not clobbering httponly cookie"; |
| 661 return false; | 664 return false; |
| 662 } | 665 } |
| 663 | 666 |
| 664 COOKIE_DLOG(INFO) << "SetCookie() cc: " << (*cc)->DebugString(); | 667 COOKIE_DLOG(INFO) << "SetCookie() cc: " << (*cc)->DebugString(); |
| 665 | 668 |
| 666 // Realize that we might be setting an expired cookie, and the only point | 669 // Realize that we might be setting an expired cookie, and the only point |
| 667 // was to delete the cookie which we've already done. | 670 // was to delete the cookie which we've already done. |
| 668 if (!(*cc)->IsExpired(creation_time)) | 671 if (!(*cc)->IsExpired(creation_time)) { |
| 672 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 673 "net.CookieExpirationDurationMinutes", |
| 674 ((*cc)->ExpiryDate() - creation_time).InMinutes(), |
| 675 1, kMinutesInTenYears, 50); |
| 669 InternalInsertCookie(cookie_domain, cc->release(), true); | 676 InternalInsertCookie(cookie_domain, cc->release(), true); |
| 677 } |
| 670 | 678 |
| 671 // We assume that hopefully setting a cookie will be less common than | 679 // We assume that hopefully setting a cookie will be less common than |
| 672 // querying a cookie. Since setting a cookie can put us over our limits, | 680 // querying a cookie. Since setting a cookie can put us over our limits, |
| 673 // make sure that we garbage collect... We can also make the assumption that | 681 // make sure that we garbage collect... We can also make the assumption that |
| 674 // if a cookie was set, in the common case it will be used soon after, | 682 // if a cookie was set, in the common case it will be used soon after, |
| 675 // and we will purge the expired cookies in GetCookies(). | 683 // and we will purge the expired cookies in GetCookies(). |
| 676 GarbageCollect(creation_time, cookie_domain); | 684 GarbageCollect(creation_time, cookie_domain); |
| 677 | 685 |
| 678 return true; | 686 return true; |
| 679 } | 687 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 694 lock_.AssertAcquired(); | 702 lock_.AssertAcquired(); |
| 695 | 703 |
| 696 // Based off the Mozilla code. When a cookie has been accessed recently, | 704 // Based off the Mozilla code. When a cookie has been accessed recently, |
| 697 // don't bother updating its access time again. This reduces the number of | 705 // don't bother updating its access time again. This reduces the number of |
| 698 // updates we do during pageload, which in turn reduces the chance our storage | 706 // updates we do during pageload, which in turn reduces the chance our storage |
| 699 // backend will hit its batch thresholds and be forced to update. | 707 // backend will hit its batch thresholds and be forced to update. |
| 700 const Time current = Time::Now(); | 708 const Time current = Time::Now(); |
| 701 if ((current - cc->LastAccessDate()) < last_access_threshold_) | 709 if ((current - cc->LastAccessDate()) < last_access_threshold_) |
| 702 return; | 710 return; |
| 703 | 711 |
| 712 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 713 "net.CookieBetweenAccessIntervalMinutes", |
| 714 (current - cc->LastAccessDate()).InMinutes(), |
| 715 1, kMinutesInTenYears, 50); |
| 716 |
| 704 cc->SetLastAccessDate(current); | 717 cc->SetLastAccessDate(current); |
| 705 if (cc->IsPersistent() && store_) | 718 if (cc->IsPersistent() && store_) |
| 706 store_->UpdateCookieAccessTime(*cc); | 719 store_->UpdateCookieAccessTime(*cc); |
| 707 } | 720 } |
| 708 | 721 |
| 709 void CookieMonster::InternalDeleteCookie(CookieMap::iterator it, | 722 void CookieMonster::InternalDeleteCookie(CookieMap::iterator it, |
| 710 bool sync_to_store) { | 723 bool sync_to_store, |
| 724 DeletionCause deletion_cause) { |
| 711 lock_.AssertAcquired(); | 725 lock_.AssertAcquired(); |
| 712 | 726 |
| 727 UMA_HISTOGRAM_ENUMERATION("net.CookieDeletionCause", deletion_cause, |
| 728 kDeleteCookieLastEntry); |
| 729 |
| 713 CanonicalCookie* cc = it->second; | 730 CanonicalCookie* cc = it->second; |
| 714 COOKIE_DLOG(INFO) << "InternalDeleteCookie() cc: " << cc->DebugString(); | 731 COOKIE_DLOG(INFO) << "InternalDeleteCookie() cc: " << cc->DebugString(); |
| 715 if (cc->IsPersistent() && store_ && sync_to_store) | 732 if (cc->IsPersistent() && store_ && sync_to_store) |
| 716 store_->DeleteCookie(*cc); | 733 store_->DeleteCookie(*cc); |
| 717 if (delegate_.get()) | 734 if (delegate_.get()) |
| 718 delegate_->OnCookieChanged(it->first, *cc, true); | 735 delegate_->OnCookieChanged(it->first, *cc, true); |
| 719 cookies_.erase(it); | 736 cookies_.erase(it); |
| 720 delete cc; | 737 delete cc; |
| 721 } | 738 } |
| 722 | 739 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 734 ++its.first; | 751 ++its.first; |
| 735 | 752 |
| 736 if (ecc.IsEquivalent(*cc)) { | 753 if (ecc.IsEquivalent(*cc)) { |
| 737 // We should never have more than one equivalent cookie, since they should | 754 // We should never have more than one equivalent cookie, since they should |
| 738 // overwrite each other. | 755 // overwrite each other. |
| 739 CHECK(!found_equivalent_cookie) << | 756 CHECK(!found_equivalent_cookie) << |
| 740 "Duplicate equivalent cookies found, cookie store is corrupted."; | 757 "Duplicate equivalent cookies found, cookie store is corrupted."; |
| 741 if (skip_httponly && cc->IsHttpOnly()) { | 758 if (skip_httponly && cc->IsHttpOnly()) { |
| 742 skipped_httponly = true; | 759 skipped_httponly = true; |
| 743 } else { | 760 } else { |
| 744 InternalDeleteCookie(curit, true); | 761 InternalDeleteCookie(curit, true, kDeleteCookieOverwrite); |
| 745 } | 762 } |
| 746 found_equivalent_cookie = true; | 763 found_equivalent_cookie = true; |
| 747 } | 764 } |
| 748 } | 765 } |
| 749 return skipped_httponly; | 766 return skipped_httponly; |
| 750 } | 767 } |
| 751 | 768 |
| 752 int CookieMonster::GarbageCollect(const Time& current, | 769 int CookieMonster::GarbageCollect(const Time& current, |
| 753 const std::string& key) { | 770 const std::string& key) { |
| 754 lock_.AssertAcquired(); | 771 lock_.AssertAcquired(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 797 | 814 |
| 798 // If the range still has too many cookies, delete the least recently used. | 815 // If the range still has too many cookies, delete the least recently used. |
| 799 if (cookie_its.size() > num_max) { | 816 if (cookie_its.size() > num_max) { |
| 800 COOKIE_DLOG(INFO) << "GarbageCollectRange() Deep Garbage Collect."; | 817 COOKIE_DLOG(INFO) << "GarbageCollectRange() Deep Garbage Collect."; |
| 801 // Purge down to (|num_max| - |num_purge|) total cookies. | 818 // Purge down to (|num_max| - |num_purge|) total cookies. |
| 802 DCHECK(num_purge <= num_max); | 819 DCHECK(num_purge <= num_max); |
| 803 num_purge += cookie_its.size() - num_max; | 820 num_purge += cookie_its.size() - num_max; |
| 804 | 821 |
| 805 std::partial_sort(cookie_its.begin(), cookie_its.begin() + num_purge, | 822 std::partial_sort(cookie_its.begin(), cookie_its.begin() + num_purge, |
| 806 cookie_its.end(), LRUCookieSorter); | 823 cookie_its.end(), LRUCookieSorter); |
| 807 for (size_t i = 0; i < num_purge; ++i) | 824 for (size_t i = 0; i < num_purge; ++i) { |
| 808 InternalDeleteCookie(cookie_its[i], true); | 825 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 826 "net.CookieEvictedLastAccessMinutes", |
| 827 (current - cookie_its[i]->second->LastAccessDate()).InMinutes(), |
| 828 1, kMinutesInTenYears, 50); |
| 829 InternalDeleteCookie(cookie_its[i], true, kDeleteCookieEvicted); |
| 830 } |
| 809 | 831 |
| 810 num_deleted += num_purge; | 832 num_deleted += num_purge; |
| 811 } | 833 } |
| 812 | 834 |
| 813 return num_deleted; | 835 return num_deleted; |
| 814 } | 836 } |
| 815 | 837 |
| 816 int CookieMonster::GarbageCollectExpired( | 838 int CookieMonster::GarbageCollectExpired( |
| 817 const Time& current, | 839 const Time& current, |
| 818 const CookieMapItPair& itpair, | 840 const CookieMapItPair& itpair, |
| 819 std::vector<CookieMap::iterator>* cookie_its) { | 841 std::vector<CookieMap::iterator>* cookie_its) { |
| 820 lock_.AssertAcquired(); | 842 lock_.AssertAcquired(); |
| 821 | 843 |
| 822 int num_deleted = 0; | 844 int num_deleted = 0; |
| 823 for (CookieMap::iterator it = itpair.first, end = itpair.second; it != end;) { | 845 for (CookieMap::iterator it = itpair.first, end = itpair.second; it != end;) { |
| 824 CookieMap::iterator curit = it; | 846 CookieMap::iterator curit = it; |
| 825 ++it; | 847 ++it; |
| 826 | 848 |
| 827 if (curit->second->IsExpired(current)) { | 849 if (curit->second->IsExpired(current)) { |
| 828 InternalDeleteCookie(curit, true); | 850 InternalDeleteCookie(curit, true, kDeleteCookieExpired); |
| 829 ++num_deleted; | 851 ++num_deleted; |
| 830 } else if (cookie_its) { | 852 } else if (cookie_its) { |
| 831 cookie_its->push_back(curit); | 853 cookie_its->push_back(curit); |
| 832 } | 854 } |
| 833 } | 855 } |
| 834 | 856 |
| 835 return num_deleted; | 857 return num_deleted; |
| 836 } | 858 } |
| 837 | 859 |
| 838 int CookieMonster::DeleteAll(bool sync_to_store) { | 860 int CookieMonster::DeleteAll(bool sync_to_store) { |
| 839 AutoLock autolock(lock_); | 861 AutoLock autolock(lock_); |
| 840 InitIfNecessary(); | 862 InitIfNecessary(); |
| 841 | 863 |
| 842 int num_deleted = 0; | 864 int num_deleted = 0; |
| 843 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) { | 865 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) { |
| 844 CookieMap::iterator curit = it; | 866 CookieMap::iterator curit = it; |
| 845 ++it; | 867 ++it; |
| 846 InternalDeleteCookie(curit, sync_to_store); | 868 InternalDeleteCookie(curit, sync_to_store, |
| 869 sync_to_store ? kDeleteCookieExplicit : |
| 870 kDeleteCookieDontRecord /* Destruction. */); |
| 847 ++num_deleted; | 871 ++num_deleted; |
| 848 } | 872 } |
| 849 | 873 |
| 850 return num_deleted; | 874 return num_deleted; |
| 851 } | 875 } |
| 852 | 876 |
| 853 int CookieMonster::DeleteAllCreatedBetween(const Time& delete_begin, | 877 int CookieMonster::DeleteAllCreatedBetween(const Time& delete_begin, |
| 854 const Time& delete_end, | 878 const Time& delete_end, |
| 855 bool sync_to_store) { | 879 bool sync_to_store) { |
| 856 AutoLock autolock(lock_); | 880 AutoLock autolock(lock_); |
| 857 InitIfNecessary(); | 881 InitIfNecessary(); |
| 858 | 882 |
| 859 int num_deleted = 0; | 883 int num_deleted = 0; |
| 860 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) { | 884 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) { |
| 861 CookieMap::iterator curit = it; | 885 CookieMap::iterator curit = it; |
| 862 CanonicalCookie* cc = curit->second; | 886 CanonicalCookie* cc = curit->second; |
| 863 ++it; | 887 ++it; |
| 864 | 888 |
| 865 if (cc->CreationDate() >= delete_begin && | 889 if (cc->CreationDate() >= delete_begin && |
| 866 (delete_end.is_null() || cc->CreationDate() < delete_end)) { | 890 (delete_end.is_null() || cc->CreationDate() < delete_end)) { |
| 867 InternalDeleteCookie(curit, sync_to_store); | 891 InternalDeleteCookie(curit, sync_to_store, kDeleteCookieExplicit); |
| 868 ++num_deleted; | 892 ++num_deleted; |
| 869 } | 893 } |
| 870 } | 894 } |
| 871 | 895 |
| 872 return num_deleted; | 896 return num_deleted; |
| 873 } | 897 } |
| 874 | 898 |
| 875 int CookieMonster::DeleteAllCreatedAfter(const Time& delete_begin, | 899 int CookieMonster::DeleteAllCreatedAfter(const Time& delete_begin, |
| 876 bool sync_to_store) { | 900 bool sync_to_store) { |
| 877 return DeleteAllCreatedBetween(delete_begin, Time(), sync_to_store); | 901 return DeleteAllCreatedBetween(delete_begin, Time(), sync_to_store); |
| 878 } | 902 } |
| 879 | 903 |
| 880 int CookieMonster::DeleteAllForURL(const GURL& url, | 904 int CookieMonster::DeleteAllForURL(const GURL& url, |
| 881 bool sync_to_store) { | 905 bool sync_to_store) { |
| 882 AutoLock autolock(lock_); | 906 AutoLock autolock(lock_); |
| 883 InitIfNecessary(); | 907 InitIfNecessary(); |
| 884 | 908 |
| 885 CookieList cookies = InternalGetAllCookiesForURL(url); | 909 CookieList cookies = InternalGetAllCookiesForURL(url); |
| 886 int num_deleted = 0; | 910 int num_deleted = 0; |
| 887 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) { | 911 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) { |
| 888 CookieMap::iterator curit = it; | 912 CookieMap::iterator curit = it; |
| 889 ++it; | 913 ++it; |
| 890 InternalDeleteCookie(curit, sync_to_store); | 914 InternalDeleteCookie(curit, sync_to_store, kDeleteCookieExplicit); |
| 891 } | 915 } |
| 892 return num_deleted; | 916 return num_deleted; |
| 893 } | 917 } |
| 894 | 918 |
| 895 bool CookieMonster::DeleteCookie(const std::string& domain, | 919 bool CookieMonster::DeleteCookie(const std::string& domain, |
| 896 const CanonicalCookie& cookie, | 920 const CanonicalCookie& cookie, |
| 897 bool sync_to_store) { | 921 bool sync_to_store) { |
| 898 AutoLock autolock(lock_); | 922 AutoLock autolock(lock_); |
| 899 InitIfNecessary(); | 923 InitIfNecessary(); |
| 900 | 924 |
| 901 for (CookieMapItPair its = cookies_.equal_range(domain); | 925 for (CookieMapItPair its = cookies_.equal_range(domain); |
| 902 its.first != its.second; ++its.first) { | 926 its.first != its.second; ++its.first) { |
| 903 // The creation date acts as our unique index... | 927 // The creation date acts as our unique index... |
| 904 if (its.first->second->CreationDate() == cookie.CreationDate()) { | 928 if (its.first->second->CreationDate() == cookie.CreationDate()) { |
| 905 InternalDeleteCookie(its.first, sync_to_store); | 929 InternalDeleteCookie(its.first, sync_to_store, kDeleteCookieExplicit); |
| 906 return true; | 930 return true; |
| 907 } | 931 } |
| 908 } | 932 } |
| 909 return false; | 933 return false; |
| 910 } | 934 } |
| 911 | 935 |
| 912 // Mozilla sorts on the path length (longest first), and then it | 936 // Mozilla sorts on the path length (longest first), and then it |
| 913 // sorts by creation time (oldest first). | 937 // sorts by creation time (oldest first). |
| 914 // The RFC says the sort order for the domain attribute is undefined. | 938 // The RFC says the sort order for the domain attribute is undefined. |
| 915 static bool CookieSorter(CookieMonster::CanonicalCookie* cc1, | 939 static bool CookieSorter(CookieMonster::CanonicalCookie* cc1, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 989 if ((*it)->Name() != cookie_name) | 1013 if ((*it)->Name() != cookie_name) |
| 990 continue; | 1014 continue; |
| 991 if (url.path().find((*it)->Path())) | 1015 if (url.path().find((*it)->Path())) |
| 992 continue; | 1016 continue; |
| 993 matching_cookies.insert(*it); | 1017 matching_cookies.insert(*it); |
| 994 } | 1018 } |
| 995 | 1019 |
| 996 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) { | 1020 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) { |
| 997 CookieMap::iterator curit = it; | 1021 CookieMap::iterator curit = it; |
| 998 ++it; | 1022 ++it; |
| 999 if (matching_cookies.find(curit->second) != matching_cookies.end()) | 1023 if (matching_cookies.find(curit->second) != matching_cookies.end()) { |
| 1000 InternalDeleteCookie(curit, true); | 1024 InternalDeleteCookie(curit, true, kDeleteCookieExplicit); |
| 1025 } |
| 1001 } | 1026 } |
| 1002 } | 1027 } |
| 1003 | 1028 |
| 1004 CookieMonster::CookieList CookieMonster::GetAllCookies() { | 1029 CookieMonster::CookieList CookieMonster::GetAllCookies() { |
| 1005 AutoLock autolock(lock_); | 1030 AutoLock autolock(lock_); |
| 1006 InitIfNecessary(); | 1031 InitIfNecessary(); |
| 1007 | 1032 |
| 1008 // This function is being called to scrape the cookie list for management UI | 1033 // This function is being called to scrape the cookie list for management UI |
| 1009 // or similar. We shouldn't show expired cookies in this list since it will | 1034 // or similar. We shouldn't show expired cookies in this list since it will |
| 1010 // just be confusing to users, and this function is called rarely enough (and | 1035 // just be confusing to users, and this function is called rarely enough (and |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1032 } | 1057 } |
| 1033 | 1058 |
| 1034 void CookieMonster::FindCookiesForHostAndDomain( | 1059 void CookieMonster::FindCookiesForHostAndDomain( |
| 1035 const GURL& url, | 1060 const GURL& url, |
| 1036 const CookieOptions& options, | 1061 const CookieOptions& options, |
| 1037 std::vector<CanonicalCookie*>* cookies) { | 1062 std::vector<CanonicalCookie*>* cookies) { |
| 1038 lock_.AssertAcquired(); | 1063 lock_.AssertAcquired(); |
| 1039 | 1064 |
| 1040 const Time current_time(CurrentTime()); | 1065 const Time current_time(CurrentTime()); |
| 1041 | 1066 |
| 1067 // Probe to save statistics relatively frequently. We do it here rather |
| 1068 // than in the set path as many websites won't set cookies, and we |
| 1069 // want to collect statistics whenever the browser's being used. |
| 1070 RecordPeriodicStats(current_time); |
| 1071 |
| 1042 // Query for the full host, For example: 'a.c.blah.com'. | 1072 // Query for the full host, For example: 'a.c.blah.com'. |
| 1043 std::string key(url.host()); | 1073 std::string key(url.host()); |
| 1044 FindCookiesForKey(key, url, options, current_time, cookies); | 1074 FindCookiesForKey(key, url, options, current_time, cookies); |
| 1045 | 1075 |
| 1046 // See if we can search for domain cookies, i.e. if the host has a TLD + 1. | 1076 // See if we can search for domain cookies, i.e. if the host has a TLD + 1. |
| 1047 const std::string domain(GetEffectiveDomain(url.scheme(), key)); | 1077 const std::string domain(GetEffectiveDomain(url.scheme(), key)); |
| 1048 if (domain.empty()) | 1078 if (domain.empty()) |
| 1049 return; | 1079 return; |
| 1050 DCHECK_LE(domain.length(), key.length()); | 1080 DCHECK_LE(domain.length(), key.length()); |
| 1051 DCHECK_EQ(0, key.compare(key.length() - domain.length(), domain.length(), | 1081 DCHECK_EQ(0, key.compare(key.length() - domain.length(), domain.length(), |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1074 bool secure = url.SchemeIsSecure(); | 1104 bool secure = url.SchemeIsSecure(); |
| 1075 | 1105 |
| 1076 for (CookieMapItPair its = cookies_.equal_range(key); | 1106 for (CookieMapItPair its = cookies_.equal_range(key); |
| 1077 its.first != its.second; ) { | 1107 its.first != its.second; ) { |
| 1078 CookieMap::iterator curit = its.first; | 1108 CookieMap::iterator curit = its.first; |
| 1079 CanonicalCookie* cc = curit->second; | 1109 CanonicalCookie* cc = curit->second; |
| 1080 ++its.first; | 1110 ++its.first; |
| 1081 | 1111 |
| 1082 // If the cookie is expired, delete it. | 1112 // If the cookie is expired, delete it. |
| 1083 if (cc->IsExpired(current)) { | 1113 if (cc->IsExpired(current)) { |
| 1084 InternalDeleteCookie(curit, true); | 1114 InternalDeleteCookie(curit, true, kDeleteCookieExpired); |
| 1085 continue; | 1115 continue; |
| 1086 } | 1116 } |
| 1087 | 1117 |
| 1088 // Filter out HttpOnly cookies, per options. | 1118 // Filter out HttpOnly cookies, per options. |
| 1089 if (options.exclude_httponly() && cc->IsHttpOnly()) | 1119 if (options.exclude_httponly() && cc->IsHttpOnly()) |
| 1090 continue; | 1120 continue; |
| 1091 | 1121 |
| 1092 // Filter out secure cookies unless we're https. | 1122 // Filter out secure cookies unless we're https. |
| 1093 if (!secure && cc->IsSecure()) | 1123 if (!secure && cc->IsSecure()) |
| 1094 continue; | 1124 continue; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1149 DCHECK_EQ(0, key.compare(key.length() - domain.length(), domain.length(), | 1179 DCHECK_EQ(0, key.compare(key.length() - domain.length(), domain.length(), |
| 1150 domain)); | 1180 domain)); |
| 1151 for (key = "." + key; key.length() > domain.length(); ) { | 1181 for (key = "." + key; key.length() > domain.length(); ) { |
| 1152 FindRawCookies(key, secure, url.path(), &cookie_list); | 1182 FindRawCookies(key, secure, url.path(), &cookie_list); |
| 1153 const size_t next_dot = key.find('.', 1); // Skip over leading dot. | 1183 const size_t next_dot = key.find('.', 1); // Skip over leading dot. |
| 1154 key.erase(0, next_dot); | 1184 key.erase(0, next_dot); |
| 1155 } | 1185 } |
| 1156 return cookie_list; | 1186 return cookie_list; |
| 1157 } | 1187 } |
| 1158 | 1188 |
| 1189 // Test to see if stats should be recorded, and record them if so. |
| 1190 // The goal here is to get sampling for the average browser-hour of |
| 1191 // activity. We won't take samples when the web isn't being surfed, |
| 1192 // and when the web is being surfed, we'll take samples about every |
| 1193 // kRecordStatisticsIntervalSeconds. |
| 1194 // last_statistic_record_time_ is initialized to Now() rather than null |
| 1195 // in the constructor so that we won't take statistics right after |
| 1196 // startup, to avoid bias from browsers that are started but not used. |
| 1197 void CookieMonster::RecordPeriodicStats(const base::Time ¤t_time) { |
| 1198 const base::TimeDelta kRecordStatisticsIntervalTime( |
| 1199 base::TimeDelta::FromSeconds(kRecordStatisticsIntervalSeconds)); |
| 1200 |
| 1201 if (current_time - last_statistic_record_time_ > |
| 1202 kRecordStatisticsIntervalTime) { |
| 1203 UMA_HISTOGRAM_CUSTOM_COUNTS("net.CookieCount", cookies_.size(), |
| 1204 1, 4000, 50); |
| 1205 last_statistic_record_time_ = current_time; |
| 1206 } |
| 1207 } |
| 1208 |
| 1159 CookieMonster::ParsedCookie::ParsedCookie(const std::string& cookie_line) | 1209 CookieMonster::ParsedCookie::ParsedCookie(const std::string& cookie_line) |
| 1160 : is_valid_(false), | 1210 : is_valid_(false), |
| 1161 path_index_(0), | 1211 path_index_(0), |
| 1162 domain_index_(0), | 1212 domain_index_(0), |
| 1163 expires_index_(0), | 1213 expires_index_(0), |
| 1164 maxage_index_(0), | 1214 maxage_index_(0), |
| 1165 secure_index_(0), | 1215 secure_index_(0), |
| 1166 httponly_index_(0) { | 1216 httponly_index_(0) { |
| 1167 | 1217 |
| 1168 if (cookie_line.size() > kMaxCookieSize) { | 1218 if (cookie_line.size() > kMaxCookieSize) { |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1515 return true; | 1565 return true; |
| 1516 } | 1566 } |
| 1517 | 1567 |
| 1518 std::string CookieMonster::CanonicalCookie::DebugString() const { | 1568 std::string CookieMonster::CanonicalCookie::DebugString() const { |
| 1519 return StringPrintf("name: %s value: %s path: %s creation: %" PRId64, | 1569 return StringPrintf("name: %s value: %s path: %s creation: %" PRId64, |
| 1520 name_.c_str(), value_.c_str(), path_.c_str(), | 1570 name_.c_str(), value_.c_str(), path_.c_str(), |
| 1521 static_cast<int64>(creation_date_.ToTimeT())); | 1571 static_cast<int64>(creation_date_.ToTimeT())); |
| 1522 } | 1572 } |
| 1523 | 1573 |
| 1524 } // namespace | 1574 } // namespace |
| OLD | NEW |