Avi Drissman | 3e1a26c | 2022-09-15 20:26:03 | [diff] [blame] | 1 | // Copyright 2015 The Chromium Authors |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "url/scheme_host_port.h" |
| 6 | |
avi | c0c6031 | 2015-12-21 21:03:50 | [diff] [blame] | 7 | #include <stdint.h> |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 8 | #include <string.h> |
| 9 | |
Chris Fredrickson | 29f143f | 2025-01-17 17:42:29 | [diff] [blame] | 10 | #include <compare> |
Tom Sepez | b03f3f8 | 2021-12-09 23:43:38 | [diff] [blame] | 11 | #include <ostream> |
David Benjamin | bf75caf | 2023-09-29 04:39:59 | [diff] [blame] | 12 | #include <string_view> |
jsbell | 938b025 | 2015-11-30 23:17:41 | [diff] [blame] | 13 | #include <tuple> |
| 14 | |
Hans Wennborg | 0e22368 | 2020-04-27 21:51:29 | [diff] [blame] | 15 | #include "base/check_op.h" |
Jan Wilken Dörrie | 721926d | 2020-12-09 23:57:47 | [diff] [blame] | 16 | #include "base/containers/contains.h" |
Hans Wennborg | 0e22368 | 2020-04-27 21:51:29 | [diff] [blame] | 17 | #include "base/notreached.h" |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 18 | #include "base/numerics/safe_conversions.h" |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 19 | #include "base/strings/string_number_conversions.h" |
Xiaochen Zhou | 4350e46 | 2023-08-21 15:06:12 | [diff] [blame] | 20 | #include "base/trace_event/memory_usage_estimator.h" |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 21 | #include "url/gurl.h" |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 22 | #include "url/third_party/mozilla/url_parse.h" |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 23 | #include "url/url_canon.h" |
| 24 | #include "url/url_canon_stdstring.h" |
| 25 | #include "url/url_constants.h" |
Hayato Ito | cddb0878 | 2024-03-13 01:02:24 | [diff] [blame] | 26 | #include "url/url_features.h" |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 27 | #include "url/url_util.h" |
| 28 | |
| 29 | namespace url { |
| 30 | |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 31 | namespace { |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 32 | |
Daniel Clark | dc91684 | 2024-10-08 18:28:19 | [diff] [blame] | 33 | bool IsCanonicalHost(std::string_view host, bool is_file_scheme) { |
msramek | 9b7972dd | 2015-08-18 13:04:19 | [diff] [blame] | 34 | std::string canon_host; |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 35 | |
| 36 | // Try to canonicalize the host (copy/pasted from net/base. :( ). |
| 37 | const Component raw_host_component(0, |
| 38 | base::checked_cast<int>(host.length())); |
| 39 | StdStringCanonOutput canon_host_output(&canon_host); |
| 40 | CanonHostInfo host_info; |
Daniel Clark | dc91684 | 2024-10-08 18:28:19 | [diff] [blame] | 41 | if (is_file_scheme) { |
| 42 | CanonicalizeFileHostVerbose(host.data(), raw_host_component, |
| 43 | canon_host_output, host_info); |
| 44 | } else { |
| 45 | CanonicalizeSpecialHostVerbose(host.data(), raw_host_component, |
| 46 | canon_host_output, host_info); |
| 47 | } |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 48 | |
| 49 | if (host_info.out_host.is_nonempty() && |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 50 | host_info.family != CanonHostInfo::BROKEN) { |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 51 | // Success! Assert that there's no extra garbage. |
| 52 | canon_host_output.Complete(); |
| 53 | DCHECK_EQ(host_info.out_host.len, static_cast<int>(canon_host.length())); |
| 54 | } else { |
| 55 | // Empty host, or canonicalization failed. |
| 56 | canon_host.clear(); |
| 57 | } |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 58 | |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 59 | return host == canon_host; |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 60 | } |
| 61 | |
Lukasz Anforowicz | 6a6a05d | 2021-01-12 01:40:07 | [diff] [blame] | 62 | // Note: When changing IsValidInput, consider also updating |
| 63 | // ShouldTreatAsOpaqueOrigin in Blink (there might be existing differences in |
| 64 | // behavior between these 2 layers, but we should avoid introducing new |
| 65 | // differences). |
Daniel Cheng | 3462e2a6 | 2024-09-13 01:23:21 | [diff] [blame] | 66 | bool IsValidInput(std::string_view scheme, |
| 67 | std::string_view host, |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 68 | uint16_t port, |
| 69 | SchemeHostPort::ConstructPolicy policy) { |
Daniel Cheng | c2b752b | 2018-11-28 00:03:29 | [diff] [blame] | 70 | // Empty schemes are never valid. |
| 71 | if (scheme.empty()) |
| 72 | return false; |
| 73 | |
Lukasz Anforowicz | 6a6a05d | 2021-01-12 01:40:07 | [diff] [blame] | 74 | // about:blank and other no-access schemes translate into an opaque origin. |
| 75 | // This helps consistency with ShouldTreatAsOpaqueOrigin in Blink. |
| 76 | if (base::Contains(GetNoAccessSchemes(), scheme)) |
| 77 | return false; |
| 78 | |
Nick Carter | 123ca19 | 2018-03-30 23:25:36 | [diff] [blame] | 79 | SchemeType scheme_type = SCHEME_WITH_HOST_PORT_AND_USER_INFORMATION; |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 80 | bool is_standard = GetStandardSchemeType( |
| 81 | scheme.data(), |
| 82 | Component(0, base::checked_cast<int>(scheme.length())), |
| 83 | &scheme_type); |
Nick Carter | 8aa718ed | 2018-09-07 21:39:51 | [diff] [blame] | 84 | if (!is_standard) { |
Lukasz Anforowicz | 6a6a05d | 2021-01-12 01:40:07 | [diff] [blame] | 85 | // To be consistent with ShouldTreatAsOpaqueOrigin in Blink, local |
| 86 | // non-standard schemes are currently allowed to be tuple origins. |
Nick Carter | 8aa718ed | 2018-09-07 21:39:51 | [diff] [blame] | 87 | // |
| 88 | // TODO: Migrate "content:" and "externalfile:" to be standard schemes, and |
| 89 | // remove this local scheme exception. |
Hayato Ito | cddb0878 | 2024-03-13 01:02:24 | [diff] [blame] | 90 | if (url::IsUsingStandardCompliantNonSpecialSchemeURLParsing()) { |
| 91 | // If the flag is enabled, a host can be empty for non-special URLs. |
| 92 | // Therefore, we don't check a host nor port. |
| 93 | if (base::Contains(GetLocalSchemes(), scheme)) { |
| 94 | return true; |
| 95 | } |
| 96 | } else { |
| 97 | if (base::Contains(GetLocalSchemes(), scheme) && host.empty() && |
| 98 | port == 0) { |
| 99 | return true; |
| 100 | } |
| 101 | } |
Daniel Cheng | c2b752b | 2018-11-28 00:03:29 | [diff] [blame] | 102 | |
| 103 | // Otherwise, allow non-standard schemes only if the Android WebView |
| 104 | // workaround is enabled. |
| 105 | return AllowNonStandardSchemesForAndroidWebView(); |
Nick Carter | 8aa718ed | 2018-09-07 21:39:51 | [diff] [blame] | 106 | } |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 107 | |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 108 | switch (scheme_type) { |
Nick Carter | ff69a10 | 2018-04-04 00:15:17 | [diff] [blame] | 109 | case SCHEME_WITH_HOST_AND_PORT: |
Nick Carter | 123ca19 | 2018-03-30 23:25:36 | [diff] [blame] | 110 | case SCHEME_WITH_HOST_PORT_AND_USER_INFORMATION: |
Lukasz Anforowicz | c664e8b | 2020-04-13 20:08:55 | [diff] [blame] | 111 | // A URL with |scheme| is required to have the host and port, so return an |
| 112 | // invalid instance if host is not given. Note that a valid port is |
| 113 | // always provided by SchemeHostPort(const GURL&) constructor (a missing |
| 114 | // port is replaced with a default port if needed by |
| 115 | // GURL::EffectiveIntPort()). |
| 116 | if (host.empty()) |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 117 | return false; |
| 118 | |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 119 | // Don't do an expensive canonicalization if the host is already |
| 120 | // canonicalized. |
| 121 | DCHECK(policy == SchemeHostPort::CHECK_CANONICALIZATION || |
Daniel Clark | dc91684 | 2024-10-08 18:28:19 | [diff] [blame] | 122 | IsCanonicalHost(host, scheme == url::kFileScheme)); |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 123 | if (policy == SchemeHostPort::CHECK_CANONICALIZATION && |
Daniel Clark | dc91684 | 2024-10-08 18:28:19 | [diff] [blame] | 124 | !IsCanonicalHost(host, scheme == url::kFileScheme)) { |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 125 | return false; |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 126 | } |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 127 | |
| 128 | return true; |
| 129 | |
Nick Carter | 123ca19 | 2018-03-30 23:25:36 | [diff] [blame] | 130 | case SCHEME_WITH_HOST: |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 131 | if (port != 0) { |
| 132 | // Return an invalid object if a URL with the scheme never represents |
| 133 | // the port data but the given |port| is non-zero. |
| 134 | return false; |
| 135 | } |
| 136 | |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 137 | // Don't do an expensive canonicalization if the host is already |
| 138 | // canonicalized. |
| 139 | DCHECK(policy == SchemeHostPort::CHECK_CANONICALIZATION || |
Daniel Clark | dc91684 | 2024-10-08 18:28:19 | [diff] [blame] | 140 | IsCanonicalHost(host, scheme == url::kFileScheme)); |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 141 | if (policy == SchemeHostPort::CHECK_CANONICALIZATION && |
Daniel Clark | dc91684 | 2024-10-08 18:28:19 | [diff] [blame] | 142 | !IsCanonicalHost(host, scheme == url::kFileScheme)) { |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 143 | return false; |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 144 | } |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 145 | |
| 146 | return true; |
| 147 | |
| 148 | case SCHEME_WITHOUT_AUTHORITY: |
| 149 | return false; |
| 150 | |
| 151 | default: |
Peter Boström | 89c82708 | 2024-09-20 10:54:38 | [diff] [blame] | 152 | NOTREACHED(); |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 153 | } |
| 154 | } |
| 155 | |
| 156 | } // namespace |
| 157 | |
Victor Costan | 7c9d0b148 | 2020-07-07 14:13:03 | [diff] [blame] | 158 | SchemeHostPort::SchemeHostPort() = default; |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 159 | |
csharrison | f07ac3c | 2016-12-13 04:15:02 | [diff] [blame] | 160 | SchemeHostPort::SchemeHostPort(std::string scheme, |
| 161 | std::string host, |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 162 | uint16_t port, |
Victor Costan | 7c9d0b148 | 2020-07-07 14:13:03 | [diff] [blame] | 163 | ConstructPolicy policy) { |
Hayato Ito | cddb0878 | 2024-03-13 01:02:24 | [diff] [blame] | 164 | if (ShouldDiscardHostAndPort(scheme)) { |
| 165 | host = ""; |
| 166 | port = 0; |
| 167 | } |
| 168 | |
Nick Carter | 8aa718ed | 2018-09-07 21:39:51 | [diff] [blame] | 169 | if (!IsValidInput(scheme, host, port, policy)) { |
Nasko Oskov | 5511938 | 2020-01-17 18:22:18 | [diff] [blame] | 170 | DCHECK(!IsValid()); |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 171 | return; |
Nick Carter | 8aa718ed | 2018-09-07 21:39:51 | [diff] [blame] | 172 | } |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 173 | |
csharrison | f07ac3c | 2016-12-13 04:15:02 | [diff] [blame] | 174 | scheme_ = std::move(scheme); |
| 175 | host_ = std::move(host); |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 176 | port_ = port; |
Nasko Oskov | 5511938 | 2020-01-17 18:22:18 | [diff] [blame] | 177 | DCHECK(IsValid()) << "Scheme: " << scheme_ << " Host: " << host_ |
| 178 | << " Port: " << port; |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 179 | } |
| 180 | |
David Benjamin | bf75caf | 2023-09-29 04:39:59 | [diff] [blame] | 181 | SchemeHostPort::SchemeHostPort(std::string_view scheme, |
| 182 | std::string_view host, |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 183 | uint16_t port) |
Peter Kasting | 95e78e4 | 2021-04-29 23:37:51 | [diff] [blame] | 184 | : SchemeHostPort(std::string(scheme), |
| 185 | std::string(host), |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 186 | port, |
| 187 | ConstructPolicy::CHECK_CANONICALIZATION) {} |
| 188 | |
Victor Costan | 7c9d0b148 | 2020-07-07 14:13:03 | [diff] [blame] | 189 | SchemeHostPort::SchemeHostPort(const GURL& url) { |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 190 | if (!url.is_valid()) |
| 191 | return; |
| 192 | |
David Benjamin | bf75caf | 2023-09-29 04:39:59 | [diff] [blame] | 193 | std::string_view scheme = url.scheme_piece(); |
| 194 | std::string_view host = url.host_piece(); |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 195 | |
| 196 | // A valid GURL never returns PORT_INVALID. |
| 197 | int port = url.EffectiveIntPort(); |
Takeshi Yoshino | e0ec8039 | 2017-12-13 11:40:53 | [diff] [blame] | 198 | if (port == PORT_UNSPECIFIED) { |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 199 | port = 0; |
Takeshi Yoshino | e0ec8039 | 2017-12-13 11:40:53 | [diff] [blame] | 200 | } else { |
| 201 | DCHECK_GE(port, 0); |
| 202 | DCHECK_LE(port, 65535); |
| 203 | } |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 204 | |
Hayato Ito | cddb0878 | 2024-03-13 01:02:24 | [diff] [blame] | 205 | if (ShouldDiscardHostAndPort(scheme)) { |
| 206 | host = ""; |
| 207 | port = 0; |
| 208 | } |
| 209 | |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 210 | if (!IsValidInput(scheme, host, port, ALREADY_CANONICALIZED)) |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 211 | return; |
| 212 | |
Jan Wilken Dörrie | c15b4bc | 2020-01-30 07:04:12 | [diff] [blame] | 213 | scheme_ = std::string(scheme); |
| 214 | host_ = std::string(host); |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 215 | port_ = port; |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 216 | } |
| 217 | |
Chris Watkins | 3e06be1 | 2017-11-29 01:40:54 | [diff] [blame] | 218 | SchemeHostPort::~SchemeHostPort() = default; |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 219 | |
Nasko Oskov | 5511938 | 2020-01-17 18:22:18 | [diff] [blame] | 220 | bool SchemeHostPort::IsValid() const { |
Nick Carter | 8aa718ed | 2018-09-07 21:39:51 | [diff] [blame] | 221 | // It suffices to just check |scheme_| for emptiness; the other fields are |
| 222 | // never present without it. |
| 223 | DCHECK(!scheme_.empty() || host_.empty()); |
| 224 | DCHECK(!scheme_.empty() || port_ == 0); |
Nasko Oskov | 5511938 | 2020-01-17 18:22:18 | [diff] [blame] | 225 | return !scheme_.empty(); |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 226 | } |
| 227 | |
| 228 | std::string SchemeHostPort::Serialize() const { |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 229 | // Null checking for |parsed| in SerializeInternal is probably slower than |
| 230 | // just filling it in and discarding it here. |
| 231 | url::Parsed parsed; |
| 232 | return SerializeInternal(&parsed); |
| 233 | } |
| 234 | |
| 235 | GURL SchemeHostPort::GetURL() const { |
| 236 | url::Parsed parsed; |
| 237 | std::string serialized = SerializeInternal(&parsed); |
| 238 | |
Nasko Oskov | 5511938 | 2020-01-17 18:22:18 | [diff] [blame] | 239 | if (!IsValid()) |
csharrison | 6fbc9fa | 2016-10-08 03:31:50 | [diff] [blame] | 240 | return GURL(std::move(serialized), parsed, false); |
| 241 | |
Charles Harrison | 60f0c53 | 2018-03-12 17:30:55 | [diff] [blame] | 242 | // SchemeHostPort does not have enough information to determine if an empty |
| 243 | // host is valid or not for the given scheme. Force re-parsing. |
| 244 | DCHECK(!scheme_.empty()); |
| 245 | if (host_.empty()) |
| 246 | return GURL(serialized); |
| 247 | |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 248 | // If the serialized string is passed to GURL for parsing, it will append an |
Hayato Ito | cddb0878 | 2024-03-13 01:02:24 | [diff] [blame] | 249 | // empty path "/" for standard URLs. Add that here. Note: per RFC 6454 we |
| 250 | // cannot do this for normal Origin serialization. |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 251 | DCHECK(!parsed.path.is_valid()); |
Hayato Ito | cddb0878 | 2024-03-13 01:02:24 | [diff] [blame] | 252 | if (url::IsUsingStandardCompliantNonSpecialSchemeURLParsing()) { |
| 253 | // Append "/" only if the URL is standard. If the flag is enabled, |
| 254 | // non-special URLs can have an empty path and GURL doesn't append "/" to |
| 255 | // that. |
| 256 | if (IsStandardScheme(scheme_)) { |
| 257 | parsed.path = Component(serialized.length(), 1); |
| 258 | serialized.append("/"); |
| 259 | } |
| 260 | } else { |
| 261 | parsed.path = Component(serialized.length(), 1); |
| 262 | serialized.append("/"); |
| 263 | } |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 264 | return GURL(std::move(serialized), parsed, true); |
| 265 | } |
| 266 | |
Xiaochen Zhou | 4350e46 | 2023-08-21 15:06:12 | [diff] [blame] | 267 | size_t SchemeHostPort::EstimateMemoryUsage() const { |
| 268 | return base::trace_event::EstimateMemoryUsage(scheme_) + |
| 269 | base::trace_event::EstimateMemoryUsage(host_); |
| 270 | } |
| 271 | |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 272 | std::string SchemeHostPort::SerializeInternal(url::Parsed* parsed) const { |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 273 | std::string result; |
Nasko Oskov | 5511938 | 2020-01-17 18:22:18 | [diff] [blame] | 274 | if (!IsValid()) |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 275 | return result; |
| 276 | |
csharrison | 8b5c370 | 2016-12-09 12:55:41 | [diff] [blame] | 277 | // Reserve enough space for the "normal" case of scheme://host/. |
| 278 | result.reserve(scheme_.size() + host_.size() + 4); |
| 279 | |
csharrison | 6fbc9fa | 2016-10-08 03:31:50 | [diff] [blame] | 280 | if (!scheme_.empty()) { |
| 281 | parsed->scheme = Component(0, scheme_.length()); |
| 282 | result.append(scheme_); |
| 283 | } |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 284 | |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 285 | result.append(kStandardSchemeSeparator); |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 286 | |
csharrison | 6fbc9fa | 2016-10-08 03:31:50 | [diff] [blame] | 287 | if (!host_.empty()) { |
| 288 | parsed->host = Component(result.length(), host_.length()); |
| 289 | result.append(host_); |
| 290 | } |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 291 | |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 292 | // Omit the port component if the port matches with the default port |
| 293 | // defined for the scheme, if any. |
Scott Violet | a02c94b14 | 2024-08-28 03:29:18 | [diff] [blame] | 294 | int default_port = DefaultPortForScheme(scheme_); |
tyoshino | 11a7c9fe | 2015-08-19 08:51:46 | [diff] [blame] | 295 | if (default_port == PORT_UNSPECIFIED) |
| 296 | return result; |
| 297 | if (port_ != default_port) { |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 298 | result.push_back(':'); |
Raul Tambre | b3eaf05 | 2019-02-09 07:22:58 | [diff] [blame] | 299 | std::string port(base::NumberToString(port_)); |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 300 | parsed->port = Component(result.length(), port.length()); |
| 301 | result.append(std::move(port)); |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 302 | } |
| 303 | |
| 304 | return result; |
| 305 | } |
| 306 | |
Tom Sepez | b55f2f1 | 2024-10-02 21:54:33 | [diff] [blame] | 307 | bool SchemeHostPort::ShouldDiscardHostAndPort(std::string_view scheme) { |
Hayato Ito | cddb0878 | 2024-03-13 01:02:24 | [diff] [blame] | 308 | return IsAndroidWebViewHackEnabledScheme(scheme) && |
| 309 | IsUsingStandardCompliantNonSpecialSchemeURLParsing(); |
| 310 | } |
| 311 | |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 312 | std::ostream& operator<<(std::ostream& out, |
| 313 | const SchemeHostPort& scheme_host_port) { |
| 314 | return out << scheme_host_port.Serialize(); |
| 315 | } |
| 316 | |
mkwst | 28c7c11 | 2015-07-14 22:41:06 | [diff] [blame] | 317 | } // namespace url |