blob: 4d0f0007595561d99bb54ffb61c57cee033b21e5 [file] [log] [blame]
mkwst28c7c112015-07-14 22:41:061// Copyright 2015 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.
4
5#include "url/scheme_host_port.h"
6
avic0c60312015-12-21 21:03:507#include <stdint.h>
mkwst28c7c112015-07-14 22:41:068#include <string.h>
9
jsbell938b0252015-11-30 23:17:4110#include <tuple>
11
mkwst28c7c112015-07-14 22:41:0612#include "base/logging.h"
tyoshino11a7c9fe2015-08-19 08:51:4613#include "base/numerics/safe_conversions.h"
mkwst28c7c112015-07-14 22:41:0614#include "base/strings/string_number_conversions.h"
15#include "url/gurl.h"
16#include "url/url_canon.h"
17#include "url/url_canon_stdstring.h"
18#include "url/url_constants.h"
19#include "url/url_util.h"
20
21namespace url {
22
tyoshino11a7c9fe2015-08-19 08:51:4623namespace {
mkwst28c7c112015-07-14 22:41:0624
tyoshino11a7c9fe2015-08-19 08:51:4625bool IsCanonicalHost(const base::StringPiece& host) {
msramek9b7972dd2015-08-18 13:04:1926 std::string canon_host;
tyoshino11a7c9fe2015-08-19 08:51:4627
28 // Try to canonicalize the host (copy/pasted from net/base. :( ).
29 const Component raw_host_component(0,
30 base::checked_cast<int>(host.length()));
31 StdStringCanonOutput canon_host_output(&canon_host);
32 CanonHostInfo host_info;
33 CanonicalizeHostVerbose(host.data(), raw_host_component,
34 &canon_host_output, &host_info);
mkwst28c7c112015-07-14 22:41:0635
36 if (host_info.out_host.is_nonempty() &&
tyoshino11a7c9fe2015-08-19 08:51:4637 host_info.family != CanonHostInfo::BROKEN) {
mkwst28c7c112015-07-14 22:41:0638 // Success! Assert that there's no extra garbage.
39 canon_host_output.Complete();
40 DCHECK_EQ(host_info.out_host.len, static_cast<int>(canon_host.length()));
41 } else {
42 // Empty host, or canonicalization failed.
43 canon_host.clear();
44 }
mkwst28c7c112015-07-14 22:41:0645
tyoshino11a7c9fe2015-08-19 08:51:4646 return host == canon_host;
mkwst28c7c112015-07-14 22:41:0647}
48
tyoshino11a7c9fe2015-08-19 08:51:4649bool IsValidInput(const base::StringPiece& scheme,
50 const base::StringPiece& host,
avic0c60312015-12-21 21:03:5051 uint16_t port) {
tyoshino11a7c9fe2015-08-19 08:51:4652 SchemeType scheme_type = SCHEME_WITH_PORT;
53 bool is_standard = GetStandardSchemeType(
54 scheme.data(),
55 Component(0, base::checked_cast<int>(scheme.length())),
56 &scheme_type);
57 if (!is_standard)
58 return false;
mkwst28c7c112015-07-14 22:41:0659
60 // These schemes do not follow the generic URL syntax, so we treat them as
61 // invalid (scheme, host, port) tuples (even though such URLs' _Origin_ might
62 // have a (scheme, host, port) tuple, they themselves do not).
tyoshino11a7c9fe2015-08-19 08:51:4663 if (scheme == kFileSystemScheme || scheme == kBlobScheme)
64 return false;
65
66 switch (scheme_type) {
67 case SCHEME_WITH_PORT:
68 // A URL with |scheme| is required to have the host and port (may be
69 // omitted in a serialization if it's the same as the default value).
70 // Return an invalid instance if either of them is not given.
71 if (host.empty() || port == 0)
72 return false;
73
74 if (!IsCanonicalHost(host))
75 return false;
76
77 return true;
78
79 case SCHEME_WITHOUT_PORT:
80 if (port != 0) {
81 // Return an invalid object if a URL with the scheme never represents
82 // the port data but the given |port| is non-zero.
83 return false;
84 }
85
86 if (!IsCanonicalHost(host))
87 return false;
88
89 return true;
90
91 case SCHEME_WITHOUT_AUTHORITY:
92 return false;
93
94 default:
95 NOTREACHED();
96 return false;
97 }
98}
99
100} // namespace
101
102SchemeHostPort::SchemeHostPort() : port_(0) {
103}
104
105SchemeHostPort::SchemeHostPort(base::StringPiece scheme,
106 base::StringPiece host,
avic0c60312015-12-21 21:03:50107 uint16_t port)
tyoshino11a7c9fe2015-08-19 08:51:46108 : port_(0) {
109 if (!IsValidInput(scheme, host, port))
mkwst28c7c112015-07-14 22:41:06110 return;
111
tyoshino11a7c9fe2015-08-19 08:51:46112 scheme.CopyToString(&scheme_);
113 host.CopyToString(&host_);
114 port_ = port;
115}
116
117SchemeHostPort::SchemeHostPort(const GURL& url) : port_(0) {
118 if (!url.is_valid())
119 return;
120
brettwadc846882015-09-25 01:16:22121 base::StringPiece scheme = url.scheme_piece();
122 base::StringPiece host = url.host_piece();
tyoshino11a7c9fe2015-08-19 08:51:46123
124 // A valid GURL never returns PORT_INVALID.
125 int port = url.EffectiveIntPort();
126 if (port == PORT_UNSPECIFIED)
127 port = 0;
128
129 if (!IsValidInput(scheme, host, port))
130 return;
131
brettwadc846882015-09-25 01:16:22132 scheme.CopyToString(&scheme_);
133 host.CopyToString(&host_);
tyoshino11a7c9fe2015-08-19 08:51:46134 port_ = port;
mkwst28c7c112015-07-14 22:41:06135}
136
137SchemeHostPort::~SchemeHostPort() {
138}
139
140bool SchemeHostPort::IsInvalid() const {
141 return scheme_.empty() && host_.empty() && !port_;
142}
143
144std::string SchemeHostPort::Serialize() const {
145 std::string result;
146 if (IsInvalid())
147 return result;
148
mkwst28c7c112015-07-14 22:41:06149 result.append(scheme_);
150 result.append(kStandardSchemeSeparator);
151 result.append(host_);
152
tyoshino11a7c9fe2015-08-19 08:51:46153 if (port_ == 0)
154 return result;
155
156 // Omit the port component if the port matches with the default port
157 // defined for the scheme, if any.
158 int default_port = DefaultPortForScheme(scheme_.data(),
159 static_cast<int>(scheme_.length()));
160 if (default_port == PORT_UNSPECIFIED)
161 return result;
162 if (port_ != default_port) {
mkwst28c7c112015-07-14 22:41:06163 result.push_back(':');
ricea460198b2015-09-18 22:42:28164 result.append(base::UintToString(port_));
mkwst28c7c112015-07-14 22:41:06165 }
166
167 return result;
168}
169
170bool SchemeHostPort::Equals(const SchemeHostPort& other) const {
171 return port_ == other.port() && scheme_ == other.scheme() &&
172 host_ == other.host();
173}
174
175bool SchemeHostPort::operator<(const SchemeHostPort& other) const {
jsbell938b0252015-11-30 23:17:41176 return std::tie(port_, scheme_, host_) <
177 std::tie(other.port_, other.scheme_, other.host_);
mkwst28c7c112015-07-14 22:41:06178}
179
180} // namespace url