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