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