schemeful_site.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef NET_BASE_SCHEMEFUL_SITE_H_
  5. #define NET_BASE_SCHEMEFUL_SITE_H_
  6. #include <ostream>
  7. #include <string>
  8. #include "base/gtest_prod_util.h"
  9. #include "net/base/net_export.h"
  10. #include "third_party/abseil-cpp/absl/types/optional.h"
  11. #include "url/origin.h"
  12. class GURL;
  13. namespace blink {
  14. class BlinkSchemefulSite;
  15. } // namespace blink
  16. namespace IPC {
  17. template <class P>
  18. struct ParamTraits;
  19. } // namespace IPC
  20. namespace network::mojom {
  21. class SchemefulSiteDataView;
  22. } // namespace network::mojom
  23. namespace mojo {
  24. template <typename DataViewType, typename T>
  25. struct StructTraits;
  26. } // namespace mojo
  27. namespace net {
  28. class SiteForCookies;
  29. // Class which represents a scheme and etld+1 for an origin, as specified by
  30. // https://html.spec.whatwg.org/multipage/origin.html#obtain-a-site.
  31. //
  32. // A SchemefulSite is obtained from an input origin by normalizing, such that:
  33. // 1. Opaque origins have distinct SchemefulSites.
  34. // 2. Origins whose schemes have network hosts have the same SchemefulSite iff
  35. // they share a scheme, and share a hostname or registrable domain. Origins
  36. // whose schemes have network hosts include http, https, ws, wss, file, etc.
  37. // 3. Origins whose schemes do not have a network host have the same
  38. // SchemefulSite iff they share a scheme and host.
  39. // 4. Origins which differ only by port have the same SchemefulSite.
  40. // 5. Websocket origins cannot have a SchemefulSite (they trigger a DCHECK).
  41. //
  42. // Note that blink::BlinkSchemefulSite mirrors this class and needs to be kept
  43. // in sync with any data member changes.
  44. class NET_EXPORT SchemefulSite {
  45. public:
  46. SchemefulSite() = default;
  47. // The passed `origin` may not match the resulting internal representation in
  48. // certain circumstances. See the comment, below, on the `site_as_origin_`
  49. // member.
  50. explicit SchemefulSite(const url::Origin& origin);
  51. // Using the origin constructor is preferred as this is less efficient.
  52. // Should only be used if the origin for a given GURL is not readily
  53. // available.
  54. explicit SchemefulSite(const GURL& url);
  55. SchemefulSite(const SchemefulSite& other);
  56. SchemefulSite(SchemefulSite&& other) noexcept;
  57. SchemefulSite& operator=(const SchemefulSite& other);
  58. SchemefulSite& operator=(SchemefulSite&& other) noexcept;
  59. // Tries to construct an instance from a (potentially untrusted) value of the
  60. // internal `site_as_origin_` that got received over an RPC.
  61. //
  62. // Returns whether successful or not. Doesn't touch |*out| if false is
  63. // returned. This returning |true| does not mean that whoever sent the values
  64. // did not lie, merely that they are well-formed.
  65. static bool FromWire(const url::Origin& site_as_origin, SchemefulSite* out);
  66. // Creates a SchemefulSite iff the passed-in origin has a registerable domain.
  67. static absl::optional<SchemefulSite> CreateIfHasRegisterableDomain(
  68. const url::Origin&);
  69. // If the scheme is ws or wss, it is converted to http or https, respectively.
  70. // Has no effect on SchemefulSites with any other schemes.
  71. //
  72. // See Step 1 of algorithm "establish a WebSocket connection" in
  73. // https://fetch.spec.whatwg.org/#websocket-opening-handshake.
  74. void ConvertWebSocketToHttp();
  75. // Deserializes a string obtained from `Serialize()` to a `SchemefulSite`.
  76. // Returns an opaque `SchemefulSite` if the value was invalid in any way.
  77. static SchemefulSite Deserialize(const std::string& value);
  78. // Returns a serialized version of `site_as_origin_`. If the underlying origin
  79. // is invalid, returns an empty string. If serialization of opaque origins
  80. // with their associated nonce is necessary, see `SerializeWithNonce()`.
  81. std::string Serialize() const;
  82. // Serializes `site_as_origin_` in cases when it has a 'file' scheme but
  83. // we want to preserve the Origin's host.
  84. // This was added to serialize cookie partition keys, which may contain
  85. // file origins with a host.
  86. std::string SerializeFileSiteWithHost() const;
  87. std::string GetDebugString() const;
  88. // Gets the underlying site as a GURL. If the internal Origin is opaque,
  89. // returns an empty GURL.
  90. GURL GetURL() const;
  91. bool opaque() const { return site_as_origin_.opaque(); }
  92. bool has_registrable_domain_or_host() const {
  93. return !registrable_domain_or_host().empty();
  94. }
  95. // Testing only function which allows tests to access the underlying
  96. // `site_as_origin_` in order to verify behavior.
  97. const url::Origin& GetInternalOriginForTesting() const;
  98. // Testing-only function which allows access to the private
  99. // `registrable_domain_or_host` method.
  100. std::string registrable_domain_or_host_for_testing() const {
  101. return registrable_domain_or_host();
  102. }
  103. bool operator==(const SchemefulSite& other) const;
  104. bool operator!=(const SchemefulSite& other) const;
  105. bool operator<(const SchemefulSite& other) const;
  106. private:
  107. // IPC serialization code needs to access internal origin.
  108. friend struct mojo::StructTraits<network::mojom::SchemefulSiteDataView,
  109. SchemefulSite>;
  110. friend struct IPC::ParamTraits<net::SchemefulSite>;
  111. friend class blink::BlinkSchemefulSite;
  112. // Create SiteForCookies from SchemefulSite needs to access internal origin,
  113. // and SiteForCookies needs to access private method SchemelesslyEqual.
  114. friend class SiteForCookies;
  115. // Needed to serialize opaque and non-transient NetworkIsolationKeys, which
  116. // use opaque origins.
  117. friend class NetworkIsolationKey;
  118. // Needed to create a bogus origin from a site.
  119. // TODO(https://crbug.com/1148927): Give IsolationInfos empty origins instead,
  120. // in this case, and unfriend IsolationInfo.
  121. friend class IsolationInfo;
  122. // Needed because cookies do not account for scheme.
  123. friend class CookieMonster;
  124. FRIEND_TEST_ALL_PREFIXES(SchemefulSiteTest, OpaqueSerialization);
  125. struct ObtainASiteResult {
  126. url::Origin origin;
  127. bool used_registerable_domain;
  128. };
  129. static ObtainASiteResult ObtainASite(const url::Origin&);
  130. explicit SchemefulSite(ObtainASiteResult);
  131. // Deserializes a string obtained from `SerializeWithNonce()` to a
  132. // `SchemefulSite`. Returns nullopt if the value was invalid in any way.
  133. static absl::optional<SchemefulSite> DeserializeWithNonce(
  134. const std::string& value);
  135. // Returns a serialized version of `site_as_origin_`. For an opaque
  136. // `site_as_origin_`, this serializes with the nonce. See
  137. // `url::origin::SerializeWithNonce()` for usage information.
  138. absl::optional<std::string> SerializeWithNonce();
  139. // Returns whether `this` and `other` share a host or registrable domain.
  140. // Should NOT be used to check equality or equivalence. This is only used
  141. // for legacy same-site cookie logic that does not check schemes. Private to
  142. // restrict usage.
  143. bool SchemelesslyEqual(const SchemefulSite& other) const;
  144. // Returns the host of the underlying `origin`, which will usually be the
  145. // registrable domain. This is private because if it were public, it would
  146. // trivially allow circumvention of the "Schemeful"-ness of this class.
  147. // However, the CookieMonster currently needs access to this, since it ignores
  148. // the schemes of domains.
  149. std::string registrable_domain_or_host() const {
  150. return site_as_origin_.host();
  151. }
  152. // Origin which stores the result of running the steps documented at
  153. // https://html.spec.whatwg.org/multipage/origin.html#obtain-a-site.
  154. // This is not an arbitrary origin. It must either be an opaque origin, or a
  155. // scheme + eTLD+1 + default port.
  156. //
  157. // The `origin` passed into the SchemefulSite(const url::Origin&) constructor
  158. // might not match this internal representation used by this class to track
  159. // the scheme and eTLD+1 representing a schemeful site. This may be the case
  160. // if, e.g., the passed `origin` has an eTLD+1 that is not equal to its
  161. // hostname, or if the port number is not the default port for its scheme.
  162. //
  163. // In general, this `site_as_origin_` used for the internal representation
  164. // should NOT be used directly by SchemefulSite consumers.
  165. url::Origin site_as_origin_;
  166. };
  167. // Provided to allow gtest to create more helpful error messages, instead of
  168. // printing hex.
  169. //
  170. // Also used so that SchemefulSites can be the arguments of DCHECK_EQ.
  171. NET_EXPORT std::ostream& operator<<(std::ostream& os, const SchemefulSite& ss);
  172. } // namespace net
  173. #endif // NET_BASE_SCHEMEFUL_SITE_H_