| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // Brought to you by the letter D and the number 2. | 5 // Brought to you by the letter D and the number 2. |
| 6 | 6 |
| 7 #ifndef NET_COOKIES_COOKIE_MONSTER_H_ | 7 #ifndef NET_COOKIES_COOKIE_MONSTER_H_ |
| 8 #define NET_COOKIES_COOKIE_MONSTER_H_ | 8 #define NET_COOKIES_COOKIE_MONSTER_H_ |
| 9 | 9 |
| 10 #include <deque> | 10 #include <deque> |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 | 27 |
| 28 class GURL; | 28 class GURL; |
| 29 | 29 |
| 30 namespace base { | 30 namespace base { |
| 31 class Histogram; | 31 class Histogram; |
| 32 class TimeTicks; | 32 class TimeTicks; |
| 33 } // namespace base | 33 } // namespace base |
| 34 | 34 |
| 35 namespace net { | 35 namespace net { |
| 36 | 36 |
| 37 class CanonicalCookie; |
| 37 class CookieList; | 38 class CookieList; |
| 38 class ParsedCookie; | 39 class ParsedCookie; |
| 39 | 40 |
| 40 // The cookie monster is the system for storing and retrieving cookies. It has | 41 // The cookie monster is the system for storing and retrieving cookies. It has |
| 41 // an in-memory list of all cookies, and synchronizes non-session cookies to an | 42 // an in-memory list of all cookies, and synchronizes non-session cookies to an |
| 42 // optional permanent storage that implements the PersistentCookieStore | 43 // optional permanent storage that implements the PersistentCookieStore |
| 43 // interface. | 44 // interface. |
| 44 // | 45 // |
| 45 // This class IS thread-safe. Normally, it is only used on the I/O thread, but | 46 // This class IS thread-safe. Normally, it is only used on the I/O thread, but |
| 46 // is also accessed directly through Automation for UI testing. | 47 // is also accessed directly through Automation for UI testing. |
| 47 // | 48 // |
| 48 // All cookie tasks are handled asynchronously. Tasks may be deferred if | 49 // All cookie tasks are handled asynchronously. Tasks may be deferred if |
| 49 // all affected cookies are not yet loaded from the backing store. Otherwise, | 50 // all affected cookies are not yet loaded from the backing store. Otherwise, |
| 50 // the callback may be invoked immediately (prior to return of the asynchronous | 51 // the callback may be invoked immediately (prior to return of the asynchronous |
| 51 // function). | 52 // function). |
| 52 // | 53 // |
| 53 // A cookie task is either pending loading of the entire cookie store, or | 54 // A cookie task is either pending loading of the entire cookie store, or |
| 54 // loading of cookies for a specfic domain key(eTLD+1). In the former case, the | 55 // loading of cookies for a specfic domain key(eTLD+1). In the former case, the |
| 55 // cookie task will be queued in queue_ while PersistentCookieStore chain loads | 56 // cookie task will be queued in queue_ while PersistentCookieStore chain loads |
| 56 // the cookie store on DB thread. In the latter case, the cookie task will be | 57 // the cookie store on DB thread. In the latter case, the cookie task will be |
| 57 // queued in tasks_queued_ while PermanentCookieStore loads cookies for the | 58 // queued in tasks_queued_ while PermanentCookieStore loads cookies for the |
| 58 // specified domain key(eTLD+1) on DB thread. | 59 // specified domain key(eTLD+1) on DB thread. |
| 59 // | 60 // |
| 60 // Callbacks are guaranteed to be invoked on the calling thread. | 61 // Callbacks are guaranteed to be invoked on the calling thread. |
| 61 // | 62 // |
| 62 // TODO(deanm) Implement CookieMonster, the cookie database. | 63 // TODO(deanm) Implement CookieMonster, the cookie database. |
| 63 // - Verify that our domain enforcement and non-dotted handling is correct | 64 // - Verify that our domain enforcement and non-dotted handling is correct |
| 64 class NET_EXPORT CookieMonster : public CookieStore { | 65 class NET_EXPORT CookieMonster : public CookieStore { |
| 65 public: | 66 public: |
| 66 class CanonicalCookie; | |
| 67 class Delegate; | 67 class Delegate; |
| 68 class PersistentCookieStore; | 68 class PersistentCookieStore; |
| 69 | 69 |
| 70 // Terminology: | 70 // Terminology: |
| 71 // * The 'top level domain' (TLD) of an internet domain name is | 71 // * The 'top level domain' (TLD) of an internet domain name is |
| 72 // the terminal "." free substring (e.g. "com" for google.com | 72 // the terminal "." free substring (e.g. "com" for google.com |
| 73 // or world.std.com). | 73 // or world.std.com). |
| 74 // * The 'effective top level domain' (eTLD) is the longest | 74 // * The 'effective top level domain' (eTLD) is the longest |
| 75 // "." initiated terminal substring of an internet domain name | 75 // "." initiated terminal substring of an internet domain name |
| 76 // that is controlled by a general domain registrar. | 76 // that is controlled by a general domain registrar. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 // monster's existence. If |store| is NULL, then no backing store will be | 112 // monster's existence. If |store| is NULL, then no backing store will be |
| 113 // updated. If |delegate| is non-NULL, it will be notified on | 113 // updated. If |delegate| is non-NULL, it will be notified on |
| 114 // creation/deletion of cookies. | 114 // creation/deletion of cookies. |
| 115 CookieMonster(PersistentCookieStore* store, Delegate* delegate); | 115 CookieMonster(PersistentCookieStore* store, Delegate* delegate); |
| 116 | 116 |
| 117 // Only used during unit testing. | 117 // Only used during unit testing. |
| 118 CookieMonster(PersistentCookieStore* store, | 118 CookieMonster(PersistentCookieStore* store, |
| 119 Delegate* delegate, | 119 Delegate* delegate, |
| 120 int last_access_threshold_milliseconds); | 120 int last_access_threshold_milliseconds); |
| 121 | 121 |
| 122 // Parses the string with the cookie time (very forgivingly). | |
| 123 static base::Time ParseCookieTime(const std::string& time_string); | |
| 124 | |
| 125 // Helper function that adds all cookies from |list| into this instance. | 122 // Helper function that adds all cookies from |list| into this instance. |
| 126 bool InitializeFrom(const CookieList& list); | 123 bool InitializeFrom(const CookieList& list); |
| 127 | 124 |
| 128 typedef base::Callback<void(const CookieList& cookies)> GetCookieListCallback; | 125 typedef base::Callback<void(const CookieList& cookies)> GetCookieListCallback; |
| 129 typedef base::Callback<void(bool success)> DeleteCookieCallback; | 126 typedef base::Callback<void(bool success)> DeleteCookieCallback; |
| 130 | 127 |
| 131 // Sets a cookie given explicit user-provided cookie attributes. The cookie | 128 // Sets a cookie given explicit user-provided cookie attributes. The cookie |
| 132 // name, value, domain, etc. are each provided as separate strings. This | 129 // name, value, domain, etc. are each provided as separate strings. This |
| 133 // function expects each attribute to be well-formed. It will check for | 130 // function expects each attribute to be well-formed. It will check for |
| 134 // disallowed characters (e.g. the ';' character is disallowed within the | 131 // disallowed characters (e.g. the ';' character is disallowed within the |
| (...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 bool persist_session_cookies_; | 650 bool persist_session_cookies_; |
| 654 | 651 |
| 655 // Static setting for whether or not file scheme cookies are allows when | 652 // Static setting for whether or not file scheme cookies are allows when |
| 656 // a new CookieMonster is created, or the accepted schemes on a CookieMonster | 653 // a new CookieMonster is created, or the accepted schemes on a CookieMonster |
| 657 // instance are reset back to defaults. | 654 // instance are reset back to defaults. |
| 658 static bool default_enable_file_scheme_; | 655 static bool default_enable_file_scheme_; |
| 659 | 656 |
| 660 DISALLOW_COPY_AND_ASSIGN(CookieMonster); | 657 DISALLOW_COPY_AND_ASSIGN(CookieMonster); |
| 661 }; | 658 }; |
| 662 | 659 |
| 663 class NET_EXPORT CookieMonster::CanonicalCookie { | |
| 664 public: | |
| 665 | |
| 666 // These constructors do no validation or canonicalization of their inputs; | |
| 667 // the resulting CanonicalCookies should not be relied on to be canonical | |
| 668 // unless the caller has done appropriate validation and canonicalization | |
| 669 // themselves. | |
| 670 CanonicalCookie(); | |
| 671 CanonicalCookie(const GURL& url, | |
| 672 const std::string& name, | |
| 673 const std::string& value, | |
| 674 const std::string& domain, | |
| 675 const std::string& path, | |
| 676 const std::string& mac_key, | |
| 677 const std::string& mac_algorithm, | |
| 678 const base::Time& creation, | |
| 679 const base::Time& expiration, | |
| 680 const base::Time& last_access, | |
| 681 bool secure, | |
| 682 bool httponly); | |
| 683 | |
| 684 // This constructor does canonicalization but not validation. | |
| 685 // The result of this constructor should not be relied on in contexts | |
| 686 // in which pre-validation of the ParsedCookie has not been done. | |
| 687 CanonicalCookie(const GURL& url, const ParsedCookie& pc); | |
| 688 | |
| 689 ~CanonicalCookie(); | |
| 690 | |
| 691 // Supports the default copy constructor. | |
| 692 | |
| 693 // Creates a canonical cookie from parsed cookie. | |
| 694 // Canonicalizes and validates inputs. May return NULL if an attribute | |
| 695 // value is invalid. | |
| 696 static CanonicalCookie* Create(const GURL& url, | |
| 697 const ParsedCookie& pc); | |
| 698 | |
| 699 // Creates a canonical cookie from unparsed attribute values. | |
| 700 // Canonicalizes and validates inputs. May return NULL if an attribute | |
| 701 // value is invalid. | |
| 702 static CanonicalCookie* Create(const GURL& url, | |
| 703 const std::string& name, | |
| 704 const std::string& value, | |
| 705 const std::string& domain, | |
| 706 const std::string& path, | |
| 707 const std::string& mac_key, | |
| 708 const std::string& mac_algorithm, | |
| 709 const base::Time& creation, | |
| 710 const base::Time& expiration, | |
| 711 bool secure, | |
| 712 bool http_only); | |
| 713 | |
| 714 const std::string& Source() const { return source_; } | |
| 715 const std::string& Name() const { return name_; } | |
| 716 const std::string& Value() const { return value_; } | |
| 717 const std::string& Domain() const { return domain_; } | |
| 718 const std::string& Path() const { return path_; } | |
| 719 const std::string& MACKey() const { return mac_key_; } | |
| 720 const std::string& MACAlgorithm() const { return mac_algorithm_; } | |
| 721 const base::Time& CreationDate() const { return creation_date_; } | |
| 722 const base::Time& LastAccessDate() const { return last_access_date_; } | |
| 723 bool IsPersistent() const { return !expiry_date_.is_null(); } | |
| 724 const base::Time& ExpiryDate() const { return expiry_date_; } | |
| 725 bool IsSecure() const { return secure_; } | |
| 726 bool IsHttpOnly() const { return httponly_; } | |
| 727 bool IsDomainCookie() const { | |
| 728 return !domain_.empty() && domain_[0] == '.'; } | |
| 729 bool IsHostCookie() const { return !IsDomainCookie(); } | |
| 730 | |
| 731 bool IsExpired(const base::Time& current) { | |
| 732 return !expiry_date_.is_null() && current >= expiry_date_; | |
| 733 } | |
| 734 | |
| 735 // Are the cookies considered equivalent in the eyes of RFC 2965. | |
| 736 // The RFC says that name must match (case-sensitive), domain must | |
| 737 // match (case insensitive), and path must match (case sensitive). | |
| 738 // For the case insensitive domain compare, we rely on the domain | |
| 739 // having been canonicalized (in | |
| 740 // GetCookieDomainWithString->CanonicalizeHost). | |
| 741 bool IsEquivalent(const CanonicalCookie& ecc) const { | |
| 742 // It seems like it would make sense to take secure and httponly into | |
| 743 // account, but the RFC doesn't specify this. | |
| 744 // NOTE: Keep this logic in-sync with TrimDuplicateCookiesForHost(). | |
| 745 return (name_ == ecc.Name() && domain_ == ecc.Domain() | |
| 746 && path_ == ecc.Path()); | |
| 747 } | |
| 748 | |
| 749 void SetLastAccessDate(const base::Time& date) { | |
| 750 last_access_date_ = date; | |
| 751 } | |
| 752 | |
| 753 bool IsOnPath(const std::string& url_path) const; | |
| 754 bool IsDomainMatch(const std::string& scheme, const std::string& host) const; | |
| 755 | |
| 756 std::string DebugString() const; | |
| 757 | |
| 758 // Returns the cookie source when cookies are set for |url|. This function | |
| 759 // is public for unit test purposes only. | |
| 760 static std::string GetCookieSourceFromURL(const GURL& url); | |
| 761 | |
| 762 private: | |
| 763 // Gives the session cookie an expiration time if needed | |
| 764 void SetSessionCookieExpiryTime(); | |
| 765 | |
| 766 // The source member of a canonical cookie is the origin of the URL that tried | |
| 767 // to set this cookie, minus the port number if any. This field is not | |
| 768 // persistent though; its only used in the in-tab cookies dialog to show the | |
| 769 // user the source URL. This is used for both allowed and blocked cookies. | |
| 770 // When a CanonicalCookie is constructed from the backing store (common case) | |
| 771 // this field will be null. CanonicalCookie consumers should not rely on | |
| 772 // this field unless they guarantee that the creator of those | |
| 773 // CanonicalCookies properly initialized the field. | |
| 774 // TODO(abarth): We might need to make this field persistent for MAC cookies. | |
| 775 std::string source_; | |
| 776 std::string name_; | |
| 777 std::string value_; | |
| 778 std::string domain_; | |
| 779 std::string path_; | |
| 780 std::string mac_key_; // TODO(abarth): Persist to disk. | |
| 781 std::string mac_algorithm_; // TODO(abarth): Persist to disk. | |
| 782 base::Time creation_date_; | |
| 783 base::Time expiry_date_; | |
| 784 base::Time last_access_date_; | |
| 785 bool secure_; | |
| 786 bool httponly_; | |
| 787 }; | |
| 788 | |
| 789 class CookieMonster::Delegate | 660 class CookieMonster::Delegate |
| 790 : public base::RefCountedThreadSafe<CookieMonster::Delegate> { | 661 : public base::RefCountedThreadSafe<CookieMonster::Delegate> { |
| 791 public: | 662 public: |
| 792 // The publicly relevant reasons a cookie might be changed. | 663 // The publicly relevant reasons a cookie might be changed. |
| 793 enum ChangeCause { | 664 enum ChangeCause { |
| 794 // The cookie was changed directly by a consumer's action. | 665 // The cookie was changed directly by a consumer's action. |
| 795 CHANGE_COOKIE_EXPLICIT, | 666 CHANGE_COOKIE_EXPLICIT, |
| 796 // The cookie was automatically removed due to an insert operation that | 667 // The cookie was automatically removed due to an insert operation that |
| 797 // overwrote it. | 668 // overwrote it. |
| 798 CHANGE_COOKIE_OVERWRITE, | 669 CHANGE_COOKIE_OVERWRITE, |
| 799 // The cookie was automatically removed as it expired. | 670 // The cookie was automatically removed as it expired. |
| 800 CHANGE_COOKIE_EXPIRED, | 671 CHANGE_COOKIE_EXPIRED, |
| 801 // The cookie was automatically evicted during garbage collection. | 672 // The cookie was automatically evicted during garbage collection. |
| 802 CHANGE_COOKIE_EVICTED, | 673 CHANGE_COOKIE_EVICTED, |
| 803 // The cookie was overwritten with an already-expired expiration date. | 674 // The cookie was overwritten with an already-expired expiration date. |
| 804 CHANGE_COOKIE_EXPIRED_OVERWRITE | 675 CHANGE_COOKIE_EXPIRED_OVERWRITE |
| 805 }; | 676 }; |
| 806 | 677 |
| 807 // Will be called when a cookie is added or removed. The function is passed | 678 // Will be called when a cookie is added or removed. The function is passed |
| 808 // the respective |cookie| which was added to or removed from the cookies. | 679 // the respective |cookie| which was added to or removed from the cookies. |
| 809 // If |removed| is true, the cookie was deleted, and |cause| will be set | 680 // If |removed| is true, the cookie was deleted, and |cause| will be set |
| 810 // to the reason for its removal. If |removed| is false, the cookie was | 681 // to the reason for its removal. If |removed| is false, the cookie was |
| 811 // added, and |cause| will be set to CHANGE_COOKIE_EXPLICIT. | 682 // added, and |cause| will be set to CHANGE_COOKIE_EXPLICIT. |
| 812 // | 683 // |
| 813 // As a special case, note that updating a cookie's properties is implemented | 684 // As a special case, note that updating a cookie's properties is implemented |
| 814 // as a two step process: the cookie to be updated is first removed entirely, | 685 // as a two step process: the cookie to be updated is first removed entirely, |
| 815 // generating a notification with cause CHANGE_COOKIE_OVERWRITE. Afterwards, | 686 // generating a notification with cause CHANGE_COOKIE_OVERWRITE. Afterwards, |
| 816 // a new cookie is written with the updated values, generating a notification | 687 // a new cookie is written with the updated values, generating a notification |
| 817 // with cause CHANGE_COOKIE_EXPLICIT. | 688 // with cause CHANGE_COOKIE_EXPLICIT. |
| 818 virtual void OnCookieChanged(const CookieMonster::CanonicalCookie& cookie, | 689 virtual void OnCookieChanged(const CanonicalCookie& cookie, |
| 819 bool removed, | 690 bool removed, |
| 820 ChangeCause cause) = 0; | 691 ChangeCause cause) = 0; |
| 821 protected: | 692 protected: |
| 822 friend class base::RefCountedThreadSafe<CookieMonster::Delegate>; | 693 friend class base::RefCountedThreadSafe<CookieMonster::Delegate>; |
| 823 virtual ~Delegate() {} | 694 virtual ~Delegate() {} |
| 824 }; | 695 }; |
| 825 | 696 |
| 826 typedef base::RefCountedThreadSafe<CookieMonster::PersistentCookieStore> | 697 typedef base::RefCountedThreadSafe<CookieMonster::PersistentCookieStore> |
| 827 RefcountedPersistentCookieStore; | 698 RefcountedPersistentCookieStore; |
| 828 | 699 |
| 829 class CookieMonster::PersistentCookieStore | 700 class CookieMonster::PersistentCookieStore |
| 830 : public RefcountedPersistentCookieStore { | 701 : public RefcountedPersistentCookieStore { |
| 831 public: | 702 public: |
| 832 typedef base::Callback<void(const std::vector< | 703 typedef base::Callback<void(const std::vector<CanonicalCookie*>&)> |
| 833 CookieMonster::CanonicalCookie*>&)> LoadedCallback; | 704 LoadedCallback; |
| 834 | 705 |
| 835 // Initializes the store and retrieves the existing cookies. This will be | 706 // Initializes the store and retrieves the existing cookies. This will be |
| 836 // called only once at startup. The callback will return all the cookies | 707 // called only once at startup. The callback will return all the cookies |
| 837 // that are not yet returned to CookieMonster by previous priority loads. | 708 // that are not yet returned to CookieMonster by previous priority loads. |
| 838 virtual void Load(const LoadedCallback& loaded_callback) = 0; | 709 virtual void Load(const LoadedCallback& loaded_callback) = 0; |
| 839 | 710 |
| 840 // Does a priority load of all cookies for the domain key (eTLD+1). The | 711 // Does a priority load of all cookies for the domain key (eTLD+1). The |
| 841 // callback will return all the cookies that are not yet returned by previous | 712 // callback will return all the cookies that are not yet returned by previous |
| 842 // loads, which includes cookies for the requested domain key if they are not | 713 // loads, which includes cookies for the requested domain key if they are not |
| 843 // already returned, plus all cookies that are chain-loaded and not yet | 714 // already returned, plus all cookies that are chain-loaded and not yet |
| (...skipping 13 matching lines...) Expand all Loading... |
| 857 | 728 |
| 858 protected: | 729 protected: |
| 859 PersistentCookieStore() {} | 730 PersistentCookieStore() {} |
| 860 virtual ~PersistentCookieStore() {} | 731 virtual ~PersistentCookieStore() {} |
| 861 | 732 |
| 862 private: | 733 private: |
| 863 friend class base::RefCountedThreadSafe<PersistentCookieStore>; | 734 friend class base::RefCountedThreadSafe<PersistentCookieStore>; |
| 864 DISALLOW_COPY_AND_ASSIGN(PersistentCookieStore); | 735 DISALLOW_COPY_AND_ASSIGN(PersistentCookieStore); |
| 865 }; | 736 }; |
| 866 | 737 |
| 867 class CookieList : public std::vector<CookieMonster::CanonicalCookie> { | |
| 868 }; | |
| 869 | |
| 870 } // namespace net | 738 } // namespace net |
| 871 | 739 |
| 872 #endif // NET_COOKIES_COOKIE_MONSTER_H_ | 740 #endif // NET_COOKIES_COOKIE_MONSTER_H_ |
| OLD | NEW |