schemeful_site.cc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. #include "net/base/schemeful_site.h"
  5. #include "base/check.h"
  6. #include "base/metrics/histogram_macros.h"
  7. #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
  8. #include "net/base/url_util.h"
  9. #include "url/gurl.h"
  10. #include "url/url_canon.h"
  11. #include "url/url_constants.h"
  12. namespace net {
  13. // Return a tuple containing:
  14. // * a new origin using the registerable domain of `origin` if possible and
  15. // a port of 0; otherwise, the passed-in origin.
  16. // * a bool indicating whether `origin` had a non-null registerable domain.
  17. // (False if `origin` was opaque.)
  18. //
  19. // Follows steps specified in
  20. // https://html.spec.whatwg.org/multipage/origin.html#obtain-a-site
  21. SchemefulSite::ObtainASiteResult SchemefulSite::ObtainASite(
  22. const url::Origin& origin) {
  23. // 1. If origin is an opaque origin, then return origin.
  24. if (origin.opaque())
  25. return {origin, false /* used_registerable_domain */};
  26. std::string registerable_domain;
  27. // Non-normative step.
  28. // We only lookup the registerable domain for schemes with network hosts, this
  29. // is non-normative. Other schemes for non-opaque origins do not
  30. // meaningfully have a registerable domain for their host, so they are
  31. // skipped.
  32. if (IsStandardSchemeWithNetworkHost(origin.scheme())) {
  33. registerable_domain = GetDomainAndRegistry(
  34. origin, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
  35. }
  36. // If origin's host's registrable domain is null, then return (origin's
  37. // scheme, origin's host).
  38. //
  39. // `GetDomainAndRegistry()` returns an empty string for IP literals and
  40. // effective TLDs.
  41. //
  42. // Note that `registerable_domain` could still end up empty, since the
  43. // `origin` might have a scheme that permits empty hostnames, such as "file".
  44. bool used_registerable_domain = !registerable_domain.empty();
  45. if (!used_registerable_domain)
  46. registerable_domain = origin.host();
  47. int port = url::DefaultPortForScheme(origin.scheme().c_str(),
  48. origin.scheme().length());
  49. // Provide a default port of 0 for non-standard schemes.
  50. if (port == url::PORT_UNSPECIFIED)
  51. port = 0;
  52. return {url::Origin::CreateFromNormalizedTuple(origin.scheme(),
  53. registerable_domain, port),
  54. used_registerable_domain};
  55. }
  56. SchemefulSite::SchemefulSite(ObtainASiteResult result)
  57. : site_as_origin_(std::move(result.origin)) {}
  58. SchemefulSite::SchemefulSite(const url::Origin& origin)
  59. : SchemefulSite(ObtainASite(origin)) {}
  60. SchemefulSite::SchemefulSite(const GURL& url)
  61. : SchemefulSite(url::Origin::Create(url)) {}
  62. SchemefulSite::SchemefulSite(const SchemefulSite& other) = default;
  63. SchemefulSite::SchemefulSite(SchemefulSite&& other) noexcept = default;
  64. SchemefulSite& SchemefulSite::operator=(const SchemefulSite& other) = default;
  65. SchemefulSite& SchemefulSite::operator=(SchemefulSite&& other) noexcept =
  66. default;
  67. // static
  68. bool SchemefulSite::FromWire(const url::Origin& site_as_origin,
  69. SchemefulSite* out) {
  70. // The origin passed into this constructor may not match the
  71. // `site_as_origin_` used as the internal representation of the schemeful
  72. // site. However, a valid SchemefulSite's internal origin should result in a
  73. // match if used to construct another SchemefulSite. Thus, if there is a
  74. // mismatch here, we must indicate a failure.
  75. SchemefulSite candidate(site_as_origin);
  76. if (candidate.site_as_origin_ != site_as_origin)
  77. return false;
  78. *out = std::move(candidate);
  79. return true;
  80. }
  81. absl::optional<SchemefulSite> SchemefulSite::CreateIfHasRegisterableDomain(
  82. const url::Origin& origin) {
  83. ObtainASiteResult result = ObtainASite(origin);
  84. if (!result.used_registerable_domain)
  85. return absl::nullopt;
  86. return SchemefulSite(std::move(result));
  87. }
  88. void SchemefulSite::ConvertWebSocketToHttp() {
  89. if (site_as_origin_.scheme() == url::kWsScheme ||
  90. site_as_origin_.scheme() == url::kWssScheme) {
  91. site_as_origin_ = url::Origin::Create(
  92. ChangeWebSocketSchemeToHttpScheme(site_as_origin_.GetURL()));
  93. }
  94. }
  95. // static
  96. SchemefulSite SchemefulSite::Deserialize(const std::string& value) {
  97. return SchemefulSite(GURL(value));
  98. }
  99. std::string SchemefulSite::Serialize() const {
  100. return site_as_origin_.Serialize();
  101. }
  102. std::string SchemefulSite::SerializeFileSiteWithHost() const {
  103. DCHECK_EQ(url::kFileScheme, site_as_origin_.scheme());
  104. return site_as_origin_.GetTupleOrPrecursorTupleIfOpaque().Serialize();
  105. }
  106. std::string SchemefulSite::GetDebugString() const {
  107. return site_as_origin_.GetDebugString();
  108. }
  109. GURL SchemefulSite::GetURL() const {
  110. return site_as_origin_.GetURL();
  111. }
  112. const url::Origin& SchemefulSite::GetInternalOriginForTesting() const {
  113. return site_as_origin_;
  114. }
  115. bool SchemefulSite::operator==(const SchemefulSite& other) const {
  116. return site_as_origin_ == other.site_as_origin_;
  117. }
  118. bool SchemefulSite::operator!=(const SchemefulSite& other) const {
  119. return !(*this == other);
  120. }
  121. // Allows SchemefulSite to be used as a key in STL containers (for example, a
  122. // std::set or std::map).
  123. bool SchemefulSite::operator<(const SchemefulSite& other) const {
  124. return site_as_origin_ < other.site_as_origin_;
  125. }
  126. // static
  127. absl::optional<SchemefulSite> SchemefulSite::DeserializeWithNonce(
  128. const std::string& value) {
  129. absl::optional<url::Origin> result = url::Origin::Deserialize(value);
  130. if (!result)
  131. return absl::nullopt;
  132. return SchemefulSite(result.value());
  133. }
  134. absl::optional<std::string> SchemefulSite::SerializeWithNonce() {
  135. return site_as_origin_.SerializeWithNonceAndInitIfNeeded();
  136. }
  137. bool SchemefulSite::SchemelesslyEqual(const SchemefulSite& other) const {
  138. return site_as_origin_.host() == other.site_as_origin_.host();
  139. }
  140. std::ostream& operator<<(std::ostream& os, const SchemefulSite& ss) {
  141. os << ss.Serialize();
  142. return os;
  143. }
  144. } // namespace net