blob: fb06480ed6e54e74c881dbe4f3aa4ea9780a8907 [file] [log] [blame]
[email protected]51bcc5d2013-04-24 01:41:371// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
[email protected]e7bba5f82013-04-10 20:10:524
avic0c60312015-12-21 21:03:505#include "url/gurl.h"
6
7#include <stddef.h>
[email protected]e7bba5f82013-04-10 20:10:528
9#include <algorithm>
10#include <ostream>
Lukasz Anforowicz0bc073e2019-06-14 19:41:5211#include <utility>
[email protected]e7bba5f82013-04-10 20:10:5212
[email protected]e7bba5f82013-04-10 20:10:5213#include "base/logging.h"
Victor Vasiliev6a2bb592019-08-19 23:03:1714#include "base/no_destructor.h"
qyearsley7ffaa682015-08-03 07:03:4915#include "base/strings/string_piece.h"
brettwbc17d2c82015-06-09 22:39:0816#include "base/strings/string_util.h"
dskiba3bc10ee82017-02-01 01:22:1917#include "base/trace_event/memory_usage_estimator.h"
[email protected]318076b2013-04-18 21:19:4518#include "url/url_canon_stdstring.h"
19#include "url/url_util.h"
[email protected]e7bba5f82013-04-10 20:10:5220
[email protected]e05d81f2013-10-22 21:20:3121GURL::GURL() : is_valid_(false) {
[email protected]e7bba5f82013-04-10 20:10:5222}
23
24GURL::GURL(const GURL& other)
25 : spec_(other.spec_),
26 is_valid_(other.is_valid_),
[email protected]e05d81f2013-10-22 21:20:3127 parsed_(other.parsed_) {
[email protected]e7bba5f82013-04-10 20:10:5228 if (other.inner_url_)
[email protected]e05d81f2013-10-22 21:20:3129 inner_url_.reset(new GURL(*other.inner_url_));
[email protected]e7bba5f82013-04-10 20:10:5230 // Valid filesystem urls should always have an inner_url_.
31 DCHECK(!is_valid_ || !SchemeIsFileSystem() || inner_url_);
32}
33
brettwf78cc272017-03-24 16:36:4234GURL::GURL(GURL&& other) noexcept
sclittle376085b32017-03-14 21:08:4135 : spec_(std::move(other.spec_)),
36 is_valid_(other.is_valid_),
37 parsed_(other.parsed_),
38 inner_url_(std::move(other.inner_url_)) {
39 other.is_valid_ = false;
40 other.parsed_ = url::Parsed();
41}
42
brettwdfbcc3b2016-01-20 01:49:1743GURL::GURL(base::StringPiece url_string) {
[email protected]369e84f72013-11-23 01:53:5244 InitCanonical(url_string, true);
[email protected]e7bba5f82013-04-10 20:10:5245}
46
brettwdfbcc3b2016-01-20 01:49:1747GURL::GURL(base::StringPiece16 url_string) {
[email protected]369e84f72013-11-23 01:53:5248 InitCanonical(url_string, true);
49}
50
51GURL::GURL(const std::string& url_string, RetainWhiteSpaceSelector) {
brettwdfbcc3b2016-01-20 01:49:1752 InitCanonical(base::StringPiece(url_string), false);
[email protected]e7bba5f82013-04-10 20:10:5253}
54
[email protected]0318f922014-04-22 00:09:2355GURL::GURL(const char* canonical_spec,
56 size_t canonical_spec_len,
57 const url::Parsed& parsed,
58 bool is_valid)
[email protected]e7bba5f82013-04-10 20:10:5259 : spec_(canonical_spec, canonical_spec_len),
60 is_valid_(is_valid),
[email protected]e05d81f2013-10-22 21:20:3161 parsed_(parsed) {
[email protected]19b61f972013-07-26 13:30:0962 InitializeFromCanonicalSpec();
63}
64
[email protected]0318f922014-04-22 00:09:2365GURL::GURL(std::string canonical_spec, const url::Parsed& parsed, bool is_valid)
ki.stfucebea5e2016-06-04 07:05:3666 : spec_(std::move(canonical_spec)), is_valid_(is_valid), parsed_(parsed) {
[email protected]19b61f972013-07-26 13:30:0967 InitializeFromCanonicalSpec();
68}
69
[email protected]369e84f72013-11-23 01:53:5270template<typename STR>
brettwdfbcc3b2016-01-20 01:49:1771void GURL::InitCanonical(base::BasicStringPiece<STR> input_spec,
72 bool trim_path_end) {
[email protected]0318f922014-04-22 00:09:2373 url::StdStringCanonOutput output(&spec_);
74 is_valid_ = url::Canonicalize(
[email protected]369e84f72013-11-23 01:53:5275 input_spec.data(), static_cast<int>(input_spec.length()), trim_path_end,
76 NULL, &output, &parsed_);
77
78 output.Complete(); // Must be done before using string.
79 if (is_valid_ && SchemeIsFileSystem()) {
80 inner_url_.reset(new GURL(spec_.data(), parsed_.Length(),
81 *parsed_.inner_parsed(), true));
82 }
csharrison475851da2016-12-17 02:19:4283 // Valid URLs always have non-empty specs.
84 DCHECK(!is_valid_ || !spec_.empty());
[email protected]369e84f72013-11-23 01:53:5285}
86
[email protected]19b61f972013-07-26 13:30:0987void GURL::InitializeFromCanonicalSpec() {
[email protected]e7bba5f82013-04-10 20:10:5288 if (is_valid_ && SchemeIsFileSystem()) {
[email protected]e05d81f2013-10-22 21:20:3189 inner_url_.reset(
90 new GURL(spec_.data(), parsed_.Length(),
91 *parsed_.inner_parsed(), true));
[email protected]e7bba5f82013-04-10 20:10:5292 }
93
94#ifndef NDEBUG
95 // For testing purposes, check that the parsed canonical URL is identical to
96 // what we would have produced. Skip checking for invalid URLs have no meaning
qyearsley2bc727d2015-08-14 20:17:1597 // and we can't always canonicalize then reproducibly.
[email protected]e7bba5f82013-04-10 20:10:5298 if (is_valid_) {
csharrison475851da2016-12-17 02:19:4299 DCHECK(!spec_.empty());
[email protected]0318f922014-04-22 00:09:23100 url::Component scheme;
[email protected]369e84f72013-11-23 01:53:52101 // We can't do this check on the inner_url of a filesystem URL, as
102 // canonical_spec actually points to the start of the outer URL, so we'd
103 // end up with infinite recursion in this constructor.
[email protected]0318f922014-04-22 00:09:23104 if (!url::FindAndCompareScheme(spec_.data(), spec_.length(),
[email protected]08dc7052014-06-18 07:57:49105 url::kFileSystemScheme, &scheme) ||
[email protected]19b61f972013-07-26 13:30:09106 scheme.begin == parsed_.scheme.begin) {
[email protected]369e84f72013-11-23 01:53:52107 // We need to retain trailing whitespace on path URLs, as the |parsed_|
108 // spec we originally received may legitimately contain trailing white-
109 // space on the path or components e.g. if the #ref has been
110 // removed from a "foo:hello #ref" URL (see http://crbug.com/291747).
111 GURL test_url(spec_, RETAIN_TRAILING_PATH_WHITEPACE);
[email protected]e7bba5f82013-04-10 20:10:52112
113 DCHECK(test_url.is_valid_ == is_valid_);
114 DCHECK(test_url.spec_ == spec_);
115
116 DCHECK(test_url.parsed_.scheme == parsed_.scheme);
117 DCHECK(test_url.parsed_.username == parsed_.username);
118 DCHECK(test_url.parsed_.password == parsed_.password);
119 DCHECK(test_url.parsed_.host == parsed_.host);
120 DCHECK(test_url.parsed_.port == parsed_.port);
121 DCHECK(test_url.parsed_.path == parsed_.path);
122 DCHECK(test_url.parsed_.query == parsed_.query);
123 DCHECK(test_url.parsed_.ref == parsed_.ref);
124 }
125 }
126#endif
127}
128
Chris Watkins3e06be12017-11-29 01:40:54129GURL::~GURL() = default;
[email protected]e7bba5f82013-04-10 20:10:52130
sclittle376085b32017-03-14 21:08:41131GURL& GURL::operator=(const GURL& other) {
132 spec_ = other.spec_;
133 is_valid_ = other.is_valid_;
134 parsed_ = other.parsed_;
135
136 if (!other.inner_url_)
137 inner_url_.reset();
138 else if (inner_url_)
139 *inner_url_ = *other.inner_url_;
140 else
141 inner_url_.reset(new GURL(*other.inner_url_));
142
143 return *this;
144}
145
Jüri Valdmannf841ac22018-05-18 22:36:28146GURL& GURL::operator=(GURL&& other) noexcept {
sclittle376085b32017-03-14 21:08:41147 spec_ = std::move(other.spec_);
148 is_valid_ = other.is_valid_;
149 parsed_ = other.parsed_;
150 inner_url_ = std::move(other.inner_url_);
151
152 other.is_valid_ = false;
153 other.parsed_ = url::Parsed();
[email protected]e7bba5f82013-04-10 20:10:52154 return *this;
155}
156
157const std::string& GURL::spec() const {
158 if (is_valid_ || spec_.empty())
159 return spec_;
160
161 DCHECK(false) << "Trying to get the spec of an invalid URL!";
Daniel Cheng0a9188d92018-08-04 04:48:23162 return base::EmptyString();
[email protected]e7bba5f82013-04-10 20:10:52163}
164
dcheng3a088772014-12-06 09:58:21165bool GURL::operator<(const GURL& other) const {
166 return spec_ < other.spec_;
167}
168
169bool GURL::operator>(const GURL& other) const {
170 return spec_ > other.spec_;
171}
172
[email protected]e7bba5f82013-04-10 20:10:52173// Note: code duplicated below (it's inconvenient to use a template here).
Victor Costane7732162018-08-30 18:29:40174GURL GURL::Resolve(base::StringPiece relative) const {
[email protected]e7bba5f82013-04-10 20:10:52175 // Not allowed for invalid URLs.
176 if (!is_valid_)
177 return GURL();
178
179 GURL result;
[email protected]0318f922014-04-22 00:09:23180 url::StdStringCanonOutput output(&result.spec_);
[email protected]0318f922014-04-22 00:09:23181 if (!url::ResolveRelative(spec_.data(), static_cast<int>(spec_.length()),
182 parsed_, relative.data(),
183 static_cast<int>(relative.length()),
mkwst45f25db2015-07-21 04:03:50184 nullptr, &output, &result.parsed_)) {
[email protected]e7bba5f82013-04-10 20:10:52185 // Error resolving, return an empty URL.
186 return GURL();
187 }
188
189 output.Complete();
190 result.is_valid_ = true;
191 if (result.SchemeIsFileSystem()) {
[email protected]e05d81f2013-10-22 21:20:31192 result.inner_url_.reset(
193 new GURL(result.spec_.data(), result.parsed_.Length(),
194 *result.parsed_.inner_parsed(), true));
[email protected]e7bba5f82013-04-10 20:10:52195 }
196 return result;
197}
198
199// Note: code duplicated above (it's inconvenient to use a template here).
Victor Costane7732162018-08-30 18:29:40200GURL GURL::Resolve(base::StringPiece16 relative) const {
[email protected]e7bba5f82013-04-10 20:10:52201 // Not allowed for invalid URLs.
202 if (!is_valid_)
203 return GURL();
204
205 GURL result;
[email protected]0318f922014-04-22 00:09:23206 url::StdStringCanonOutput output(&result.spec_);
[email protected]0318f922014-04-22 00:09:23207 if (!url::ResolveRelative(spec_.data(), static_cast<int>(spec_.length()),
208 parsed_, relative.data(),
209 static_cast<int>(relative.length()),
mkwst45f25db2015-07-21 04:03:50210 nullptr, &output, &result.parsed_)) {
[email protected]e7bba5f82013-04-10 20:10:52211 // Error resolving, return an empty URL.
212 return GURL();
213 }
214
215 output.Complete();
216 result.is_valid_ = true;
217 if (result.SchemeIsFileSystem()) {
[email protected]e05d81f2013-10-22 21:20:31218 result.inner_url_.reset(
219 new GURL(result.spec_.data(), result.parsed_.Length(),
220 *result.parsed_.inner_parsed(), true));
[email protected]e7bba5f82013-04-10 20:10:52221 }
222 return result;
223}
224
225// Note: code duplicated below (it's inconvenient to use a template here).
226GURL GURL::ReplaceComponents(
[email protected]0318f922014-04-22 00:09:23227 const url::Replacements<char>& replacements) const {
[email protected]e7bba5f82013-04-10 20:10:52228 GURL result;
229
230 // Not allowed for invalid URLs.
231 if (!is_valid_)
232 return GURL();
233
[email protected]0318f922014-04-22 00:09:23234 url::StdStringCanonOutput output(&result.spec_);
[email protected]0318f922014-04-22 00:09:23235 result.is_valid_ = url::ReplaceComponents(
[email protected]e7bba5f82013-04-10 20:10:52236 spec_.data(), static_cast<int>(spec_.length()), parsed_, replacements,
237 NULL, &output, &result.parsed_);
238
239 output.Complete();
240 if (result.is_valid_ && result.SchemeIsFileSystem()) {
mmenke73cea7e4a2016-06-13 19:04:57241 result.inner_url_.reset(new GURL(result.spec_.data(),
242 result.parsed_.Length(),
[email protected]e05d81f2013-10-22 21:20:31243 *result.parsed_.inner_parsed(), true));
[email protected]e7bba5f82013-04-10 20:10:52244 }
245 return result;
246}
247
248// Note: code duplicated above (it's inconvenient to use a template here).
249GURL GURL::ReplaceComponents(
[email protected]0318f922014-04-22 00:09:23250 const url::Replacements<base::char16>& replacements) const {
[email protected]e7bba5f82013-04-10 20:10:52251 GURL result;
252
253 // Not allowed for invalid URLs.
254 if (!is_valid_)
255 return GURL();
256
[email protected]0318f922014-04-22 00:09:23257 url::StdStringCanonOutput output(&result.spec_);
[email protected]0318f922014-04-22 00:09:23258 result.is_valid_ = url::ReplaceComponents(
[email protected]e7bba5f82013-04-10 20:10:52259 spec_.data(), static_cast<int>(spec_.length()), parsed_, replacements,
260 NULL, &output, &result.parsed_);
261
262 output.Complete();
263 if (result.is_valid_ && result.SchemeIsFileSystem()) {
mmenke73cea7e4a2016-06-13 19:04:57264 result.inner_url_.reset(new GURL(result.spec_.data(),
265 result.parsed_.Length(),
[email protected]e05d81f2013-10-22 21:20:31266 *result.parsed_.inner_parsed(), true));
[email protected]e7bba5f82013-04-10 20:10:52267 }
268 return result;
269}
270
271GURL GURL::GetOrigin() const {
272 // This doesn't make sense for invalid or nonstandard URLs, so return
qyearsley2bc727d2015-08-14 20:17:15273 // the empty URL.
[email protected]e7bba5f82013-04-10 20:10:52274 if (!is_valid_ || !IsStandard())
275 return GURL();
276
277 if (SchemeIsFileSystem())
278 return inner_url_->GetOrigin();
279
[email protected]0318f922014-04-22 00:09:23280 url::Replacements<char> replacements;
[email protected]e7bba5f82013-04-10 20:10:52281 replacements.ClearUsername();
282 replacements.ClearPassword();
283 replacements.ClearPath();
284 replacements.ClearQuery();
285 replacements.ClearRef();
286
287 return ReplaceComponents(replacements);
288}
289
[email protected]6b775ee2014-03-20 20:27:25290GURL GURL::GetAsReferrer() const {
lizeb5120f6dc2016-02-19 09:29:44291 if (!SchemeIsValidForReferrer())
jochen42450392014-11-24 19:47:22292 return GURL();
293
294 if (!has_ref() && !has_username() && !has_password())
[email protected]6b775ee2014-03-20 20:27:25295 return GURL(*this);
296
[email protected]0318f922014-04-22 00:09:23297 url::Replacements<char> replacements;
[email protected]6b775ee2014-03-20 20:27:25298 replacements.ClearRef();
299 replacements.ClearUsername();
300 replacements.ClearPassword();
301 return ReplaceComponents(replacements);
302}
303
[email protected]e7bba5f82013-04-10 20:10:52304GURL GURL::GetWithEmptyPath() const {
305 // This doesn't make sense for invalid or nonstandard URLs, so return
306 // the empty URL.
307 if (!is_valid_ || !IsStandard())
308 return GURL();
309
310 // We could optimize this since we know that the URL is canonical, and we are
311 // appending a canonical path, so avoiding re-parsing.
312 GURL other(*this);
313 if (parsed_.path.len == 0)
314 return other;
315
316 // Clear everything after the path.
317 other.parsed_.query.reset();
318 other.parsed_.ref.reset();
319
320 // Set the path, since the path is longer than one, we can just set the
321 // first character and resize.
322 other.spec_[other.parsed_.path.begin] = '/';
323 other.parsed_.path.len = 1;
324 other.spec_.resize(other.parsed_.path.begin + 1);
325 return other;
326}
327
Giovanni Ortuño Urquidi61b24eda2017-08-09 08:13:10328GURL GURL::GetWithoutFilename() const {
329 return Resolve(".");
330}
331
[email protected]e7bba5f82013-04-10 20:10:52332bool GURL::IsStandard() const {
[email protected]0318f922014-04-22 00:09:23333 return url::IsStandard(spec_.data(), parsed_.scheme);
[email protected]e7bba5f82013-04-10 20:10:52334}
335
clamy12bca18b2017-02-10 15:33:07336bool GURL::IsAboutBlank() const {
Lukasz Anforowicz0bc073e2019-06-14 19:41:52337 return IsAboutUrl(url::kAboutBlankPath);
338}
clamy12bca18b2017-02-10 15:33:07339
Lukasz Anforowicz0bc073e2019-06-14 19:41:52340bool GURL::IsAboutSrcdoc() const {
341 return IsAboutUrl(url::kAboutSrcdocPath);
clamy12bca18b2017-02-10 15:33:07342}
343
brettwadc846882015-09-25 01:16:22344bool GURL::SchemeIs(base::StringPiece lower_ascii_scheme) const {
345 DCHECK(base::IsStringASCII(lower_ascii_scheme));
346 DCHECK(base::ToLowerASCII(lower_ascii_scheme) == lower_ascii_scheme);
347
[email protected]e7bba5f82013-04-10 20:10:52348 if (parsed_.scheme.len <= 0)
brettwadc846882015-09-25 01:16:22349 return lower_ascii_scheme.empty();
350 return scheme_piece() == lower_ascii_scheme;
[email protected]e7bba5f82013-04-10 20:10:52351}
352
[email protected]91f5689032013-08-22 01:43:33353bool GURL::SchemeIsHTTPOrHTTPS() const {
[email protected]9d5877e2014-06-02 07:34:35354 return SchemeIs(url::kHttpScheme) || SchemeIs(url::kHttpsScheme);
[email protected]91f5689032013-08-22 01:43:33355}
356
lizeb5120f6dc2016-02-19 09:29:44357bool GURL::SchemeIsValidForReferrer() const {
358 return is_valid_ && IsReferrerScheme(spec_.data(), parsed_.scheme);
359}
360
[email protected]9690b992013-11-22 07:40:46361bool GURL::SchemeIsWSOrWSS() const {
[email protected]9d5877e2014-06-02 07:34:35362 return SchemeIs(url::kWsScheme) || SchemeIs(url::kWssScheme);
[email protected]9690b992013-11-22 07:40:46363}
364
Maks Orlovich44525ce2019-02-25 14:17:58365bool GURL::SchemeIsCryptographic() const {
366 if (parsed_.scheme.len <= 0)
367 return false;
368 return SchemeIsCryptographic(scheme_piece());
369}
370
371bool GURL::SchemeIsCryptographic(base::StringPiece lower_ascii_scheme) {
372 DCHECK(base::IsStringASCII(lower_ascii_scheme));
373 DCHECK(base::ToLowerASCII(lower_ascii_scheme) == lower_ascii_scheme);
374
375 return lower_ascii_scheme == url::kHttpsScheme ||
376 lower_ascii_scheme == url::kWssScheme;
377}
378
[email protected]e7bba5f82013-04-10 20:10:52379int GURL::IntPort() const {
380 if (parsed_.port.is_nonempty())
[email protected]0318f922014-04-22 00:09:23381 return url::ParsePort(spec_.data(), parsed_.port);
382 return url::PORT_UNSPECIFIED;
[email protected]e7bba5f82013-04-10 20:10:52383}
384
385int GURL::EffectiveIntPort() const {
386 int int_port = IntPort();
[email protected]0318f922014-04-22 00:09:23387 if (int_port == url::PORT_UNSPECIFIED && IsStandard())
388 return url::DefaultPortForScheme(spec_.data() + parsed_.scheme.begin,
389 parsed_.scheme.len);
[email protected]e7bba5f82013-04-10 20:10:52390 return int_port;
391}
392
393std::string GURL::ExtractFileName() const {
[email protected]0318f922014-04-22 00:09:23394 url::Component file_component;
395 url::ExtractFileName(spec_.data(), parsed_.path, &file_component);
[email protected]e7bba5f82013-04-10 20:10:52396 return ComponentString(file_component);
397}
398
David Van Cleve5f374442019-11-06 15:01:17399base::StringPiece GURL::PathForRequestPiece() const {
qyearsley2bc727d2015-08-14 20:17:15400 DCHECK(parsed_.path.len > 0)
401 << "Canonical path for requests should be non-empty";
[email protected]e7bba5f82013-04-10 20:10:52402 if (parsed_.ref.len >= 0) {
qyearsley2bc727d2015-08-14 20:17:15403 // Clip off the reference when it exists. The reference starts after the
404 // #-sign, so we have to subtract one to also remove it.
David Van Cleve5f374442019-11-06 15:01:17405 return base::StringPiece(&spec_[parsed_.path.begin],
406 parsed_.ref.begin - parsed_.path.begin - 1);
[email protected]e7bba5f82013-04-10 20:10:52407 }
408 // Compute the actual path length, rather than depending on the spec's
qyearsley2bc727d2015-08-14 20:17:15409 // terminator. If we're an inner_url, our spec continues on into our outer
410 // URL's path/query/ref.
[email protected]e7bba5f82013-04-10 20:10:52411 int path_len = parsed_.path.len;
412 if (parsed_.query.is_valid())
413 path_len = parsed_.query.end() - parsed_.path.begin;
414
David Van Cleve5f374442019-11-06 15:01:17415 return base::StringPiece(&spec_[parsed_.path.begin], path_len);
416}
417
418std::string GURL::PathForRequest() const {
419 return PathForRequestPiece().as_string();
[email protected]e7bba5f82013-04-10 20:10:52420}
421
422std::string GURL::HostNoBrackets() const {
ricea1c0de2f2017-07-03 08:21:43423 return HostNoBracketsPiece().as_string();
424}
425
426base::StringPiece GURL::HostNoBracketsPiece() const {
[email protected]e7bba5f82013-04-10 20:10:52427 // If host looks like an IPv6 literal, strip the square brackets.
[email protected]0318f922014-04-22 00:09:23428 url::Component h(parsed_.host);
[email protected]e7bba5f82013-04-10 20:10:52429 if (h.len >= 2 && spec_[h.begin] == '[' && spec_[h.end() - 1] == ']') {
430 h.begin++;
431 h.len -= 2;
432 }
ricea1c0de2f2017-07-03 08:21:43433 return ComponentStringPiece(h);
[email protected]e7bba5f82013-04-10 20:10:52434}
435
[email protected]5f50c5d2013-10-24 19:05:17436std::string GURL::GetContent() const {
Stephen McGruerb52ebdc2018-10-31 22:06:04437 if (!is_valid_)
438 return std::string();
439 std::string content = ComponentString(parsed_.GetContent());
440 if (!SchemeIs(url::kJavaScriptScheme) && parsed_.ref.len >= 0)
441 content.erase(content.size() - parsed_.ref.len - 1);
442 return content;
[email protected]5f50c5d2013-10-24 19:05:17443}
444
[email protected]e7bba5f82013-04-10 20:10:52445bool GURL::HostIsIPAddress() const {
csharrison475851da2016-12-17 02:19:42446 return is_valid_ && url::HostIsIPAddress(host_piece());
[email protected]e7bba5f82013-04-10 20:10:52447}
448
[email protected]e7bba5f82013-04-10 20:10:52449const GURL& GURL::EmptyGURL() {
Victor Vasiliev6a2bb592019-08-19 23:03:17450 static base::NoDestructor<GURL> empty_gurl;
451 return *empty_gurl;
[email protected]e7bba5f82013-04-10 20:10:52452}
453
Charles Harrison81dc2fb2017-08-30 23:41:12454bool GURL::DomainIs(base::StringPiece canonical_domain) const {
pkalinnikov054f4032016-08-31 10:54:17455 if (!is_valid_)
[email protected]e7bba5f82013-04-10 20:10:52456 return false;
457
pkalinnikov054f4032016-08-31 10:54:17458 // FileSystem URLs have empty host_piece, so check this first.
Charles Harrison81dc2fb2017-08-30 23:41:12459 if (inner_url_ && SchemeIsFileSystem())
460 return inner_url_->DomainIs(canonical_domain);
461 return url::DomainIs(host_piece(), canonical_domain);
[email protected]e7bba5f82013-04-10 20:10:52462}
463
arthursonzogni9c873d8c2017-02-08 17:58:05464bool GURL::EqualsIgnoringRef(const GURL& other) const {
465 int ref_position = parsed_.CountCharactersBefore(url::Parsed::REF, true);
466 int ref_position_other =
467 other.parsed_.CountCharactersBefore(url::Parsed::REF, true);
468 return base::StringPiece(spec_).substr(0, ref_position) ==
469 base::StringPiece(other.spec_).substr(0, ref_position_other);
470}
471
[email protected]e7bba5f82013-04-10 20:10:52472void GURL::Swap(GURL* other) {
473 spec_.swap(other->spec_);
474 std::swap(is_valid_, other->is_valid_);
475 std::swap(parsed_, other->parsed_);
[email protected]e05d81f2013-10-22 21:20:31476 inner_url_.swap(other->inner_url_);
[email protected]e7bba5f82013-04-10 20:10:52477}
478
dskiba3bc10ee82017-02-01 01:22:19479size_t GURL::EstimateMemoryUsage() const {
480 return base::trace_event::EstimateMemoryUsage(spec_) +
481 base::trace_event::EstimateMemoryUsage(inner_url_) +
482 (parsed_.inner_parsed() ? sizeof(url::Parsed) : 0);
483}
484
Lukasz Anforowicz0bc073e2019-06-14 19:41:52485bool GURL::IsAboutUrl(base::StringPiece allowed_path) const {
486 if (!SchemeIs(url::kAboutScheme))
487 return false;
488
489 if (has_host() || has_username() || has_password() || has_port())
490 return false;
491
492 if (!path_piece().starts_with(allowed_path))
493 return false;
494
495 if (path_piece().size() == allowed_path.size()) {
496 DCHECK_EQ(path_piece(), allowed_path);
497 return true;
498 }
499
500 if ((path_piece().size() == allowed_path.size() + 1) &&
501 path_piece().back() == '/') {
502 DCHECK_EQ(path_piece(), allowed_path.as_string() + '/');
503 return true;
504 }
505
506 return false;
507}
508
[email protected]e7bba5f82013-04-10 20:10:52509std::ostream& operator<<(std::ostream& out, const GURL& url) {
510 return out << url.possibly_invalid_spec();
511}
csharrisonebeca8e2016-10-18 02:35:36512
513bool operator==(const GURL& x, const GURL& y) {
514 return x.possibly_invalid_spec() == y.possibly_invalid_spec();
515}
516
517bool operator!=(const GURL& x, const GURL& y) {
518 return !(x == y);
519}
520
521bool operator==(const GURL& x, const base::StringPiece& spec) {
cfredric370250a2016-11-15 22:38:56522 DCHECK_EQ(GURL(spec).possibly_invalid_spec(), spec);
csharrisonebeca8e2016-10-18 02:35:36523 return x.possibly_invalid_spec() == spec;
524}
525
Andrew Moylan892964682017-10-10 07:09:28526bool operator==(const base::StringPiece& spec, const GURL& x) {
527 return x == spec;
528}
529
csharrisonebeca8e2016-10-18 02:35:36530bool operator!=(const GURL& x, const base::StringPiece& spec) {
531 return !(x == spec);
532}
Andrew Moylan892964682017-10-10 07:09:28533
534bool operator!=(const base::StringPiece& spec, const GURL& x) {
535 return !(x == spec);
536}