xref: /aosp_15_r20/external/cronet/net/base/schemeful_site.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/base/schemeful_site.h"
6 
7 #include "base/check.h"
8 #include "base/metrics/histogram_macros.h"
9 #include "base/trace_event/memory_usage_estimator.h"
10 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
11 #include "net/base/url_util.h"
12 #include "url/gurl.h"
13 #include "url/url_canon.h"
14 #include "url/url_constants.h"
15 
16 namespace net {
17 
18 // Return a tuple containing:
19 // * a new origin using the registerable domain of `origin` if possible and
20 //   a port of 0; otherwise, the passed-in origin.
21 // * a bool indicating whether `origin` had a non-null registerable domain.
22 //   (False if `origin` was opaque.)
23 //
24 // Follows steps specified in
25 // https://html.spec.whatwg.org/multipage/origin.html#obtain-a-site
ObtainASite(const url::Origin & origin)26 SchemefulSite::ObtainASiteResult SchemefulSite::ObtainASite(
27     const url::Origin& origin) {
28   // 1. If origin is an opaque origin, then return origin.
29   if (origin.opaque())
30     return {origin, false /* used_registerable_domain */};
31 
32   std::string registerable_domain;
33 
34   // Non-normative step.
35   // We only lookup the registerable domain for schemes with network hosts, this
36   // is non-normative. Other schemes for non-opaque origins do not
37   // meaningfully have a registerable domain for their host, so they are
38   // skipped.
39   if (IsStandardSchemeWithNetworkHost(origin.scheme())) {
40     registerable_domain = GetDomainAndRegistry(
41         origin, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
42   }
43 
44   // If origin's host's registrable domain is null, then return (origin's
45   // scheme, origin's host).
46   //
47   // `GetDomainAndRegistry()` returns an empty string for IP literals and
48   // effective TLDs.
49   //
50   // Note that `registerable_domain` could still end up empty, since the
51   // `origin` might have a scheme that permits empty hostnames, such as "file".
52   bool used_registerable_domain = !registerable_domain.empty();
53   if (!used_registerable_domain)
54     registerable_domain = origin.host();
55 
56   int port = url::DefaultPortForScheme(origin.scheme().c_str(),
57                                        origin.scheme().length());
58 
59   // Provide a default port of 0 for non-standard schemes.
60   if (port == url::PORT_UNSPECIFIED)
61     port = 0;
62 
63   return {url::Origin::CreateFromNormalizedTuple(origin.scheme(),
64                                                  registerable_domain, port),
65           used_registerable_domain};
66 }
67 
SchemefulSite(ObtainASiteResult result)68 SchemefulSite::SchemefulSite(ObtainASiteResult result)
69     : site_as_origin_(std::move(result.origin)) {}
70 
SchemefulSite(const url::Origin & origin)71 SchemefulSite::SchemefulSite(const url::Origin& origin)
72     : SchemefulSite(ObtainASite(origin)) {}
73 
SchemefulSite(const GURL & url)74 SchemefulSite::SchemefulSite(const GURL& url)
75     : SchemefulSite(url::Origin::Create(url)) {}
76 
77 SchemefulSite::SchemefulSite(const SchemefulSite& other) = default;
78 SchemefulSite::SchemefulSite(SchemefulSite&& other) noexcept = default;
79 
80 SchemefulSite& SchemefulSite::operator=(const SchemefulSite& other) = default;
81 SchemefulSite& SchemefulSite::operator=(SchemefulSite&& other) noexcept =
82     default;
83 
84 // static
FromWire(const url::Origin & site_as_origin,SchemefulSite * out)85 bool SchemefulSite::FromWire(const url::Origin& site_as_origin,
86                              SchemefulSite* out) {
87   // The origin passed into this constructor may not match the
88   // `site_as_origin_` used as the internal representation of the schemeful
89   // site. However, a valid SchemefulSite's internal origin should result in a
90   // match if used to construct another SchemefulSite. Thus, if there is a
91   // mismatch here, we must indicate a failure.
92   SchemefulSite candidate(site_as_origin);
93   if (candidate.site_as_origin_ != site_as_origin)
94     return false;
95 
96   *out = std::move(candidate);
97   return true;
98 }
99 
CreateIfHasRegisterableDomain(const url::Origin & origin)100 std::optional<SchemefulSite> SchemefulSite::CreateIfHasRegisterableDomain(
101     const url::Origin& origin) {
102   ObtainASiteResult result = ObtainASite(origin);
103   if (!result.used_registerable_domain)
104     return std::nullopt;
105   return SchemefulSite(std::move(result));
106 }
107 
ConvertWebSocketToHttp()108 void SchemefulSite::ConvertWebSocketToHttp() {
109   if (site_as_origin_.scheme() == url::kWsScheme ||
110       site_as_origin_.scheme() == url::kWssScheme) {
111     site_as_origin_ = url::Origin::Create(
112         ChangeWebSocketSchemeToHttpScheme(site_as_origin_.GetURL()));
113   }
114 }
115 
116 // static
Deserialize(const std::string & value)117 SchemefulSite SchemefulSite::Deserialize(const std::string& value) {
118   return SchemefulSite(GURL(value));
119 }
120 
Serialize() const121 std::string SchemefulSite::Serialize() const {
122   return site_as_origin_.Serialize();
123 }
124 
SerializeFileSiteWithHost() const125 std::string SchemefulSite::SerializeFileSiteWithHost() const {
126   DCHECK_EQ(url::kFileScheme, site_as_origin_.scheme());
127   return site_as_origin_.GetTupleOrPrecursorTupleIfOpaque().Serialize();
128 }
129 
GetDebugString() const130 std::string SchemefulSite::GetDebugString() const {
131   return site_as_origin_.GetDebugString();
132 }
133 
GetURL() const134 GURL SchemefulSite::GetURL() const {
135   return site_as_origin_.GetURL();
136 }
137 
GetInternalOriginForTesting() const138 const url::Origin& SchemefulSite::GetInternalOriginForTesting() const {
139   return site_as_origin_;
140 }
141 
EstimateMemoryUsage() const142 size_t SchemefulSite::EstimateMemoryUsage() const {
143   return base::trace_event::EstimateMemoryUsage(site_as_origin_);
144 }
145 
operator ==(const SchemefulSite & other) const146 bool SchemefulSite::operator==(const SchemefulSite& other) const {
147   return site_as_origin_ == other.site_as_origin_;
148 }
149 
operator !=(const SchemefulSite & other) const150 bool SchemefulSite::operator!=(const SchemefulSite& other) const {
151   return !(*this == other);
152 }
153 
154 // Allows SchemefulSite to be used as a key in STL containers (for example, a
155 // std::set or std::map).
operator <(const SchemefulSite & other) const156 bool SchemefulSite::operator<(const SchemefulSite& other) const {
157   return site_as_origin_ < other.site_as_origin_;
158 }
159 
160 // static
DeserializeWithNonce(base::PassKey<NetworkAnonymizationKey>,const std::string & value)161 std::optional<SchemefulSite> SchemefulSite::DeserializeWithNonce(
162     base::PassKey<NetworkAnonymizationKey>,
163     const std::string& value) {
164   return DeserializeWithNonce(value);
165 }
166 
167 // static
DeserializeWithNonce(const std::string & value)168 std::optional<SchemefulSite> SchemefulSite::DeserializeWithNonce(
169     const std::string& value) {
170   std::optional<url::Origin> result = url::Origin::Deserialize(value);
171   if (!result)
172     return std::nullopt;
173   return SchemefulSite(result.value());
174 }
175 
SerializeWithNonce(base::PassKey<NetworkAnonymizationKey>)176 std::optional<std::string> SchemefulSite::SerializeWithNonce(
177     base::PassKey<NetworkAnonymizationKey>) {
178   return SerializeWithNonce();
179 }
180 
SerializeWithNonce()181 std::optional<std::string> SchemefulSite::SerializeWithNonce() {
182   return site_as_origin_.SerializeWithNonceAndInitIfNeeded();
183 }
184 
SchemelesslyEqual(const SchemefulSite & other) const185 bool SchemefulSite::SchemelesslyEqual(const SchemefulSite& other) const {
186   return site_as_origin_.host() == other.site_as_origin_.host();
187 }
188 
operator <<(std::ostream & os,const SchemefulSite & ss)189 std::ostream& operator<<(std::ostream& os, const SchemefulSite& ss) {
190   os << ss.Serialize();
191   return os;
192 }
193 
194 }  // namespace net
195