1*6777b538SAndroid Build Coastguard Worker // Copyright 2013 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/gurl.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <algorithm>
10*6777b538SAndroid Build Coastguard Worker #include <memory>
11*6777b538SAndroid Build Coastguard Worker #include <ostream>
12*6777b538SAndroid Build Coastguard Worker #include <string_view>
13*6777b538SAndroid Build Coastguard Worker #include <utility>
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/no_destructor.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/base_tracing.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/memory_usage_estimator.h"
21*6777b538SAndroid Build Coastguard Worker #include "url/url_canon_stdstring.h"
22*6777b538SAndroid Build Coastguard Worker #include "url/url_util.h"
23*6777b538SAndroid Build Coastguard Worker
GURL()24*6777b538SAndroid Build Coastguard Worker GURL::GURL() : is_valid_(false) {
25*6777b538SAndroid Build Coastguard Worker }
26*6777b538SAndroid Build Coastguard Worker
GURL(const GURL & other)27*6777b538SAndroid Build Coastguard Worker GURL::GURL(const GURL& other)
28*6777b538SAndroid Build Coastguard Worker : spec_(other.spec_),
29*6777b538SAndroid Build Coastguard Worker is_valid_(other.is_valid_),
30*6777b538SAndroid Build Coastguard Worker parsed_(other.parsed_) {
31*6777b538SAndroid Build Coastguard Worker if (other.inner_url_)
32*6777b538SAndroid Build Coastguard Worker inner_url_ = std::make_unique<GURL>(*other.inner_url_);
33*6777b538SAndroid Build Coastguard Worker // Valid filesystem urls should always have an inner_url_.
34*6777b538SAndroid Build Coastguard Worker DCHECK(!is_valid_ || !SchemeIsFileSystem() || inner_url_);
35*6777b538SAndroid Build Coastguard Worker }
36*6777b538SAndroid Build Coastguard Worker
GURL(GURL && other)37*6777b538SAndroid Build Coastguard Worker GURL::GURL(GURL&& other) noexcept
38*6777b538SAndroid Build Coastguard Worker : spec_(std::move(other.spec_)),
39*6777b538SAndroid Build Coastguard Worker is_valid_(other.is_valid_),
40*6777b538SAndroid Build Coastguard Worker parsed_(other.parsed_),
41*6777b538SAndroid Build Coastguard Worker inner_url_(std::move(other.inner_url_)) {
42*6777b538SAndroid Build Coastguard Worker other.is_valid_ = false;
43*6777b538SAndroid Build Coastguard Worker other.parsed_ = url::Parsed();
44*6777b538SAndroid Build Coastguard Worker }
45*6777b538SAndroid Build Coastguard Worker
GURL(std::string_view url_string)46*6777b538SAndroid Build Coastguard Worker GURL::GURL(std::string_view url_string) {
47*6777b538SAndroid Build Coastguard Worker InitCanonical(url_string, true);
48*6777b538SAndroid Build Coastguard Worker }
49*6777b538SAndroid Build Coastguard Worker
GURL(std::u16string_view url_string)50*6777b538SAndroid Build Coastguard Worker GURL::GURL(std::u16string_view url_string) {
51*6777b538SAndroid Build Coastguard Worker InitCanonical(url_string, true);
52*6777b538SAndroid Build Coastguard Worker }
53*6777b538SAndroid Build Coastguard Worker
GURL(const std::string & url_string,RetainWhiteSpaceSelector)54*6777b538SAndroid Build Coastguard Worker GURL::GURL(const std::string& url_string, RetainWhiteSpaceSelector) {
55*6777b538SAndroid Build Coastguard Worker InitCanonical(url_string, false);
56*6777b538SAndroid Build Coastguard Worker }
57*6777b538SAndroid Build Coastguard Worker
GURL(const char * canonical_spec,size_t canonical_spec_len,const url::Parsed & parsed,bool is_valid)58*6777b538SAndroid Build Coastguard Worker GURL::GURL(const char* canonical_spec,
59*6777b538SAndroid Build Coastguard Worker size_t canonical_spec_len,
60*6777b538SAndroid Build Coastguard Worker const url::Parsed& parsed,
61*6777b538SAndroid Build Coastguard Worker bool is_valid)
62*6777b538SAndroid Build Coastguard Worker : spec_(canonical_spec, canonical_spec_len),
63*6777b538SAndroid Build Coastguard Worker is_valid_(is_valid),
64*6777b538SAndroid Build Coastguard Worker parsed_(parsed) {
65*6777b538SAndroid Build Coastguard Worker InitializeFromCanonicalSpec();
66*6777b538SAndroid Build Coastguard Worker }
67*6777b538SAndroid Build Coastguard Worker
GURL(std::string canonical_spec,const url::Parsed & parsed,bool is_valid)68*6777b538SAndroid Build Coastguard Worker GURL::GURL(std::string canonical_spec, const url::Parsed& parsed, bool is_valid)
69*6777b538SAndroid Build Coastguard Worker : spec_(std::move(canonical_spec)), is_valid_(is_valid), parsed_(parsed) {
70*6777b538SAndroid Build Coastguard Worker InitializeFromCanonicalSpec();
71*6777b538SAndroid Build Coastguard Worker }
72*6777b538SAndroid Build Coastguard Worker
73*6777b538SAndroid Build Coastguard Worker template <typename T, typename CharT>
InitCanonical(T input_spec,bool trim_path_end)74*6777b538SAndroid Build Coastguard Worker void GURL::InitCanonical(T input_spec, bool trim_path_end) {
75*6777b538SAndroid Build Coastguard Worker url::StdStringCanonOutput output(&spec_);
76*6777b538SAndroid Build Coastguard Worker is_valid_ = url::Canonicalize(
77*6777b538SAndroid Build Coastguard Worker input_spec.data(), static_cast<int>(input_spec.length()), trim_path_end,
78*6777b538SAndroid Build Coastguard Worker NULL, &output, &parsed_);
79*6777b538SAndroid Build Coastguard Worker
80*6777b538SAndroid Build Coastguard Worker output.Complete(); // Must be done before using string.
81*6777b538SAndroid Build Coastguard Worker if (is_valid_ && SchemeIsFileSystem()) {
82*6777b538SAndroid Build Coastguard Worker inner_url_ = std::make_unique<GURL>(spec_.data(), parsed_.Length(),
83*6777b538SAndroid Build Coastguard Worker *parsed_.inner_parsed(), true);
84*6777b538SAndroid Build Coastguard Worker }
85*6777b538SAndroid Build Coastguard Worker // Valid URLs always have non-empty specs.
86*6777b538SAndroid Build Coastguard Worker DCHECK(!is_valid_ || !spec_.empty());
87*6777b538SAndroid Build Coastguard Worker }
88*6777b538SAndroid Build Coastguard Worker
InitializeFromCanonicalSpec()89*6777b538SAndroid Build Coastguard Worker void GURL::InitializeFromCanonicalSpec() {
90*6777b538SAndroid Build Coastguard Worker if (is_valid_ && SchemeIsFileSystem()) {
91*6777b538SAndroid Build Coastguard Worker inner_url_ = std::make_unique<GURL>(spec_.data(), parsed_.Length(),
92*6777b538SAndroid Build Coastguard Worker *parsed_.inner_parsed(), true);
93*6777b538SAndroid Build Coastguard Worker }
94*6777b538SAndroid Build Coastguard Worker
95*6777b538SAndroid Build Coastguard Worker #ifndef NDEBUG
96*6777b538SAndroid Build Coastguard Worker // For testing purposes, check that the parsed canonical URL is identical to
97*6777b538SAndroid Build Coastguard Worker // what we would have produced. Skip checking for invalid URLs have no meaning
98*6777b538SAndroid Build Coastguard Worker // and we can't always canonicalize then reproducibly.
99*6777b538SAndroid Build Coastguard Worker if (is_valid_) {
100*6777b538SAndroid Build Coastguard Worker DCHECK(!spec_.empty());
101*6777b538SAndroid Build Coastguard Worker url::Component scheme;
102*6777b538SAndroid Build Coastguard Worker // We can't do this check on the inner_url of a filesystem URL, as
103*6777b538SAndroid Build Coastguard Worker // canonical_spec actually points to the start of the outer URL, so we'd
104*6777b538SAndroid Build Coastguard Worker // end up with infinite recursion in this constructor.
105*6777b538SAndroid Build Coastguard Worker if (!url::FindAndCompareScheme(spec_.data(), spec_.length(),
106*6777b538SAndroid Build Coastguard Worker url::kFileSystemScheme, &scheme) ||
107*6777b538SAndroid Build Coastguard Worker scheme.begin == parsed_.scheme.begin) {
108*6777b538SAndroid Build Coastguard Worker // We need to retain trailing whitespace on path URLs, as the |parsed_|
109*6777b538SAndroid Build Coastguard Worker // spec we originally received may legitimately contain trailing white-
110*6777b538SAndroid Build Coastguard Worker // space on the path or components e.g. if the #ref has been
111*6777b538SAndroid Build Coastguard Worker // removed from a "foo:hello #ref" URL (see http://crbug.com/291747).
112*6777b538SAndroid Build Coastguard Worker GURL test_url(spec_, RETAIN_TRAILING_PATH_WHITEPACE);
113*6777b538SAndroid Build Coastguard Worker
114*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(test_url.is_valid_, is_valid_);
115*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(test_url.spec_, spec_);
116*6777b538SAndroid Build Coastguard Worker
117*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(test_url.parsed_.scheme, parsed_.scheme);
118*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(test_url.parsed_.username, parsed_.username);
119*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(test_url.parsed_.password, parsed_.password);
120*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(test_url.parsed_.host, parsed_.host);
121*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(test_url.parsed_.port, parsed_.port);
122*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(test_url.parsed_.path, parsed_.path);
123*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(test_url.parsed_.query, parsed_.query);
124*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(test_url.parsed_.ref, parsed_.ref);
125*6777b538SAndroid Build Coastguard Worker }
126*6777b538SAndroid Build Coastguard Worker }
127*6777b538SAndroid Build Coastguard Worker #endif
128*6777b538SAndroid Build Coastguard Worker }
129*6777b538SAndroid Build Coastguard Worker
130*6777b538SAndroid Build Coastguard Worker GURL::~GURL() = default;
131*6777b538SAndroid Build Coastguard Worker
operator =(const GURL & other)132*6777b538SAndroid Build Coastguard Worker GURL& GURL::operator=(const GURL& other) {
133*6777b538SAndroid Build Coastguard Worker spec_ = other.spec_;
134*6777b538SAndroid Build Coastguard Worker is_valid_ = other.is_valid_;
135*6777b538SAndroid Build Coastguard Worker parsed_ = other.parsed_;
136*6777b538SAndroid Build Coastguard Worker
137*6777b538SAndroid Build Coastguard Worker if (!other.inner_url_)
138*6777b538SAndroid Build Coastguard Worker inner_url_.reset();
139*6777b538SAndroid Build Coastguard Worker else if (inner_url_)
140*6777b538SAndroid Build Coastguard Worker *inner_url_ = *other.inner_url_;
141*6777b538SAndroid Build Coastguard Worker else
142*6777b538SAndroid Build Coastguard Worker inner_url_ = std::make_unique<GURL>(*other.inner_url_);
143*6777b538SAndroid Build Coastguard Worker
144*6777b538SAndroid Build Coastguard Worker return *this;
145*6777b538SAndroid Build Coastguard Worker }
146*6777b538SAndroid Build Coastguard Worker
operator =(GURL && other)147*6777b538SAndroid Build Coastguard Worker GURL& GURL::operator=(GURL&& other) noexcept {
148*6777b538SAndroid Build Coastguard Worker spec_ = std::move(other.spec_);
149*6777b538SAndroid Build Coastguard Worker is_valid_ = other.is_valid_;
150*6777b538SAndroid Build Coastguard Worker parsed_ = other.parsed_;
151*6777b538SAndroid Build Coastguard Worker inner_url_ = std::move(other.inner_url_);
152*6777b538SAndroid Build Coastguard Worker
153*6777b538SAndroid Build Coastguard Worker other.is_valid_ = false;
154*6777b538SAndroid Build Coastguard Worker other.parsed_ = url::Parsed();
155*6777b538SAndroid Build Coastguard Worker return *this;
156*6777b538SAndroid Build Coastguard Worker }
157*6777b538SAndroid Build Coastguard Worker
spec() const158*6777b538SAndroid Build Coastguard Worker const std::string& GURL::spec() const {
159*6777b538SAndroid Build Coastguard Worker if (is_valid_ || spec_.empty())
160*6777b538SAndroid Build Coastguard Worker return spec_;
161*6777b538SAndroid Build Coastguard Worker
162*6777b538SAndroid Build Coastguard Worker // TODO(crbug.com/851128): Make sure this no longer hits before making
163*6777b538SAndroid Build Coastguard Worker // NOTREACHED_NORETURN();
164*6777b538SAndroid Build Coastguard Worker DUMP_WILL_BE_NOTREACHED_NORETURN()
165*6777b538SAndroid Build Coastguard Worker << "Trying to get the spec of an invalid URL!";
166*6777b538SAndroid Build Coastguard Worker return base::EmptyString();
167*6777b538SAndroid Build Coastguard Worker }
168*6777b538SAndroid Build Coastguard Worker
operator <(const GURL & other) const169*6777b538SAndroid Build Coastguard Worker bool GURL::operator<(const GURL& other) const {
170*6777b538SAndroid Build Coastguard Worker return spec_ < other.spec_;
171*6777b538SAndroid Build Coastguard Worker }
172*6777b538SAndroid Build Coastguard Worker
operator >(const GURL & other) const173*6777b538SAndroid Build Coastguard Worker bool GURL::operator>(const GURL& other) const {
174*6777b538SAndroid Build Coastguard Worker return spec_ > other.spec_;
175*6777b538SAndroid Build Coastguard Worker }
176*6777b538SAndroid Build Coastguard Worker
177*6777b538SAndroid Build Coastguard Worker // Note: code duplicated below (it's inconvenient to use a template here).
Resolve(std::string_view relative) const178*6777b538SAndroid Build Coastguard Worker GURL GURL::Resolve(std::string_view relative) const {
179*6777b538SAndroid Build Coastguard Worker // Not allowed for invalid URLs.
180*6777b538SAndroid Build Coastguard Worker if (!is_valid_)
181*6777b538SAndroid Build Coastguard Worker return GURL();
182*6777b538SAndroid Build Coastguard Worker
183*6777b538SAndroid Build Coastguard Worker GURL result;
184*6777b538SAndroid Build Coastguard Worker url::StdStringCanonOutput output(&result.spec_);
185*6777b538SAndroid Build Coastguard Worker if (!url::ResolveRelative(spec_.data(), static_cast<int>(spec_.length()),
186*6777b538SAndroid Build Coastguard Worker parsed_, relative.data(),
187*6777b538SAndroid Build Coastguard Worker static_cast<int>(relative.length()),
188*6777b538SAndroid Build Coastguard Worker nullptr, &output, &result.parsed_)) {
189*6777b538SAndroid Build Coastguard Worker // Error resolving, return an empty URL.
190*6777b538SAndroid Build Coastguard Worker return GURL();
191*6777b538SAndroid Build Coastguard Worker }
192*6777b538SAndroid Build Coastguard Worker
193*6777b538SAndroid Build Coastguard Worker output.Complete();
194*6777b538SAndroid Build Coastguard Worker result.is_valid_ = true;
195*6777b538SAndroid Build Coastguard Worker if (result.SchemeIsFileSystem()) {
196*6777b538SAndroid Build Coastguard Worker result.inner_url_ =
197*6777b538SAndroid Build Coastguard Worker std::make_unique<GURL>(result.spec_.data(), result.parsed_.Length(),
198*6777b538SAndroid Build Coastguard Worker *result.parsed_.inner_parsed(), true);
199*6777b538SAndroid Build Coastguard Worker }
200*6777b538SAndroid Build Coastguard Worker return result;
201*6777b538SAndroid Build Coastguard Worker }
202*6777b538SAndroid Build Coastguard Worker
203*6777b538SAndroid Build Coastguard Worker // Note: code duplicated above (it's inconvenient to use a template here).
Resolve(std::u16string_view relative) const204*6777b538SAndroid Build Coastguard Worker GURL GURL::Resolve(std::u16string_view relative) const {
205*6777b538SAndroid Build Coastguard Worker // Not allowed for invalid URLs.
206*6777b538SAndroid Build Coastguard Worker if (!is_valid_)
207*6777b538SAndroid Build Coastguard Worker return GURL();
208*6777b538SAndroid Build Coastguard Worker
209*6777b538SAndroid Build Coastguard Worker GURL result;
210*6777b538SAndroid Build Coastguard Worker url::StdStringCanonOutput output(&result.spec_);
211*6777b538SAndroid Build Coastguard Worker if (!url::ResolveRelative(spec_.data(), static_cast<int>(spec_.length()),
212*6777b538SAndroid Build Coastguard Worker parsed_, relative.data(),
213*6777b538SAndroid Build Coastguard Worker static_cast<int>(relative.length()),
214*6777b538SAndroid Build Coastguard Worker nullptr, &output, &result.parsed_)) {
215*6777b538SAndroid Build Coastguard Worker // Error resolving, return an empty URL.
216*6777b538SAndroid Build Coastguard Worker return GURL();
217*6777b538SAndroid Build Coastguard Worker }
218*6777b538SAndroid Build Coastguard Worker
219*6777b538SAndroid Build Coastguard Worker output.Complete();
220*6777b538SAndroid Build Coastguard Worker result.is_valid_ = true;
221*6777b538SAndroid Build Coastguard Worker if (result.SchemeIsFileSystem()) {
222*6777b538SAndroid Build Coastguard Worker result.inner_url_ =
223*6777b538SAndroid Build Coastguard Worker std::make_unique<GURL>(result.spec_.data(), result.parsed_.Length(),
224*6777b538SAndroid Build Coastguard Worker *result.parsed_.inner_parsed(), true);
225*6777b538SAndroid Build Coastguard Worker }
226*6777b538SAndroid Build Coastguard Worker return result;
227*6777b538SAndroid Build Coastguard Worker }
228*6777b538SAndroid Build Coastguard Worker
229*6777b538SAndroid Build Coastguard Worker // Note: code duplicated below (it's inconvenient to use a template here).
ReplaceComponents(const Replacements & replacements) const230*6777b538SAndroid Build Coastguard Worker GURL GURL::ReplaceComponents(const Replacements& replacements) const {
231*6777b538SAndroid Build Coastguard Worker GURL result;
232*6777b538SAndroid Build Coastguard Worker
233*6777b538SAndroid Build Coastguard Worker // Not allowed for invalid URLs.
234*6777b538SAndroid Build Coastguard Worker if (!is_valid_)
235*6777b538SAndroid Build Coastguard Worker return GURL();
236*6777b538SAndroid Build Coastguard Worker
237*6777b538SAndroid Build Coastguard Worker url::StdStringCanonOutput output(&result.spec_);
238*6777b538SAndroid Build Coastguard Worker result.is_valid_ = url::ReplaceComponents(
239*6777b538SAndroid Build Coastguard Worker spec_.data(), static_cast<int>(spec_.length()), parsed_, replacements,
240*6777b538SAndroid Build Coastguard Worker NULL, &output, &result.parsed_);
241*6777b538SAndroid Build Coastguard Worker
242*6777b538SAndroid Build Coastguard Worker output.Complete();
243*6777b538SAndroid Build Coastguard Worker
244*6777b538SAndroid Build Coastguard Worker result.ProcessFileSystemURLAfterReplaceComponents();
245*6777b538SAndroid Build Coastguard Worker return result;
246*6777b538SAndroid Build Coastguard Worker }
247*6777b538SAndroid Build Coastguard Worker
248*6777b538SAndroid Build Coastguard Worker // Note: code duplicated above (it's inconvenient to use a template here).
ReplaceComponents(const ReplacementsW & replacements) const249*6777b538SAndroid Build Coastguard Worker GURL GURL::ReplaceComponents(const ReplacementsW& replacements) const {
250*6777b538SAndroid Build Coastguard Worker GURL result;
251*6777b538SAndroid Build Coastguard Worker
252*6777b538SAndroid Build Coastguard Worker // Not allowed for invalid URLs.
253*6777b538SAndroid Build Coastguard Worker if (!is_valid_)
254*6777b538SAndroid Build Coastguard Worker return GURL();
255*6777b538SAndroid Build Coastguard Worker
256*6777b538SAndroid Build Coastguard Worker url::StdStringCanonOutput output(&result.spec_);
257*6777b538SAndroid Build Coastguard Worker result.is_valid_ = url::ReplaceComponents(
258*6777b538SAndroid Build Coastguard Worker spec_.data(), static_cast<int>(spec_.length()), parsed_, replacements,
259*6777b538SAndroid Build Coastguard Worker NULL, &output, &result.parsed_);
260*6777b538SAndroid Build Coastguard Worker
261*6777b538SAndroid Build Coastguard Worker output.Complete();
262*6777b538SAndroid Build Coastguard Worker
263*6777b538SAndroid Build Coastguard Worker result.ProcessFileSystemURLAfterReplaceComponents();
264*6777b538SAndroid Build Coastguard Worker
265*6777b538SAndroid Build Coastguard Worker return result;
266*6777b538SAndroid Build Coastguard Worker }
267*6777b538SAndroid Build Coastguard Worker
ProcessFileSystemURLAfterReplaceComponents()268*6777b538SAndroid Build Coastguard Worker void GURL::ProcessFileSystemURLAfterReplaceComponents() {
269*6777b538SAndroid Build Coastguard Worker if (!is_valid_)
270*6777b538SAndroid Build Coastguard Worker return;
271*6777b538SAndroid Build Coastguard Worker if (SchemeIsFileSystem()) {
272*6777b538SAndroid Build Coastguard Worker inner_url_ = std::make_unique<GURL>(spec_.data(), parsed_.Length(),
273*6777b538SAndroid Build Coastguard Worker *parsed_.inner_parsed(), true);
274*6777b538SAndroid Build Coastguard Worker }
275*6777b538SAndroid Build Coastguard Worker }
276*6777b538SAndroid Build Coastguard Worker
DeprecatedGetOriginAsURL() const277*6777b538SAndroid Build Coastguard Worker GURL GURL::DeprecatedGetOriginAsURL() const {
278*6777b538SAndroid Build Coastguard Worker // This doesn't make sense for invalid or nonstandard URLs, so return
279*6777b538SAndroid Build Coastguard Worker // the empty URL.
280*6777b538SAndroid Build Coastguard Worker if (!is_valid_ || !IsStandard())
281*6777b538SAndroid Build Coastguard Worker return GURL();
282*6777b538SAndroid Build Coastguard Worker
283*6777b538SAndroid Build Coastguard Worker if (SchemeIsFileSystem())
284*6777b538SAndroid Build Coastguard Worker return inner_url_->DeprecatedGetOriginAsURL();
285*6777b538SAndroid Build Coastguard Worker
286*6777b538SAndroid Build Coastguard Worker Replacements replacements;
287*6777b538SAndroid Build Coastguard Worker replacements.ClearUsername();
288*6777b538SAndroid Build Coastguard Worker replacements.ClearPassword();
289*6777b538SAndroid Build Coastguard Worker replacements.ClearPath();
290*6777b538SAndroid Build Coastguard Worker replacements.ClearQuery();
291*6777b538SAndroid Build Coastguard Worker replacements.ClearRef();
292*6777b538SAndroid Build Coastguard Worker
293*6777b538SAndroid Build Coastguard Worker return ReplaceComponents(replacements);
294*6777b538SAndroid Build Coastguard Worker }
295*6777b538SAndroid Build Coastguard Worker
GetAsReferrer() const296*6777b538SAndroid Build Coastguard Worker GURL GURL::GetAsReferrer() const {
297*6777b538SAndroid Build Coastguard Worker if (!is_valid() || !IsReferrerScheme(spec_.data(), parsed_.scheme))
298*6777b538SAndroid Build Coastguard Worker return GURL();
299*6777b538SAndroid Build Coastguard Worker
300*6777b538SAndroid Build Coastguard Worker if (!has_ref() && !has_username() && !has_password())
301*6777b538SAndroid Build Coastguard Worker return GURL(*this);
302*6777b538SAndroid Build Coastguard Worker
303*6777b538SAndroid Build Coastguard Worker Replacements replacements;
304*6777b538SAndroid Build Coastguard Worker replacements.ClearRef();
305*6777b538SAndroid Build Coastguard Worker replacements.ClearUsername();
306*6777b538SAndroid Build Coastguard Worker replacements.ClearPassword();
307*6777b538SAndroid Build Coastguard Worker return ReplaceComponents(replacements);
308*6777b538SAndroid Build Coastguard Worker }
309*6777b538SAndroid Build Coastguard Worker
GetWithEmptyPath() const310*6777b538SAndroid Build Coastguard Worker GURL GURL::GetWithEmptyPath() const {
311*6777b538SAndroid Build Coastguard Worker // This doesn't make sense for invalid or nonstandard URLs, so return
312*6777b538SAndroid Build Coastguard Worker // the empty URL.
313*6777b538SAndroid Build Coastguard Worker if (!is_valid_ || !IsStandard())
314*6777b538SAndroid Build Coastguard Worker return GURL();
315*6777b538SAndroid Build Coastguard Worker
316*6777b538SAndroid Build Coastguard Worker // We could optimize this since we know that the URL is canonical, and we are
317*6777b538SAndroid Build Coastguard Worker // appending a canonical path, so avoiding re-parsing.
318*6777b538SAndroid Build Coastguard Worker GURL other(*this);
319*6777b538SAndroid Build Coastguard Worker if (parsed_.path.len == 0)
320*6777b538SAndroid Build Coastguard Worker return other;
321*6777b538SAndroid Build Coastguard Worker
322*6777b538SAndroid Build Coastguard Worker // Clear everything after the path.
323*6777b538SAndroid Build Coastguard Worker other.parsed_.query.reset();
324*6777b538SAndroid Build Coastguard Worker other.parsed_.ref.reset();
325*6777b538SAndroid Build Coastguard Worker
326*6777b538SAndroid Build Coastguard Worker // Set the path, since the path is longer than one, we can just set the
327*6777b538SAndroid Build Coastguard Worker // first character and resize.
328*6777b538SAndroid Build Coastguard Worker other.spec_[other.parsed_.path.begin] = '/';
329*6777b538SAndroid Build Coastguard Worker other.parsed_.path.len = 1;
330*6777b538SAndroid Build Coastguard Worker other.spec_.resize(other.parsed_.path.begin + 1);
331*6777b538SAndroid Build Coastguard Worker return other;
332*6777b538SAndroid Build Coastguard Worker }
333*6777b538SAndroid Build Coastguard Worker
GetWithoutFilename() const334*6777b538SAndroid Build Coastguard Worker GURL GURL::GetWithoutFilename() const {
335*6777b538SAndroid Build Coastguard Worker return Resolve(".");
336*6777b538SAndroid Build Coastguard Worker }
337*6777b538SAndroid Build Coastguard Worker
GetWithoutRef() const338*6777b538SAndroid Build Coastguard Worker GURL GURL::GetWithoutRef() const {
339*6777b538SAndroid Build Coastguard Worker if (!has_ref())
340*6777b538SAndroid Build Coastguard Worker return GURL(*this);
341*6777b538SAndroid Build Coastguard Worker
342*6777b538SAndroid Build Coastguard Worker Replacements replacements;
343*6777b538SAndroid Build Coastguard Worker replacements.ClearRef();
344*6777b538SAndroid Build Coastguard Worker return ReplaceComponents(replacements);
345*6777b538SAndroid Build Coastguard Worker }
346*6777b538SAndroid Build Coastguard Worker
IsStandard() const347*6777b538SAndroid Build Coastguard Worker bool GURL::IsStandard() const {
348*6777b538SAndroid Build Coastguard Worker return url::IsStandard(spec_.data(), parsed_.scheme);
349*6777b538SAndroid Build Coastguard Worker }
350*6777b538SAndroid Build Coastguard Worker
IsAboutBlank() const351*6777b538SAndroid Build Coastguard Worker bool GURL::IsAboutBlank() const {
352*6777b538SAndroid Build Coastguard Worker return IsAboutUrl(url::kAboutBlankPath);
353*6777b538SAndroid Build Coastguard Worker }
354*6777b538SAndroid Build Coastguard Worker
IsAboutSrcdoc() const355*6777b538SAndroid Build Coastguard Worker bool GURL::IsAboutSrcdoc() const {
356*6777b538SAndroid Build Coastguard Worker return IsAboutUrl(url::kAboutSrcdocPath);
357*6777b538SAndroid Build Coastguard Worker }
358*6777b538SAndroid Build Coastguard Worker
SchemeIs(std::string_view lower_ascii_scheme) const359*6777b538SAndroid Build Coastguard Worker bool GURL::SchemeIs(std::string_view lower_ascii_scheme) const {
360*6777b538SAndroid Build Coastguard Worker DCHECK(base::IsStringASCII(lower_ascii_scheme));
361*6777b538SAndroid Build Coastguard Worker DCHECK(base::ToLowerASCII(lower_ascii_scheme) == lower_ascii_scheme);
362*6777b538SAndroid Build Coastguard Worker
363*6777b538SAndroid Build Coastguard Worker if (!has_scheme())
364*6777b538SAndroid Build Coastguard Worker return lower_ascii_scheme.empty();
365*6777b538SAndroid Build Coastguard Worker return scheme_piece() == lower_ascii_scheme;
366*6777b538SAndroid Build Coastguard Worker }
367*6777b538SAndroid Build Coastguard Worker
SchemeIsHTTPOrHTTPS() const368*6777b538SAndroid Build Coastguard Worker bool GURL::SchemeIsHTTPOrHTTPS() const {
369*6777b538SAndroid Build Coastguard Worker return SchemeIs(url::kHttpsScheme) || SchemeIs(url::kHttpScheme);
370*6777b538SAndroid Build Coastguard Worker }
371*6777b538SAndroid Build Coastguard Worker
SchemeIsWSOrWSS() const372*6777b538SAndroid Build Coastguard Worker bool GURL::SchemeIsWSOrWSS() const {
373*6777b538SAndroid Build Coastguard Worker return SchemeIs(url::kWsScheme) || SchemeIs(url::kWssScheme);
374*6777b538SAndroid Build Coastguard Worker }
375*6777b538SAndroid Build Coastguard Worker
SchemeIsCryptographic() const376*6777b538SAndroid Build Coastguard Worker bool GURL::SchemeIsCryptographic() const {
377*6777b538SAndroid Build Coastguard Worker if (!has_scheme())
378*6777b538SAndroid Build Coastguard Worker return false;
379*6777b538SAndroid Build Coastguard Worker return SchemeIsCryptographic(scheme_piece());
380*6777b538SAndroid Build Coastguard Worker }
381*6777b538SAndroid Build Coastguard Worker
SchemeIsCryptographic(std::string_view lower_ascii_scheme)382*6777b538SAndroid Build Coastguard Worker bool GURL::SchemeIsCryptographic(std::string_view lower_ascii_scheme) {
383*6777b538SAndroid Build Coastguard Worker DCHECK(base::IsStringASCII(lower_ascii_scheme));
384*6777b538SAndroid Build Coastguard Worker DCHECK(base::ToLowerASCII(lower_ascii_scheme) == lower_ascii_scheme);
385*6777b538SAndroid Build Coastguard Worker
386*6777b538SAndroid Build Coastguard Worker return lower_ascii_scheme == url::kHttpsScheme ||
387*6777b538SAndroid Build Coastguard Worker lower_ascii_scheme == url::kWssScheme;
388*6777b538SAndroid Build Coastguard Worker }
389*6777b538SAndroid Build Coastguard Worker
SchemeIsLocal() const390*6777b538SAndroid Build Coastguard Worker bool GURL::SchemeIsLocal() const {
391*6777b538SAndroid Build Coastguard Worker // The `filesystem:` scheme is not in the Fetch spec, but Chromium still
392*6777b538SAndroid Build Coastguard Worker // supports it in large part. It should be treated as a local scheme too.
393*6777b538SAndroid Build Coastguard Worker return SchemeIs(url::kAboutScheme) || SchemeIs(url::kBlobScheme) ||
394*6777b538SAndroid Build Coastguard Worker SchemeIs(url::kDataScheme) || SchemeIs(url::kFileSystemScheme);
395*6777b538SAndroid Build Coastguard Worker }
396*6777b538SAndroid Build Coastguard Worker
IntPort() const397*6777b538SAndroid Build Coastguard Worker int GURL::IntPort() const {
398*6777b538SAndroid Build Coastguard Worker if (parsed_.port.is_nonempty())
399*6777b538SAndroid Build Coastguard Worker return url::ParsePort(spec_.data(), parsed_.port);
400*6777b538SAndroid Build Coastguard Worker return url::PORT_UNSPECIFIED;
401*6777b538SAndroid Build Coastguard Worker }
402*6777b538SAndroid Build Coastguard Worker
EffectiveIntPort() const403*6777b538SAndroid Build Coastguard Worker int GURL::EffectiveIntPort() const {
404*6777b538SAndroid Build Coastguard Worker int int_port = IntPort();
405*6777b538SAndroid Build Coastguard Worker if (int_port == url::PORT_UNSPECIFIED && IsStandard())
406*6777b538SAndroid Build Coastguard Worker return url::DefaultPortForScheme(spec_.data() + parsed_.scheme.begin,
407*6777b538SAndroid Build Coastguard Worker parsed_.scheme.len);
408*6777b538SAndroid Build Coastguard Worker return int_port;
409*6777b538SAndroid Build Coastguard Worker }
410*6777b538SAndroid Build Coastguard Worker
ExtractFileName() const411*6777b538SAndroid Build Coastguard Worker std::string GURL::ExtractFileName() const {
412*6777b538SAndroid Build Coastguard Worker url::Component file_component;
413*6777b538SAndroid Build Coastguard Worker url::ExtractFileName(spec_.data(), parsed_.path, &file_component);
414*6777b538SAndroid Build Coastguard Worker return ComponentString(file_component);
415*6777b538SAndroid Build Coastguard Worker }
416*6777b538SAndroid Build Coastguard Worker
PathForRequestPiece() const417*6777b538SAndroid Build Coastguard Worker std::string_view GURL::PathForRequestPiece() const {
418*6777b538SAndroid Build Coastguard Worker DCHECK(parsed_.path.is_nonempty())
419*6777b538SAndroid Build Coastguard Worker << "Canonical path for requests should be non-empty";
420*6777b538SAndroid Build Coastguard Worker if (parsed_.ref.is_valid()) {
421*6777b538SAndroid Build Coastguard Worker // Clip off the reference when it exists. The reference starts after the
422*6777b538SAndroid Build Coastguard Worker // #-sign, so we have to subtract one to also remove it.
423*6777b538SAndroid Build Coastguard Worker return std::string_view(spec_).substr(
424*6777b538SAndroid Build Coastguard Worker parsed_.path.begin, parsed_.ref.begin - parsed_.path.begin - 1);
425*6777b538SAndroid Build Coastguard Worker }
426*6777b538SAndroid Build Coastguard Worker // Compute the actual path length, rather than depending on the spec's
427*6777b538SAndroid Build Coastguard Worker // terminator. If we're an inner_url, our spec continues on into our outer
428*6777b538SAndroid Build Coastguard Worker // URL's path/query/ref.
429*6777b538SAndroid Build Coastguard Worker int path_len = parsed_.path.len;
430*6777b538SAndroid Build Coastguard Worker if (parsed_.query.is_valid())
431*6777b538SAndroid Build Coastguard Worker path_len = parsed_.query.end() - parsed_.path.begin;
432*6777b538SAndroid Build Coastguard Worker
433*6777b538SAndroid Build Coastguard Worker return std::string_view(spec_).substr(parsed_.path.begin, path_len);
434*6777b538SAndroid Build Coastguard Worker }
435*6777b538SAndroid Build Coastguard Worker
PathForRequest() const436*6777b538SAndroid Build Coastguard Worker std::string GURL::PathForRequest() const {
437*6777b538SAndroid Build Coastguard Worker return std::string(PathForRequestPiece());
438*6777b538SAndroid Build Coastguard Worker }
439*6777b538SAndroid Build Coastguard Worker
HostNoBrackets() const440*6777b538SAndroid Build Coastguard Worker std::string GURL::HostNoBrackets() const {
441*6777b538SAndroid Build Coastguard Worker return std::string(HostNoBracketsPiece());
442*6777b538SAndroid Build Coastguard Worker }
443*6777b538SAndroid Build Coastguard Worker
HostNoBracketsPiece() const444*6777b538SAndroid Build Coastguard Worker std::string_view GURL::HostNoBracketsPiece() const {
445*6777b538SAndroid Build Coastguard Worker // If host looks like an IPv6 literal, strip the square brackets.
446*6777b538SAndroid Build Coastguard Worker url::Component h(parsed_.host);
447*6777b538SAndroid Build Coastguard Worker if (h.len >= 2 && spec_[h.begin] == '[' && spec_[h.end() - 1] == ']') {
448*6777b538SAndroid Build Coastguard Worker h.begin++;
449*6777b538SAndroid Build Coastguard Worker h.len -= 2;
450*6777b538SAndroid Build Coastguard Worker }
451*6777b538SAndroid Build Coastguard Worker return ComponentStringPiece(h);
452*6777b538SAndroid Build Coastguard Worker }
453*6777b538SAndroid Build Coastguard Worker
GetContent() const454*6777b538SAndroid Build Coastguard Worker std::string GURL::GetContent() const {
455*6777b538SAndroid Build Coastguard Worker return std::string(GetContentPiece());
456*6777b538SAndroid Build Coastguard Worker }
457*6777b538SAndroid Build Coastguard Worker
GetContentPiece() const458*6777b538SAndroid Build Coastguard Worker std::string_view GURL::GetContentPiece() const {
459*6777b538SAndroid Build Coastguard Worker if (!is_valid_)
460*6777b538SAndroid Build Coastguard Worker return std::string_view();
461*6777b538SAndroid Build Coastguard Worker url::Component content_component = parsed_.GetContent();
462*6777b538SAndroid Build Coastguard Worker if (!SchemeIs(url::kJavaScriptScheme) && parsed_.ref.is_valid())
463*6777b538SAndroid Build Coastguard Worker content_component.len -= parsed_.ref.len + 1;
464*6777b538SAndroid Build Coastguard Worker return ComponentStringPiece(content_component);
465*6777b538SAndroid Build Coastguard Worker }
466*6777b538SAndroid Build Coastguard Worker
HostIsIPAddress() const467*6777b538SAndroid Build Coastguard Worker bool GURL::HostIsIPAddress() const {
468*6777b538SAndroid Build Coastguard Worker return is_valid_ && url::HostIsIPAddress(host_piece());
469*6777b538SAndroid Build Coastguard Worker }
470*6777b538SAndroid Build Coastguard Worker
EmptyGURL()471*6777b538SAndroid Build Coastguard Worker const GURL& GURL::EmptyGURL() {
472*6777b538SAndroid Build Coastguard Worker static base::NoDestructor<GURL> empty_gurl;
473*6777b538SAndroid Build Coastguard Worker return *empty_gurl;
474*6777b538SAndroid Build Coastguard Worker }
475*6777b538SAndroid Build Coastguard Worker
DomainIs(std::string_view canonical_domain) const476*6777b538SAndroid Build Coastguard Worker bool GURL::DomainIs(std::string_view canonical_domain) const {
477*6777b538SAndroid Build Coastguard Worker if (!is_valid_)
478*6777b538SAndroid Build Coastguard Worker return false;
479*6777b538SAndroid Build Coastguard Worker
480*6777b538SAndroid Build Coastguard Worker // FileSystem URLs have empty host_piece, so check this first.
481*6777b538SAndroid Build Coastguard Worker if (inner_url_ && SchemeIsFileSystem())
482*6777b538SAndroid Build Coastguard Worker return inner_url_->DomainIs(canonical_domain);
483*6777b538SAndroid Build Coastguard Worker return url::DomainIs(host_piece(), canonical_domain);
484*6777b538SAndroid Build Coastguard Worker }
485*6777b538SAndroid Build Coastguard Worker
EqualsIgnoringRef(const GURL & other) const486*6777b538SAndroid Build Coastguard Worker bool GURL::EqualsIgnoringRef(const GURL& other) const {
487*6777b538SAndroid Build Coastguard Worker int ref_position = parsed_.CountCharactersBefore(url::Parsed::REF, true);
488*6777b538SAndroid Build Coastguard Worker int ref_position_other =
489*6777b538SAndroid Build Coastguard Worker other.parsed_.CountCharactersBefore(url::Parsed::REF, true);
490*6777b538SAndroid Build Coastguard Worker return std::string_view(spec_).substr(0, ref_position) ==
491*6777b538SAndroid Build Coastguard Worker std::string_view(other.spec_).substr(0, ref_position_other);
492*6777b538SAndroid Build Coastguard Worker }
493*6777b538SAndroid Build Coastguard Worker
Swap(GURL * other)494*6777b538SAndroid Build Coastguard Worker void GURL::Swap(GURL* other) {
495*6777b538SAndroid Build Coastguard Worker spec_.swap(other->spec_);
496*6777b538SAndroid Build Coastguard Worker std::swap(is_valid_, other->is_valid_);
497*6777b538SAndroid Build Coastguard Worker std::swap(parsed_, other->parsed_);
498*6777b538SAndroid Build Coastguard Worker inner_url_.swap(other->inner_url_);
499*6777b538SAndroid Build Coastguard Worker }
500*6777b538SAndroid Build Coastguard Worker
EstimateMemoryUsage() const501*6777b538SAndroid Build Coastguard Worker size_t GURL::EstimateMemoryUsage() const {
502*6777b538SAndroid Build Coastguard Worker return base::trace_event::EstimateMemoryUsage(spec_) +
503*6777b538SAndroid Build Coastguard Worker base::trace_event::EstimateMemoryUsage(inner_url_) +
504*6777b538SAndroid Build Coastguard Worker (parsed_.inner_parsed() ? sizeof(url::Parsed) : 0);
505*6777b538SAndroid Build Coastguard Worker }
506*6777b538SAndroid Build Coastguard Worker
IsAboutUrl(std::string_view allowed_path) const507*6777b538SAndroid Build Coastguard Worker bool GURL::IsAboutUrl(std::string_view allowed_path) const {
508*6777b538SAndroid Build Coastguard Worker if (!SchemeIs(url::kAboutScheme))
509*6777b538SAndroid Build Coastguard Worker return false;
510*6777b538SAndroid Build Coastguard Worker
511*6777b538SAndroid Build Coastguard Worker if (has_host() || has_username() || has_password() || has_port())
512*6777b538SAndroid Build Coastguard Worker return false;
513*6777b538SAndroid Build Coastguard Worker
514*6777b538SAndroid Build Coastguard Worker return IsAboutPath(path_piece(), allowed_path);
515*6777b538SAndroid Build Coastguard Worker }
516*6777b538SAndroid Build Coastguard Worker
517*6777b538SAndroid Build Coastguard Worker // static
IsAboutPath(std::string_view actual_path,std::string_view allowed_path)518*6777b538SAndroid Build Coastguard Worker bool GURL::IsAboutPath(std::string_view actual_path,
519*6777b538SAndroid Build Coastguard Worker std::string_view allowed_path) {
520*6777b538SAndroid Build Coastguard Worker if (!base::StartsWith(actual_path, allowed_path))
521*6777b538SAndroid Build Coastguard Worker return false;
522*6777b538SAndroid Build Coastguard Worker
523*6777b538SAndroid Build Coastguard Worker if (actual_path.size() == allowed_path.size()) {
524*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(actual_path, allowed_path);
525*6777b538SAndroid Build Coastguard Worker return true;
526*6777b538SAndroid Build Coastguard Worker }
527*6777b538SAndroid Build Coastguard Worker
528*6777b538SAndroid Build Coastguard Worker if ((actual_path.size() == allowed_path.size() + 1) &&
529*6777b538SAndroid Build Coastguard Worker actual_path.back() == '/') {
530*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(actual_path, std::string(allowed_path) + '/');
531*6777b538SAndroid Build Coastguard Worker return true;
532*6777b538SAndroid Build Coastguard Worker }
533*6777b538SAndroid Build Coastguard Worker
534*6777b538SAndroid Build Coastguard Worker return false;
535*6777b538SAndroid Build Coastguard Worker }
536*6777b538SAndroid Build Coastguard Worker
WriteIntoTrace(perfetto::TracedValue context) const537*6777b538SAndroid Build Coastguard Worker void GURL::WriteIntoTrace(perfetto::TracedValue context) const {
538*6777b538SAndroid Build Coastguard Worker std::move(context).WriteString(possibly_invalid_spec());
539*6777b538SAndroid Build Coastguard Worker }
540*6777b538SAndroid Build Coastguard Worker
operator <<(std::ostream & out,const GURL & url)541*6777b538SAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& out, const GURL& url) {
542*6777b538SAndroid Build Coastguard Worker return out << url.possibly_invalid_spec();
543*6777b538SAndroid Build Coastguard Worker }
544*6777b538SAndroid Build Coastguard Worker
operator ==(const GURL & x,const GURL & y)545*6777b538SAndroid Build Coastguard Worker bool operator==(const GURL& x, const GURL& y) {
546*6777b538SAndroid Build Coastguard Worker return x.possibly_invalid_spec() == y.possibly_invalid_spec();
547*6777b538SAndroid Build Coastguard Worker }
548*6777b538SAndroid Build Coastguard Worker
operator !=(const GURL & x,const GURL & y)549*6777b538SAndroid Build Coastguard Worker bool operator!=(const GURL& x, const GURL& y) {
550*6777b538SAndroid Build Coastguard Worker return !(x == y);
551*6777b538SAndroid Build Coastguard Worker }
552*6777b538SAndroid Build Coastguard Worker
operator ==(const GURL & x,std::string_view spec)553*6777b538SAndroid Build Coastguard Worker bool operator==(const GURL& x, std::string_view spec) {
554*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(GURL(spec).possibly_invalid_spec(), spec)
555*6777b538SAndroid Build Coastguard Worker << "Comparisons of GURLs and strings must ensure as a precondition that "
556*6777b538SAndroid Build Coastguard Worker "the string is fully canonicalized.";
557*6777b538SAndroid Build Coastguard Worker return x.possibly_invalid_spec() == spec;
558*6777b538SAndroid Build Coastguard Worker }
559*6777b538SAndroid Build Coastguard Worker
operator ==(std::string_view spec,const GURL & x)560*6777b538SAndroid Build Coastguard Worker bool operator==(std::string_view spec, const GURL& x) {
561*6777b538SAndroid Build Coastguard Worker return x == spec;
562*6777b538SAndroid Build Coastguard Worker }
563*6777b538SAndroid Build Coastguard Worker
operator !=(const GURL & x,std::string_view spec)564*6777b538SAndroid Build Coastguard Worker bool operator!=(const GURL& x, std::string_view spec) {
565*6777b538SAndroid Build Coastguard Worker return !(x == spec);
566*6777b538SAndroid Build Coastguard Worker }
567*6777b538SAndroid Build Coastguard Worker
operator !=(std::string_view spec,const GURL & x)568*6777b538SAndroid Build Coastguard Worker bool operator!=(std::string_view spec, const GURL& x) {
569*6777b538SAndroid Build Coastguard Worker return !(x == spec);
570*6777b538SAndroid Build Coastguard Worker }
571*6777b538SAndroid Build Coastguard Worker
572*6777b538SAndroid Build Coastguard Worker namespace url::debug {
573*6777b538SAndroid Build Coastguard Worker
ScopedUrlCrashKey(base::debug::CrashKeyString * crash_key,const GURL & url)574*6777b538SAndroid Build Coastguard Worker ScopedUrlCrashKey::ScopedUrlCrashKey(base::debug::CrashKeyString* crash_key,
575*6777b538SAndroid Build Coastguard Worker const GURL& url)
576*6777b538SAndroid Build Coastguard Worker : scoped_string_value_(
577*6777b538SAndroid Build Coastguard Worker crash_key,
578*6777b538SAndroid Build Coastguard Worker url.is_empty() ? "<empty url>" : url.possibly_invalid_spec()) {}
579*6777b538SAndroid Build Coastguard Worker
580*6777b538SAndroid Build Coastguard Worker ScopedUrlCrashKey::~ScopedUrlCrashKey() = default;
581*6777b538SAndroid Build Coastguard Worker
582*6777b538SAndroid Build Coastguard Worker } // namespace url::debug
583