| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NET_COOKIES_CANONICAL_COOKIE_H_ |
| #define NET_COOKIES_CANONICAL_COOKIE_H_ |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/gtest_prod_util.h" |
| #include "base/time/time.h" |
| #include "net/base/net_export.h" |
| #include "net/cookies/cookie_constants.h" |
| #include "net/cookies/cookie_options.h" |
| |
| class GURL; |
| |
| namespace net { |
| |
| class ParsedCookie; |
| |
| class NET_EXPORT CanonicalCookie { |
| public: |
| // These constructors do no validation or canonicalization of their inputs; |
| // the resulting CanonicalCookies should not be relied on to be canonical |
| // unless the caller has done appropriate validation and canonicalization |
| // themselves. |
| CanonicalCookie(); |
| CanonicalCookie(const GURL& url, |
| const std::string& name, |
| const std::string& value, |
| const std::string& domain, |
| const std::string& path, |
| const base::Time& creation, |
| const base::Time& expiration, |
| const base::Time& last_access, |
| bool secure, |
| bool httponly, |
| CookieSameSite same_site, |
| CookiePriority priority); |
| |
| CanonicalCookie(const CanonicalCookie& other); |
| |
| ~CanonicalCookie(); |
| |
| // Supports the default copy constructor. |
| |
| // Creates a new |CanonicalCookie| from the |cookie_line| and the |
| // |creation_time|. Canonicalizes and validates inputs. May return NULL if |
| // an attribute value is invalid. |
| static std::unique_ptr<CanonicalCookie> Create( |
| const GURL& url, |
| const std::string& cookie_line, |
| const base::Time& creation_time, |
| const CookieOptions& options); |
| |
| // Creates a canonical cookie from unparsed attribute values. |
| // Canonicalizes and validates inputs. May return NULL if an attribute |
| // value is invalid. |
| static std::unique_ptr<CanonicalCookie> Create(const GURL& url, |
| const std::string& name, |
| const std::string& value, |
| const std::string& domain, |
| const std::string& path, |
| const base::Time& creation, |
| const base::Time& expiration, |
| bool secure, |
| bool http_only, |
| CookieSameSite same_site, |
| bool enforce_strict_secure, |
| CookiePriority priority); |
| |
| // Creates a canonical cookie from unparsed attribute values. |
| // It does not do any validation. |
| static std::unique_ptr<CanonicalCookie> Create(const std::string& name, |
| const std::string& value, |
| const std::string& domain, |
| const std::string& path, |
| const base::Time& creation, |
| const base::Time& expiration, |
| const base::Time& last_access, |
| bool secure, |
| bool http_only, |
| CookieSameSite same_site, |
| CookiePriority priority); |
| |
| const GURL& Source() const { return source_; } |
| const std::string& Name() const { return name_; } |
| const std::string& Value() const { return value_; } |
| const std::string& Domain() const { return domain_; } |
| const std::string& Path() const { return path_; } |
| const base::Time& CreationDate() const { return creation_date_; } |
| const base::Time& LastAccessDate() const { return last_access_date_; } |
| bool IsPersistent() const { return !expiry_date_.is_null(); } |
| const base::Time& ExpiryDate() const { return expiry_date_; } |
| bool IsSecure() const { return secure_; } |
| bool IsHttpOnly() const { return httponly_; } |
| CookieSameSite SameSite() const { return same_site_; } |
| CookiePriority Priority() const { return priority_; } |
| bool IsDomainCookie() const { |
| return !domain_.empty() && domain_[0] == '.'; } |
| bool IsHostCookie() const { return !IsDomainCookie(); } |
| |
| bool IsExpired(const base::Time& current) const { |
| return !expiry_date_.is_null() && current >= expiry_date_; |
| } |
| |
| // Are the cookies considered equivalent in the eyes of RFC 2965. |
| // The RFC says that name must match (case-sensitive), domain must |
| // match (case insensitive), and path must match (case sensitive). |
| // For the case insensitive domain compare, we rely on the domain |
| // having been canonicalized (in |
| // GetCookieDomainWithString->CanonicalizeHost). |
| bool IsEquivalent(const CanonicalCookie& ecc) const { |
| // It seems like it would make sense to take secure and httponly into |
| // account, but the RFC doesn't specify this. |
| // NOTE: Keep this logic in-sync with TrimDuplicateCookiesForHost(). |
| return (name_ == ecc.Name() && domain_ == ecc.Domain() |
| && path_ == ecc.Path()); |
| } |
| |
| // Checks if two cookies have the same name and domain-match per RFC 6265. |
| // Note that this purposefully ignores paths, and that this function is |
| // guaranteed to return |true| for a superset of the inputs that |
| // IsEquivalent() above returns |true| for. |
| // |
| // This is needed for the updates to RFC6265 as per |
| // https://tools.ietf.org/html/draft-west-leave-secure-cookies-alone. |
| bool IsEquivalentForSecureCookieMatching(const CanonicalCookie& ecc) const { |
| return (name_ == ecc.Name() && (ecc.IsDomainMatch(Source().host()) || |
| IsDomainMatch(ecc.Source().host()))); |
| } |
| |
| void SetLastAccessDate(const base::Time& date) { |
| last_access_date_ = date; |
| } |
| |
| // Returns true if the given |url_path| path-matches the cookie-path as |
| // described in section 5.1.4 in RFC 6265. |
| bool IsOnPath(const std::string& url_path) const; |
| |
| // Returns true if the cookie domain matches the given |host| as described in |
| // section 5.1.3 of RFC 6265. |
| bool IsDomainMatch(const std::string& host) const; |
| |
| // Returns true if the cookie should be included for the given request |url|. |
| // HTTP only cookies can be filter by using appropriate cookie |options|. |
| // PLEASE NOTE that this method does not check whether a cookie is expired or |
| // not! |
| bool IncludeForRequestURL(const GURL& url, |
| const CookieOptions& options) const; |
| |
| std::string DebugString() const; |
| |
| static std::string CanonPath(const GURL& url, const ParsedCookie& pc); |
| static base::Time CanonExpiration(const ParsedCookie& pc, |
| const base::Time& current, |
| const base::Time& server_time); |
| |
| // Cookie ordering methods. |
| |
| // Returns true if the cookie is less than |other|, considering only name, |
| // domain and path. In particular, two equivalent cookies (see IsEquivalent()) |
| // are identical for PartialCompare(). |
| bool PartialCompare(const CanonicalCookie& other) const; |
| |
| // Returns true if the cookie is less than |other|, considering all fields. |
| // FullCompare() is consistent with PartialCompare(): cookies sorted using |
| // FullCompare() are also sorted with respect to PartialCompare(). |
| bool FullCompare(const CanonicalCookie& other) const; |
| |
| private: |
| FRIEND_TEST_ALL_PREFIXES(CanonicalCookieTest, TestPrefixHistograms); |
| |
| // The special cookie prefixes as defined in |
| // https://tools.ietf.org/html/draft-west-cookie-prefixes |
| // |
| // This enum is being histogrammed; do not reorder or remove values. |
| enum CookiePrefix { |
| COOKIE_PREFIX_NONE = 0, |
| COOKIE_PREFIX_SECURE, |
| COOKIE_PREFIX_HOST, |
| COOKIE_PREFIX_LAST |
| }; |
| |
| // Returns the CookiePrefix (or COOKIE_PREFIX_NONE if none) that |
| // applies to the given cookie |name|. |
| static CookiePrefix GetCookiePrefix(const std::string& name); |
| // Records histograms to measure how often cookie prefixes appear in |
| // the wild and how often they would be blocked. |
| static void RecordCookiePrefixMetrics(CookiePrefix prefix, |
| bool is_cookie_valid); |
| // Returns true if a prefixed cookie does not violate any of the rules |
| // for that cookie. |
| static bool IsCookiePrefixValid(CookiePrefix prefix, |
| const GURL& url, |
| const ParsedCookie& parsed_cookie); |
| |
| // The source member of a canonical cookie is the origin of the URL that tried |
| // to set this cookie. This field is not persistent though; its only used in |
| // the in-tab cookies dialog to show the user the source URL. This is used for |
| // both allowed and blocked cookies. |
| // When a CanonicalCookie is constructed from the backing store (common case) |
| // this field will be null. CanonicalCookie consumers should not rely on |
| // this field unless they guarantee that the creator of those |
| // CanonicalCookies properly initialized the field. |
| GURL source_; |
| std::string name_; |
| std::string value_; |
| std::string domain_; |
| std::string path_; |
| base::Time creation_date_; |
| base::Time expiry_date_; |
| base::Time last_access_date_; |
| bool secure_; |
| bool httponly_; |
| CookieSameSite same_site_; |
| CookiePriority priority_; |
| }; |
| |
| typedef std::vector<CanonicalCookie> CookieList; |
| |
| } // namespace net |
| |
| #endif // NET_COOKIES_CANONICAL_COOKIE_H_ |