| // 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 <tuple> | 
 | #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: | 
 |   CanonicalCookie(); | 
 |   CanonicalCookie(const CanonicalCookie& other); | 
 |  | 
 |   // This constructor does not validate or canonicalize their inputs; | 
 |   // the resulting CanonicalCookies should not be relied on to be canonical | 
 |   // unless the caller has done appropriate validation and canonicalization | 
 |   // themselves. | 
 |   CanonicalCookie(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(); | 
 |  | 
 |   // 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.  |creation_time| may not be null. | 
 |   static std::unique_ptr<CanonicalCookie> Create( | 
 |       const GURL& url, | 
 |       const std::string& cookie_line, | 
 |       const base::Time& creation_time, | 
 |       const CookieOptions& options); | 
 |  | 
 |   // Create a canonical cookie based on sanitizing the passed inputs in the | 
 |   // context of the passed URL.  Returns a null unique pointer if the inputs | 
 |   // cannot be sanitized.  If a cookie is created, |cookie->IsCanonical()| | 
 |   // will be true. | 
 |   static std::unique_ptr<CanonicalCookie> CreateSanitizedCookie( | 
 |       const GURL& url, | 
 |       const std::string& name, | 
 |       const std::string& value, | 
 |       const std::string& domain, | 
 |       const std::string& path, | 
 |       base::Time creation_time, | 
 |       base::Time expiration_time, | 
 |       base::Time last_access_time, | 
 |       bool secure, | 
 |       bool http_only, | 
 |       CookieSameSite same_site, | 
 |       CookiePriority priority); | 
 |  | 
 |   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()); | 
 |   } | 
 |  | 
 |   // Returns a key such that two cookies with the same UniqueKey() are | 
 |   // guaranteed to be equivalent in the sense of IsEquivalent(). | 
 |   std::tuple<std::string, std::string, std::string> UniqueKey() const { | 
 |     return std::make_tuple(name_, domain_, path_); | 
 |   } | 
 |  | 
 |   // Checks a looser set of equivalency rules than 'IsEquivalent()' in order | 
 |   // to support the stricter 'Secure' behaviors specified in | 
 |   // https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone#section-3 | 
 |   // | 
 |   // Returns 'true' if this cookie's name matches |ecc|, and this cookie is | 
 |   // a domain-match for |ecc| (or vice versa), and |ecc|'s path is "on" this | 
 |   // cookie's path (as per 'IsOnPath()'). | 
 |   // | 
 |   // Note that while the domain-match cuts both ways (e.g. 'example.com' | 
 |   // matches 'www.example.com' in either direction), the path-match is | 
 |   // unidirectional (e.g. '/login/en' matches '/login' and '/', but | 
 |   // '/login' and '/' do not match '/login/en'). | 
 |   bool IsEquivalentForSecureCookieMatching(const CanonicalCookie& ecc) const; | 
 |  | 
 |   void SetLastAccessDate(const base::Time& date) { | 
 |     last_access_date_ = date; | 
 |   } | 
 |   void SetCreationDate(const base::Time& date) { creation_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 CanonPathWithString(const GURL& url, | 
 |                                          const std::string& path_string); | 
 |  | 
 |   // Returns a "null" time if expiration was unspecified or invalid. | 
 |   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; | 
 |  | 
 |   // Return whether this object is a valid CanonicalCookie().  Invalid | 
 |   // cookies may be constructed by the detailed constructor. | 
 |   // A cookie is considered canonical if-and-only-if: | 
 |   // * It can be created by CanonicalCookie::Create, or | 
 |   // * It is identical to a cookie created by CanonicalCookie::Create except | 
 |   //   that the creation time is null, or | 
 |   // * It can be derived from a cookie created by CanonicalCookie::Create by | 
 |   //   entry into and retrieval from a cookie store (specifically, this means | 
 |   //   by the setting of an creation time in place of a null creation time, and | 
 |   //   the setting of a last access time). | 
 |   // An additional requirement on a CanonicalCookie is that if the last | 
 |   // access time is non-null, the creation time must also be non-null and | 
 |   // greater than the last access time. | 
 |   bool IsCanonical() const; | 
 |  | 
 |   // Returns the cookie line (e.g. "cookie1=value1; cookie2=value2") represented | 
 |   // by |cookies|. The string is built in the same order as the given list. | 
 |   static std::string BuildCookieLine( | 
 |       const std::vector<CanonicalCookie>& cookies); | 
 |  | 
 |  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); | 
 |  | 
 |   // Returns the cookie's domain, with the leading dot removed, if present. | 
 |   std::string DomainWithoutDot() const; | 
 |  | 
 |   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_ |