xref: /aosp_15_r20/external/cronet/url/origin.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2015 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 "url/origin.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <algorithm>
10*6777b538SAndroid Build Coastguard Worker #include <ostream>
11*6777b538SAndroid Build Coastguard Worker #include <string>
12*6777b538SAndroid Build Coastguard Worker #include <string_view>
13*6777b538SAndroid Build Coastguard Worker #include <tuple>
14*6777b538SAndroid Build Coastguard Worker #include <utility>
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker #include "base/base64.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/containers/contains.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/debug/crash_logging.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/pickle.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/strings/strcat.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/base_tracing.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/memory_usage_estimator.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/unguessable_token.h"
27*6777b538SAndroid Build Coastguard Worker #include "url/gurl.h"
28*6777b538SAndroid Build Coastguard Worker #include "url/scheme_host_port.h"
29*6777b538SAndroid Build Coastguard Worker #include "url/url_constants.h"
30*6777b538SAndroid Build Coastguard Worker #include "url/url_features.h"
31*6777b538SAndroid Build Coastguard Worker #include "url/url_util.h"
32*6777b538SAndroid Build Coastguard Worker 
33*6777b538SAndroid Build Coastguard Worker namespace url {
34*6777b538SAndroid Build Coastguard Worker 
Origin()35*6777b538SAndroid Build Coastguard Worker Origin::Origin() : nonce_(Nonce()) {}
36*6777b538SAndroid Build Coastguard Worker 
Create(const GURL & url)37*6777b538SAndroid Build Coastguard Worker Origin Origin::Create(const GURL& url) {
38*6777b538SAndroid Build Coastguard Worker   if (!url.is_valid())
39*6777b538SAndroid Build Coastguard Worker     return Origin();
40*6777b538SAndroid Build Coastguard Worker 
41*6777b538SAndroid Build Coastguard Worker   SchemeHostPort tuple;
42*6777b538SAndroid Build Coastguard Worker 
43*6777b538SAndroid Build Coastguard Worker   if (url.SchemeIsFileSystem()) {
44*6777b538SAndroid Build Coastguard Worker     tuple = SchemeHostPort(*url.inner_url());
45*6777b538SAndroid Build Coastguard Worker   } else if (url.SchemeIsBlob()) {
46*6777b538SAndroid Build Coastguard Worker     // If we're dealing with a 'blob:' URL, https://url.spec.whatwg.org/#origin
47*6777b538SAndroid Build Coastguard Worker     // defines the origin as the origin of the URL which results from parsing
48*6777b538SAndroid Build Coastguard Worker     // the "path", which boils down to everything after the scheme. GURL's
49*6777b538SAndroid Build Coastguard Worker     // 'GetContent()' gives us exactly that.
50*6777b538SAndroid Build Coastguard Worker     tuple = SchemeHostPort(GURL(url.GetContent()));
51*6777b538SAndroid Build Coastguard Worker   } else {
52*6777b538SAndroid Build Coastguard Worker     tuple = SchemeHostPort(url);
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker     // It's SchemeHostPort's responsibility to filter out unrecognized schemes;
55*6777b538SAndroid Build Coastguard Worker     // sanity check that this is happening.
56*6777b538SAndroid Build Coastguard Worker     DCHECK(!tuple.IsValid() || url.IsStandard() ||
57*6777b538SAndroid Build Coastguard Worker            base::Contains(GetLocalSchemes(), url.scheme_piece()) ||
58*6777b538SAndroid Build Coastguard Worker            AllowNonStandardSchemesForAndroidWebView());
59*6777b538SAndroid Build Coastguard Worker   }
60*6777b538SAndroid Build Coastguard Worker 
61*6777b538SAndroid Build Coastguard Worker   if (!tuple.IsValid())
62*6777b538SAndroid Build Coastguard Worker     return Origin();
63*6777b538SAndroid Build Coastguard Worker   return Origin(std::move(tuple));
64*6777b538SAndroid Build Coastguard Worker }
65*6777b538SAndroid Build Coastguard Worker 
Resolve(const GURL & url,const Origin & base_origin)66*6777b538SAndroid Build Coastguard Worker Origin Origin::Resolve(const GURL& url, const Origin& base_origin) {
67*6777b538SAndroid Build Coastguard Worker   if (url.SchemeIs(kAboutScheme) || url.is_empty())
68*6777b538SAndroid Build Coastguard Worker     return base_origin;
69*6777b538SAndroid Build Coastguard Worker   Origin result = Origin::Create(url);
70*6777b538SAndroid Build Coastguard Worker   if (!result.opaque())
71*6777b538SAndroid Build Coastguard Worker     return result;
72*6777b538SAndroid Build Coastguard Worker   return base_origin.DeriveNewOpaqueOrigin();
73*6777b538SAndroid Build Coastguard Worker }
74*6777b538SAndroid Build Coastguard Worker 
75*6777b538SAndroid Build Coastguard Worker Origin::Origin(const Origin&) = default;
76*6777b538SAndroid Build Coastguard Worker Origin& Origin::operator=(const Origin&) = default;
77*6777b538SAndroid Build Coastguard Worker Origin::Origin(Origin&&) noexcept = default;
78*6777b538SAndroid Build Coastguard Worker Origin& Origin::operator=(Origin&&) noexcept = default;
79*6777b538SAndroid Build Coastguard Worker Origin::~Origin() = default;
80*6777b538SAndroid Build Coastguard Worker 
81*6777b538SAndroid Build Coastguard Worker // static
UnsafelyCreateTupleOriginWithoutNormalization(std::string_view scheme,std::string_view host,uint16_t port)82*6777b538SAndroid Build Coastguard Worker std::optional<Origin> Origin::UnsafelyCreateTupleOriginWithoutNormalization(
83*6777b538SAndroid Build Coastguard Worker     std::string_view scheme,
84*6777b538SAndroid Build Coastguard Worker     std::string_view host,
85*6777b538SAndroid Build Coastguard Worker     uint16_t port) {
86*6777b538SAndroid Build Coastguard Worker   SchemeHostPort tuple(std::string(scheme), std::string(host), port,
87*6777b538SAndroid Build Coastguard Worker                        SchemeHostPort::CHECK_CANONICALIZATION);
88*6777b538SAndroid Build Coastguard Worker   if (!tuple.IsValid())
89*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
90*6777b538SAndroid Build Coastguard Worker   return Origin(std::move(tuple));
91*6777b538SAndroid Build Coastguard Worker }
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker // static
UnsafelyCreateOpaqueOriginWithoutNormalization(std::string_view precursor_scheme,std::string_view precursor_host,uint16_t precursor_port,const Origin::Nonce & nonce)94*6777b538SAndroid Build Coastguard Worker std::optional<Origin> Origin::UnsafelyCreateOpaqueOriginWithoutNormalization(
95*6777b538SAndroid Build Coastguard Worker     std::string_view precursor_scheme,
96*6777b538SAndroid Build Coastguard Worker     std::string_view precursor_host,
97*6777b538SAndroid Build Coastguard Worker     uint16_t precursor_port,
98*6777b538SAndroid Build Coastguard Worker     const Origin::Nonce& nonce) {
99*6777b538SAndroid Build Coastguard Worker   SchemeHostPort precursor(std::string(precursor_scheme),
100*6777b538SAndroid Build Coastguard Worker                            std::string(precursor_host), precursor_port,
101*6777b538SAndroid Build Coastguard Worker                            SchemeHostPort::CHECK_CANONICALIZATION);
102*6777b538SAndroid Build Coastguard Worker   // For opaque origins, it is okay for the SchemeHostPort to be invalid;
103*6777b538SAndroid Build Coastguard Worker   // however, this should only arise when the arguments indicate the
104*6777b538SAndroid Build Coastguard Worker   // canonical representation of the invalid SchemeHostPort.
105*6777b538SAndroid Build Coastguard Worker   if (!precursor.IsValid() &&
106*6777b538SAndroid Build Coastguard Worker       !(precursor_scheme.empty() && precursor_host.empty() &&
107*6777b538SAndroid Build Coastguard Worker         precursor_port == 0)) {
108*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
109*6777b538SAndroid Build Coastguard Worker   }
110*6777b538SAndroid Build Coastguard Worker   return Origin(std::move(nonce), std::move(precursor));
111*6777b538SAndroid Build Coastguard Worker }
112*6777b538SAndroid Build Coastguard Worker 
113*6777b538SAndroid Build Coastguard Worker // static
CreateFromNormalizedTuple(std::string scheme,std::string host,uint16_t port)114*6777b538SAndroid Build Coastguard Worker Origin Origin::CreateFromNormalizedTuple(std::string scheme,
115*6777b538SAndroid Build Coastguard Worker                                          std::string host,
116*6777b538SAndroid Build Coastguard Worker                                          uint16_t port) {
117*6777b538SAndroid Build Coastguard Worker   SchemeHostPort tuple(std::move(scheme), std::move(host), port,
118*6777b538SAndroid Build Coastguard Worker                        SchemeHostPort::ALREADY_CANONICALIZED);
119*6777b538SAndroid Build Coastguard Worker   if (!tuple.IsValid())
120*6777b538SAndroid Build Coastguard Worker     return Origin();
121*6777b538SAndroid Build Coastguard Worker   return Origin(std::move(tuple));
122*6777b538SAndroid Build Coastguard Worker }
123*6777b538SAndroid Build Coastguard Worker 
124*6777b538SAndroid Build Coastguard Worker // static
CreateOpaqueFromNormalizedPrecursorTuple(std::string precursor_scheme,std::string precursor_host,uint16_t precursor_port,const Origin::Nonce & nonce)125*6777b538SAndroid Build Coastguard Worker Origin Origin::CreateOpaqueFromNormalizedPrecursorTuple(
126*6777b538SAndroid Build Coastguard Worker     std::string precursor_scheme,
127*6777b538SAndroid Build Coastguard Worker     std::string precursor_host,
128*6777b538SAndroid Build Coastguard Worker     uint16_t precursor_port,
129*6777b538SAndroid Build Coastguard Worker     const Origin::Nonce& nonce) {
130*6777b538SAndroid Build Coastguard Worker   SchemeHostPort precursor(std::move(precursor_scheme),
131*6777b538SAndroid Build Coastguard Worker                            std::move(precursor_host), precursor_port,
132*6777b538SAndroid Build Coastguard Worker                            SchemeHostPort::ALREADY_CANONICALIZED);
133*6777b538SAndroid Build Coastguard Worker   // For opaque origins, it is okay for the SchemeHostPort to be invalid.
134*6777b538SAndroid Build Coastguard Worker   return Origin(std::move(nonce), std::move(precursor));
135*6777b538SAndroid Build Coastguard Worker }
136*6777b538SAndroid Build Coastguard Worker 
Serialize() const137*6777b538SAndroid Build Coastguard Worker std::string Origin::Serialize() const {
138*6777b538SAndroid Build Coastguard Worker   if (opaque())
139*6777b538SAndroid Build Coastguard Worker     return "null";
140*6777b538SAndroid Build Coastguard Worker 
141*6777b538SAndroid Build Coastguard Worker   if (scheme() == kFileScheme)
142*6777b538SAndroid Build Coastguard Worker     return "file://";
143*6777b538SAndroid Build Coastguard Worker 
144*6777b538SAndroid Build Coastguard Worker   return tuple_.Serialize();
145*6777b538SAndroid Build Coastguard Worker }
146*6777b538SAndroid Build Coastguard Worker 
GetURL() const147*6777b538SAndroid Build Coastguard Worker GURL Origin::GetURL() const {
148*6777b538SAndroid Build Coastguard Worker   if (opaque())
149*6777b538SAndroid Build Coastguard Worker     return GURL();
150*6777b538SAndroid Build Coastguard Worker 
151*6777b538SAndroid Build Coastguard Worker   if (scheme() == kFileScheme)
152*6777b538SAndroid Build Coastguard Worker     return GURL("file:///");
153*6777b538SAndroid Build Coastguard Worker 
154*6777b538SAndroid Build Coastguard Worker   return tuple_.GetURL();
155*6777b538SAndroid Build Coastguard Worker }
156*6777b538SAndroid Build Coastguard Worker 
GetNonceForSerialization() const157*6777b538SAndroid Build Coastguard Worker const base::UnguessableToken* Origin::GetNonceForSerialization() const {
158*6777b538SAndroid Build Coastguard Worker   return nonce_ ? &nonce_->token() : nullptr;
159*6777b538SAndroid Build Coastguard Worker }
160*6777b538SAndroid Build Coastguard Worker 
IsSameOriginWith(const Origin & other) const161*6777b538SAndroid Build Coastguard Worker bool Origin::IsSameOriginWith(const Origin& other) const {
162*6777b538SAndroid Build Coastguard Worker   // scheme/host/port must match, even for opaque origins where |tuple_| holds
163*6777b538SAndroid Build Coastguard Worker   // the precursor origin.
164*6777b538SAndroid Build Coastguard Worker   return std::tie(tuple_, nonce_) == std::tie(other.tuple_, other.nonce_);
165*6777b538SAndroid Build Coastguard Worker }
166*6777b538SAndroid Build Coastguard Worker 
IsSameOriginWith(const GURL & url) const167*6777b538SAndroid Build Coastguard Worker bool Origin::IsSameOriginWith(const GURL& url) const {
168*6777b538SAndroid Build Coastguard Worker   if (opaque())
169*6777b538SAndroid Build Coastguard Worker     return false;
170*6777b538SAndroid Build Coastguard Worker 
171*6777b538SAndroid Build Coastguard Worker   // The `url::Origin::Create` call here preserves how IsSameOriginWith was used
172*6777b538SAndroid Build Coastguard Worker   // historically, even though in some scenarios it is not clearly correct:
173*6777b538SAndroid Build Coastguard Worker   // - Origin of about:blank and about:srcdoc cannot be correctly
174*6777b538SAndroid Build Coastguard Worker   //   computed/recovered.
175*6777b538SAndroid Build Coastguard Worker   // - Ideally passing an invalid `url` would be a caller error (e.g. a DCHECK).
176*6777b538SAndroid Build Coastguard Worker   // - The caller intent is not always clear wrt handling the outer-vs-inner
177*6777b538SAndroid Build Coastguard Worker   //   origins/URLs in blob: and filesystem: schemes.
178*6777b538SAndroid Build Coastguard Worker   return IsSameOriginWith(url::Origin::Create(url));
179*6777b538SAndroid Build Coastguard Worker }
180*6777b538SAndroid Build Coastguard Worker 
CanBeDerivedFrom(const GURL & url) const181*6777b538SAndroid Build Coastguard Worker bool Origin::CanBeDerivedFrom(const GURL& url) const {
182*6777b538SAndroid Build Coastguard Worker   DCHECK(url.is_valid());
183*6777b538SAndroid Build Coastguard Worker 
184*6777b538SAndroid Build Coastguard Worker   // For "no access" schemes, blink's SecurityOrigin will always create an
185*6777b538SAndroid Build Coastguard Worker   // opaque unique one. However, about: scheme is also registered as such but
186*6777b538SAndroid Build Coastguard Worker   // does not behave this way, therefore exclude it from this check.
187*6777b538SAndroid Build Coastguard Worker   if (base::Contains(url::GetNoAccessSchemes(), url.scheme()) &&
188*6777b538SAndroid Build Coastguard Worker       !url.SchemeIs(kAboutScheme)) {
189*6777b538SAndroid Build Coastguard Worker     // If |this| is not opaque, definitely return false as the expectation
190*6777b538SAndroid Build Coastguard Worker     // is for opaque origin.
191*6777b538SAndroid Build Coastguard Worker     if (!opaque())
192*6777b538SAndroid Build Coastguard Worker       return false;
193*6777b538SAndroid Build Coastguard Worker 
194*6777b538SAndroid Build Coastguard Worker     // And if it is unique opaque origin, it definitely is fine. But if there
195*6777b538SAndroid Build Coastguard Worker     // is a precursor stored, we should fall through to compare the tuples.
196*6777b538SAndroid Build Coastguard Worker     if (!tuple_.IsValid())
197*6777b538SAndroid Build Coastguard Worker       return true;
198*6777b538SAndroid Build Coastguard Worker   }
199*6777b538SAndroid Build Coastguard Worker 
200*6777b538SAndroid Build Coastguard Worker   SchemeHostPort url_tuple;
201*6777b538SAndroid Build Coastguard Worker 
202*6777b538SAndroid Build Coastguard Worker   // Optimization for the common, success case: Scheme/Host/Port match on the
203*6777b538SAndroid Build Coastguard Worker   // precursor, and the URL is standard. Opaqueness does not matter as a tuple
204*6777b538SAndroid Build Coastguard Worker   // origin can always create an opaque tuple origin.
205*6777b538SAndroid Build Coastguard Worker   if (url.IsStandard()) {
206*6777b538SAndroid Build Coastguard Worker     // Note: if extra copies of the scheme and host are undesirable, this check
207*6777b538SAndroid Build Coastguard Worker     // can be implemented using StringPiece comparisons, but it has to account
208*6777b538SAndroid Build Coastguard Worker     // explicitly checks on port numbers.
209*6777b538SAndroid Build Coastguard Worker     if (url.SchemeIsFileSystem()) {
210*6777b538SAndroid Build Coastguard Worker       url_tuple = SchemeHostPort(*url.inner_url());
211*6777b538SAndroid Build Coastguard Worker     } else {
212*6777b538SAndroid Build Coastguard Worker       url_tuple = SchemeHostPort(url);
213*6777b538SAndroid Build Coastguard Worker     }
214*6777b538SAndroid Build Coastguard Worker     return url_tuple == tuple_;
215*6777b538SAndroid Build Coastguard Worker 
216*6777b538SAndroid Build Coastguard Worker     // Blob URLs still contain an inner origin, however it is not accessible
217*6777b538SAndroid Build Coastguard Worker     // through inner_url(), therefore it requires specific case to handle it.
218*6777b538SAndroid Build Coastguard Worker   } else if (url.SchemeIsBlob()) {
219*6777b538SAndroid Build Coastguard Worker     // If |this| doesn't contain any precursor information, it is an unique
220*6777b538SAndroid Build Coastguard Worker     // opaque origin. It is valid case, as any browser-initiated navigation
221*6777b538SAndroid Build Coastguard Worker     // to about:blank or data: URL will result in a document with such
222*6777b538SAndroid Build Coastguard Worker     // origin and it is valid for it to create blob: URLs.
223*6777b538SAndroid Build Coastguard Worker     if (!tuple_.IsValid())
224*6777b538SAndroid Build Coastguard Worker       return true;
225*6777b538SAndroid Build Coastguard Worker 
226*6777b538SAndroid Build Coastguard Worker     url_tuple = SchemeHostPort(GURL(url.GetContent()));
227*6777b538SAndroid Build Coastguard Worker     return url_tuple == tuple_;
228*6777b538SAndroid Build Coastguard Worker   }
229*6777b538SAndroid Build Coastguard Worker 
230*6777b538SAndroid Build Coastguard Worker   // At this point, the URL has non-standard scheme.
231*6777b538SAndroid Build Coastguard Worker   DCHECK(!url.IsStandard());
232*6777b538SAndroid Build Coastguard Worker 
233*6777b538SAndroid Build Coastguard Worker   // All about: URLs (about:blank, about:srcdoc) inherit their origin from
234*6777b538SAndroid Build Coastguard Worker   // the context which navigated them, which means that they can be in any
235*6777b538SAndroid Build Coastguard Worker   // type of origin.
236*6777b538SAndroid Build Coastguard Worker   if (url.SchemeIs(kAboutScheme))
237*6777b538SAndroid Build Coastguard Worker     return true;
238*6777b538SAndroid Build Coastguard Worker 
239*6777b538SAndroid Build Coastguard Worker   // All data: URLs commit in opaque origins, therefore |this| must be opaque
240*6777b538SAndroid Build Coastguard Worker   // if |url| has data: scheme.
241*6777b538SAndroid Build Coastguard Worker   if (url.SchemeIs(kDataScheme))
242*6777b538SAndroid Build Coastguard Worker     return opaque();
243*6777b538SAndroid Build Coastguard Worker 
244*6777b538SAndroid Build Coastguard Worker   // If |this| does not have valid precursor tuple, it is unique opaque origin,
245*6777b538SAndroid Build Coastguard Worker   // which is what we expect non-standard schemes to get.
246*6777b538SAndroid Build Coastguard Worker   if (!tuple_.IsValid())
247*6777b538SAndroid Build Coastguard Worker     return true;
248*6777b538SAndroid Build Coastguard Worker 
249*6777b538SAndroid Build Coastguard Worker   // However, when there is precursor present, that must match.
250*6777b538SAndroid Build Coastguard Worker   if (IsUsingStandardCompliantNonSpecialSchemeURLParsing()) {
251*6777b538SAndroid Build Coastguard Worker     return SchemeHostPort(url) == tuple_;
252*6777b538SAndroid Build Coastguard Worker   } else {
253*6777b538SAndroid Build Coastguard Worker     // Match only the scheme because host and port are unavailable for
254*6777b538SAndroid Build Coastguard Worker     // non-special URLs when the flag is disabled.
255*6777b538SAndroid Build Coastguard Worker     return url.scheme() == tuple_.scheme();
256*6777b538SAndroid Build Coastguard Worker   }
257*6777b538SAndroid Build Coastguard Worker }
258*6777b538SAndroid Build Coastguard Worker 
DomainIs(std::string_view canonical_domain) const259*6777b538SAndroid Build Coastguard Worker bool Origin::DomainIs(std::string_view canonical_domain) const {
260*6777b538SAndroid Build Coastguard Worker   return !opaque() && url::DomainIs(tuple_.host(), canonical_domain);
261*6777b538SAndroid Build Coastguard Worker }
262*6777b538SAndroid Build Coastguard Worker 
operator <(const Origin & other) const263*6777b538SAndroid Build Coastguard Worker bool Origin::operator<(const Origin& other) const {
264*6777b538SAndroid Build Coastguard Worker   return std::tie(tuple_, nonce_) < std::tie(other.tuple_, other.nonce_);
265*6777b538SAndroid Build Coastguard Worker }
266*6777b538SAndroid Build Coastguard Worker 
DeriveNewOpaqueOrigin() const267*6777b538SAndroid Build Coastguard Worker Origin Origin::DeriveNewOpaqueOrigin() const {
268*6777b538SAndroid Build Coastguard Worker   return Origin(Nonce(), tuple_);
269*6777b538SAndroid Build Coastguard Worker }
270*6777b538SAndroid Build Coastguard Worker 
GetNonceForTesting() const271*6777b538SAndroid Build Coastguard Worker const base::UnguessableToken* Origin::GetNonceForTesting() const {
272*6777b538SAndroid Build Coastguard Worker   return GetNonceForSerialization();
273*6777b538SAndroid Build Coastguard Worker }
274*6777b538SAndroid Build Coastguard Worker 
GetDebugString(bool include_nonce) const275*6777b538SAndroid Build Coastguard Worker std::string Origin::GetDebugString(bool include_nonce) const {
276*6777b538SAndroid Build Coastguard Worker   // Handle non-opaque origins first, as they are simpler.
277*6777b538SAndroid Build Coastguard Worker   if (!opaque()) {
278*6777b538SAndroid Build Coastguard Worker     std::string out = Serialize();
279*6777b538SAndroid Build Coastguard Worker     if (scheme() == kFileScheme)
280*6777b538SAndroid Build Coastguard Worker       base::StrAppend(&out, {" [internally: ", tuple_.Serialize(), "]"});
281*6777b538SAndroid Build Coastguard Worker     return out;
282*6777b538SAndroid Build Coastguard Worker   }
283*6777b538SAndroid Build Coastguard Worker 
284*6777b538SAndroid Build Coastguard Worker   // For opaque origins, log the nonce and precursor as well. Without this,
285*6777b538SAndroid Build Coastguard Worker   // EXPECT_EQ failures between opaque origins are nearly impossible to
286*6777b538SAndroid Build Coastguard Worker   // understand.
287*6777b538SAndroid Build Coastguard Worker   std::string out = base::StrCat({Serialize(), " [internally:"});
288*6777b538SAndroid Build Coastguard Worker   if (include_nonce) {
289*6777b538SAndroid Build Coastguard Worker     out += " (";
290*6777b538SAndroid Build Coastguard Worker     if (nonce_->raw_token().is_empty())
291*6777b538SAndroid Build Coastguard Worker       out += "nonce TBD";
292*6777b538SAndroid Build Coastguard Worker     else
293*6777b538SAndroid Build Coastguard Worker       out += nonce_->raw_token().ToString();
294*6777b538SAndroid Build Coastguard Worker     out += ")";
295*6777b538SAndroid Build Coastguard Worker   }
296*6777b538SAndroid Build Coastguard Worker   if (!tuple_.IsValid())
297*6777b538SAndroid Build Coastguard Worker     base::StrAppend(&out, {" anonymous]"});
298*6777b538SAndroid Build Coastguard Worker   else
299*6777b538SAndroid Build Coastguard Worker     base::StrAppend(&out, {" derived from ", tuple_.Serialize(), "]"});
300*6777b538SAndroid Build Coastguard Worker   return out;
301*6777b538SAndroid Build Coastguard Worker }
302*6777b538SAndroid Build Coastguard Worker 
Origin(SchemeHostPort tuple)303*6777b538SAndroid Build Coastguard Worker Origin::Origin(SchemeHostPort tuple) : tuple_(std::move(tuple)) {
304*6777b538SAndroid Build Coastguard Worker   DCHECK(!opaque());
305*6777b538SAndroid Build Coastguard Worker   DCHECK(tuple_.IsValid());
306*6777b538SAndroid Build Coastguard Worker }
307*6777b538SAndroid Build Coastguard Worker 
308*6777b538SAndroid Build Coastguard Worker // Constructs an opaque origin derived from |precursor|.
Origin(const Nonce & nonce,SchemeHostPort precursor)309*6777b538SAndroid Build Coastguard Worker Origin::Origin(const Nonce& nonce, SchemeHostPort precursor)
310*6777b538SAndroid Build Coastguard Worker     : tuple_(std::move(precursor)), nonce_(std::move(nonce)) {
311*6777b538SAndroid Build Coastguard Worker   DCHECK(opaque());
312*6777b538SAndroid Build Coastguard Worker   // |precursor| is retained, but not accessible via scheme()/host()/port().
313*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ("", scheme());
314*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ("", host());
315*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(0U, port());
316*6777b538SAndroid Build Coastguard Worker }
317*6777b538SAndroid Build Coastguard Worker 
SerializeWithNonce() const318*6777b538SAndroid Build Coastguard Worker std::optional<std::string> Origin::SerializeWithNonce() const {
319*6777b538SAndroid Build Coastguard Worker   return SerializeWithNonceImpl();
320*6777b538SAndroid Build Coastguard Worker }
321*6777b538SAndroid Build Coastguard Worker 
SerializeWithNonceAndInitIfNeeded()322*6777b538SAndroid Build Coastguard Worker std::optional<std::string> Origin::SerializeWithNonceAndInitIfNeeded() {
323*6777b538SAndroid Build Coastguard Worker   GetNonceForSerialization();
324*6777b538SAndroid Build Coastguard Worker   return SerializeWithNonceImpl();
325*6777b538SAndroid Build Coastguard Worker }
326*6777b538SAndroid Build Coastguard Worker 
327*6777b538SAndroid Build Coastguard Worker // The pickle is saved in the following format, in order:
328*6777b538SAndroid Build Coastguard Worker // string - tuple_.GetURL().spec().
329*6777b538SAndroid Build Coastguard Worker // uint64_t (if opaque) - high bits of nonce if opaque. 0 if not initialized.
330*6777b538SAndroid Build Coastguard Worker // uint64_t (if opaque) - low bits of nonce if opaque. 0 if not initialized.
SerializeWithNonceImpl() const331*6777b538SAndroid Build Coastguard Worker std::optional<std::string> Origin::SerializeWithNonceImpl() const {
332*6777b538SAndroid Build Coastguard Worker   if (!opaque() && !tuple_.IsValid())
333*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
334*6777b538SAndroid Build Coastguard Worker 
335*6777b538SAndroid Build Coastguard Worker   base::Pickle pickle;
336*6777b538SAndroid Build Coastguard Worker   pickle.WriteString(tuple_.Serialize());
337*6777b538SAndroid Build Coastguard Worker   if (opaque() && !nonce_->raw_token().is_empty()) {
338*6777b538SAndroid Build Coastguard Worker     pickle.WriteUInt64(nonce_->token().GetHighForSerialization());
339*6777b538SAndroid Build Coastguard Worker     pickle.WriteUInt64(nonce_->token().GetLowForSerialization());
340*6777b538SAndroid Build Coastguard Worker   } else if (opaque()) {
341*6777b538SAndroid Build Coastguard Worker     // Nonce hasn't been initialized.
342*6777b538SAndroid Build Coastguard Worker     pickle.WriteUInt64(0);
343*6777b538SAndroid Build Coastguard Worker     pickle.WriteUInt64(0);
344*6777b538SAndroid Build Coastguard Worker   }
345*6777b538SAndroid Build Coastguard Worker 
346*6777b538SAndroid Build Coastguard Worker   base::span<const uint8_t> data(static_cast<const uint8_t*>(pickle.data()),
347*6777b538SAndroid Build Coastguard Worker                                  pickle.size());
348*6777b538SAndroid Build Coastguard Worker   // Base64 encode the data to make it nicer to play with.
349*6777b538SAndroid Build Coastguard Worker   return base::Base64Encode(data);
350*6777b538SAndroid Build Coastguard Worker }
351*6777b538SAndroid Build Coastguard Worker 
352*6777b538SAndroid Build Coastguard Worker // static
Deserialize(const std::string & value)353*6777b538SAndroid Build Coastguard Worker std::optional<Origin> Origin::Deserialize(const std::string& value) {
354*6777b538SAndroid Build Coastguard Worker   std::string data;
355*6777b538SAndroid Build Coastguard Worker   if (!base::Base64Decode(value, &data))
356*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
357*6777b538SAndroid Build Coastguard Worker 
358*6777b538SAndroid Build Coastguard Worker   base::Pickle pickle =
359*6777b538SAndroid Build Coastguard Worker       base::Pickle::WithUnownedBuffer(base::as_byte_span(data));
360*6777b538SAndroid Build Coastguard Worker   base::PickleIterator reader(pickle);
361*6777b538SAndroid Build Coastguard Worker 
362*6777b538SAndroid Build Coastguard Worker   std::string pickled_url;
363*6777b538SAndroid Build Coastguard Worker   if (!reader.ReadString(&pickled_url))
364*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
365*6777b538SAndroid Build Coastguard Worker   GURL url(pickled_url);
366*6777b538SAndroid Build Coastguard Worker 
367*6777b538SAndroid Build Coastguard Worker   // If only a tuple was serialized, then this origin is not opaque. For opaque
368*6777b538SAndroid Build Coastguard Worker   // origins, we expect two uint64's to be left in the pickle.
369*6777b538SAndroid Build Coastguard Worker   bool is_opaque = !reader.ReachedEnd();
370*6777b538SAndroid Build Coastguard Worker 
371*6777b538SAndroid Build Coastguard Worker   // Opaque origins without a tuple are ok.
372*6777b538SAndroid Build Coastguard Worker   if (!is_opaque && !url.is_valid())
373*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
374*6777b538SAndroid Build Coastguard Worker   SchemeHostPort tuple(url);
375*6777b538SAndroid Build Coastguard Worker 
376*6777b538SAndroid Build Coastguard Worker   // Possible successful early return if the pickled Origin was not opaque.
377*6777b538SAndroid Build Coastguard Worker   if (!is_opaque) {
378*6777b538SAndroid Build Coastguard Worker     Origin origin(tuple);
379*6777b538SAndroid Build Coastguard Worker     if (origin.opaque())
380*6777b538SAndroid Build Coastguard Worker       return std::nullopt;  // Something went horribly wrong.
381*6777b538SAndroid Build Coastguard Worker     return origin;
382*6777b538SAndroid Build Coastguard Worker   }
383*6777b538SAndroid Build Coastguard Worker 
384*6777b538SAndroid Build Coastguard Worker   uint64_t nonce_high = 0;
385*6777b538SAndroid Build Coastguard Worker   if (!reader.ReadUInt64(&nonce_high))
386*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
387*6777b538SAndroid Build Coastguard Worker 
388*6777b538SAndroid Build Coastguard Worker   uint64_t nonce_low = 0;
389*6777b538SAndroid Build Coastguard Worker   if (!reader.ReadUInt64(&nonce_low))
390*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
391*6777b538SAndroid Build Coastguard Worker 
392*6777b538SAndroid Build Coastguard Worker   std::optional<base::UnguessableToken> nonce_token =
393*6777b538SAndroid Build Coastguard Worker       base::UnguessableToken::Deserialize(nonce_high, nonce_low);
394*6777b538SAndroid Build Coastguard Worker 
395*6777b538SAndroid Build Coastguard Worker   Origin::Nonce nonce;
396*6777b538SAndroid Build Coastguard Worker   if (nonce_token.has_value()) {
397*6777b538SAndroid Build Coastguard Worker     // The serialized nonce wasn't empty, so copy it here.
398*6777b538SAndroid Build Coastguard Worker     nonce = Origin::Nonce(nonce_token.value());
399*6777b538SAndroid Build Coastguard Worker   }
400*6777b538SAndroid Build Coastguard Worker   Origin origin;
401*6777b538SAndroid Build Coastguard Worker   origin.nonce_ = std::move(nonce);
402*6777b538SAndroid Build Coastguard Worker   origin.tuple_ = tuple;
403*6777b538SAndroid Build Coastguard Worker   return origin;
404*6777b538SAndroid Build Coastguard Worker }
405*6777b538SAndroid Build Coastguard Worker 
WriteIntoTrace(perfetto::TracedValue context) const406*6777b538SAndroid Build Coastguard Worker void Origin::WriteIntoTrace(perfetto::TracedValue context) const {
407*6777b538SAndroid Build Coastguard Worker   std::move(context).WriteString(GetDebugString());
408*6777b538SAndroid Build Coastguard Worker }
409*6777b538SAndroid Build Coastguard Worker 
EstimateMemoryUsage() const410*6777b538SAndroid Build Coastguard Worker size_t Origin::EstimateMemoryUsage() const {
411*6777b538SAndroid Build Coastguard Worker   return base::trace_event::EstimateMemoryUsage(tuple_);
412*6777b538SAndroid Build Coastguard Worker }
413*6777b538SAndroid Build Coastguard Worker 
operator <<(std::ostream & out,const url::Origin & origin)414*6777b538SAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& out, const url::Origin& origin) {
415*6777b538SAndroid Build Coastguard Worker   out << origin.GetDebugString();
416*6777b538SAndroid Build Coastguard Worker   return out;
417*6777b538SAndroid Build Coastguard Worker }
418*6777b538SAndroid Build Coastguard Worker 
operator <<(std::ostream & out,const url::Origin::Nonce & nonce)419*6777b538SAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& out, const url::Origin::Nonce& nonce) {
420*6777b538SAndroid Build Coastguard Worker   // Subtle: don't let logging trigger lazy-generation of the token value.
421*6777b538SAndroid Build Coastguard Worker   if (nonce.raw_token().is_empty())
422*6777b538SAndroid Build Coastguard Worker     return (out << "(nonce TBD)");
423*6777b538SAndroid Build Coastguard Worker   else
424*6777b538SAndroid Build Coastguard Worker     return (out << nonce.raw_token());
425*6777b538SAndroid Build Coastguard Worker }
426*6777b538SAndroid Build Coastguard Worker 
IsSameOriginWith(const GURL & a,const GURL & b)427*6777b538SAndroid Build Coastguard Worker bool IsSameOriginWith(const GURL& a, const GURL& b) {
428*6777b538SAndroid Build Coastguard Worker   return Origin::Create(a).IsSameOriginWith(Origin::Create(b));
429*6777b538SAndroid Build Coastguard Worker }
430*6777b538SAndroid Build Coastguard Worker 
431*6777b538SAndroid Build Coastguard Worker Origin::Nonce::Nonce() = default;
Nonce(const base::UnguessableToken & token)432*6777b538SAndroid Build Coastguard Worker Origin::Nonce::Nonce(const base::UnguessableToken& token) : token_(token) {
433*6777b538SAndroid Build Coastguard Worker   CHECK(!token_.is_empty());
434*6777b538SAndroid Build Coastguard Worker }
435*6777b538SAndroid Build Coastguard Worker 
token() const436*6777b538SAndroid Build Coastguard Worker const base::UnguessableToken& Origin::Nonce::token() const {
437*6777b538SAndroid Build Coastguard Worker   // Inspecting the value of a nonce triggers lazy-generation.
438*6777b538SAndroid Build Coastguard Worker   // TODO(dcheng): UnguessableToken::is_empty should go away -- what sentinel
439*6777b538SAndroid Build Coastguard Worker   // value to use instead?
440*6777b538SAndroid Build Coastguard Worker   if (token_.is_empty())
441*6777b538SAndroid Build Coastguard Worker     token_ = base::UnguessableToken::Create();
442*6777b538SAndroid Build Coastguard Worker   return token_;
443*6777b538SAndroid Build Coastguard Worker }
444*6777b538SAndroid Build Coastguard Worker 
raw_token() const445*6777b538SAndroid Build Coastguard Worker const base::UnguessableToken& Origin::Nonce::raw_token() const {
446*6777b538SAndroid Build Coastguard Worker   return token_;
447*6777b538SAndroid Build Coastguard Worker }
448*6777b538SAndroid Build Coastguard Worker 
449*6777b538SAndroid Build Coastguard Worker // Copying a Nonce triggers lazy-generation of the token.
Nonce(const Origin::Nonce & other)450*6777b538SAndroid Build Coastguard Worker Origin::Nonce::Nonce(const Origin::Nonce& other) : token_(other.token()) {}
451*6777b538SAndroid Build Coastguard Worker 
operator =(const Origin::Nonce & other)452*6777b538SAndroid Build Coastguard Worker Origin::Nonce& Origin::Nonce::operator=(const Origin::Nonce& other) {
453*6777b538SAndroid Build Coastguard Worker   // Copying a Nonce triggers lazy-generation of the token.
454*6777b538SAndroid Build Coastguard Worker   token_ = other.token();
455*6777b538SAndroid Build Coastguard Worker   return *this;
456*6777b538SAndroid Build Coastguard Worker }
457*6777b538SAndroid Build Coastguard Worker 
458*6777b538SAndroid Build Coastguard Worker // Moving a nonce does NOT trigger lazy-generation of the token.
Nonce(Origin::Nonce && other)459*6777b538SAndroid Build Coastguard Worker Origin::Nonce::Nonce(Origin::Nonce&& other) noexcept : token_(other.token_) {
460*6777b538SAndroid Build Coastguard Worker   other.token_ = base::UnguessableToken();  // Reset |other|.
461*6777b538SAndroid Build Coastguard Worker }
462*6777b538SAndroid Build Coastguard Worker 
operator =(Origin::Nonce && other)463*6777b538SAndroid Build Coastguard Worker Origin::Nonce& Origin::Nonce::operator=(Origin::Nonce&& other) noexcept {
464*6777b538SAndroid Build Coastguard Worker   token_ = other.token_;
465*6777b538SAndroid Build Coastguard Worker   other.token_ = base::UnguessableToken();  // Reset |other|.
466*6777b538SAndroid Build Coastguard Worker   return *this;
467*6777b538SAndroid Build Coastguard Worker }
468*6777b538SAndroid Build Coastguard Worker 
operator <(const Origin::Nonce & other) const469*6777b538SAndroid Build Coastguard Worker bool Origin::Nonce::operator<(const Origin::Nonce& other) const {
470*6777b538SAndroid Build Coastguard Worker   // When comparing, lazy-generation is required of both tokens, so that an
471*6777b538SAndroid Build Coastguard Worker   // ordering is established.
472*6777b538SAndroid Build Coastguard Worker   return token() < other.token();
473*6777b538SAndroid Build Coastguard Worker }
474*6777b538SAndroid Build Coastguard Worker 
operator ==(const Origin::Nonce & other) const475*6777b538SAndroid Build Coastguard Worker bool Origin::Nonce::operator==(const Origin::Nonce& other) const {
476*6777b538SAndroid Build Coastguard Worker   // Equality testing doesn't actually require that the tokens be generated.
477*6777b538SAndroid Build Coastguard Worker   // If the tokens are both zero, equality only holds if they're the same
478*6777b538SAndroid Build Coastguard Worker   // object.
479*6777b538SAndroid Build Coastguard Worker   return (other.token_ == token_) && !(token_.is_empty() && (&other != this));
480*6777b538SAndroid Build Coastguard Worker }
481*6777b538SAndroid Build Coastguard Worker 
operator !=(const Origin::Nonce & other) const482*6777b538SAndroid Build Coastguard Worker bool Origin::Nonce::operator!=(const Origin::Nonce& other) const {
483*6777b538SAndroid Build Coastguard Worker   return !(*this == other);
484*6777b538SAndroid Build Coastguard Worker }
485*6777b538SAndroid Build Coastguard Worker 
486*6777b538SAndroid Build Coastguard Worker namespace debug {
487*6777b538SAndroid Build Coastguard Worker 
ScopedOriginCrashKey(base::debug::CrashKeyString * crash_key,const url::Origin * value)488*6777b538SAndroid Build Coastguard Worker ScopedOriginCrashKey::ScopedOriginCrashKey(
489*6777b538SAndroid Build Coastguard Worker     base::debug::CrashKeyString* crash_key,
490*6777b538SAndroid Build Coastguard Worker     const url::Origin* value)
491*6777b538SAndroid Build Coastguard Worker     : scoped_string_value_(
492*6777b538SAndroid Build Coastguard Worker           crash_key,
493*6777b538SAndroid Build Coastguard Worker           value ? value->GetDebugString(false /* include_nonce */)
494*6777b538SAndroid Build Coastguard Worker                 : "nullptr") {}
495*6777b538SAndroid Build Coastguard Worker 
496*6777b538SAndroid Build Coastguard Worker ScopedOriginCrashKey::~ScopedOriginCrashKey() = default;
497*6777b538SAndroid Build Coastguard Worker 
498*6777b538SAndroid Build Coastguard Worker }  // namespace debug
499*6777b538SAndroid Build Coastguard Worker 
500*6777b538SAndroid Build Coastguard Worker }  // namespace url
501