mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 1 | // 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 | |
avi | c0c6031 | 2015-12-21 21:03:50 | [diff] [blame] | 5 | #include <stddef.h> |
| 6 | #include <stdint.h> |
| 7 | |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 8 | #include "base/logging.h" |
avi | c0c6031 | 2015-12-21 21:03:50 | [diff] [blame] | 9 | #include "base/macros.h" |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 10 | #include "testing/gtest/include/gtest/gtest.h" |
| 11 | #include "url/gurl.h" |
avi | c0c6031 | 2015-12-21 21:03:50 | [diff] [blame] | 12 | #include "url/origin.h" |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 13 | |
| 14 | namespace { |
| 15 | |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 16 | void ExpectParsedUrlsEqual(const GURL& a, const GURL& b) { |
| 17 | EXPECT_EQ(a, b); |
| 18 | const url::Parsed& a_parsed = a.parsed_for_possibly_invalid_spec(); |
| 19 | const url::Parsed& b_parsed = b.parsed_for_possibly_invalid_spec(); |
csharrison | 6fbc9fa | 2016-10-08 03:31:50 | [diff] [blame^] | 20 | EXPECT_EQ(a_parsed.scheme.begin, b_parsed.scheme.begin); |
| 21 | EXPECT_EQ(a_parsed.scheme.len, b_parsed.scheme.len); |
| 22 | EXPECT_EQ(a_parsed.username.begin, b_parsed.username.begin); |
| 23 | EXPECT_EQ(a_parsed.username.len, b_parsed.username.len); |
| 24 | EXPECT_EQ(a_parsed.password.begin, b_parsed.password.begin); |
| 25 | EXPECT_EQ(a_parsed.password.len, b_parsed.password.len); |
| 26 | EXPECT_EQ(a_parsed.host.begin, b_parsed.host.begin); |
| 27 | EXPECT_EQ(a_parsed.host.len, b_parsed.host.len); |
| 28 | EXPECT_EQ(a_parsed.port.begin, b_parsed.port.begin); |
| 29 | EXPECT_EQ(a_parsed.port.len, b_parsed.port.len); |
| 30 | EXPECT_EQ(a_parsed.path.begin, b_parsed.path.begin); |
| 31 | EXPECT_EQ(a_parsed.path.len, b_parsed.path.len); |
| 32 | EXPECT_EQ(a_parsed.query.begin, b_parsed.query.begin); |
| 33 | EXPECT_EQ(a_parsed.query.len, b_parsed.query.len); |
| 34 | EXPECT_EQ(a_parsed.ref.begin, b_parsed.ref.begin); |
| 35 | EXPECT_EQ(a_parsed.ref.len, b_parsed.ref.len); |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 36 | } |
| 37 | |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 38 | TEST(OriginTest, UniqueOriginComparison) { |
| 39 | url::Origin unique_origin; |
| 40 | EXPECT_EQ("", unique_origin.scheme()); |
| 41 | EXPECT_EQ("", unique_origin.host()); |
| 42 | EXPECT_EQ(0, unique_origin.port()); |
| 43 | EXPECT_TRUE(unique_origin.unique()); |
| 44 | EXPECT_FALSE(unique_origin.IsSameOriginWith(unique_origin)); |
| 45 | |
| 46 | const char* const urls[] = {"data:text/html,Hello!", |
| 47 | "javascript:alert(1)", |
| 48 | "file://example.com:443/etc/passwd", |
| 49 | "yay", |
| 50 | "http::///invalid.example.com/"}; |
| 51 | |
vmpstr | 981aa5a | 2016-07-14 01:05:08 | [diff] [blame] | 52 | for (auto* test_url : urls) { |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 53 | SCOPED_TRACE(test_url); |
| 54 | GURL url(test_url); |
| 55 | url::Origin origin(url); |
| 56 | EXPECT_EQ("", origin.scheme()); |
| 57 | EXPECT_EQ("", origin.host()); |
| 58 | EXPECT_EQ(0, origin.port()); |
| 59 | EXPECT_TRUE(origin.unique()); |
| 60 | EXPECT_FALSE(origin.IsSameOriginWith(origin)); |
| 61 | EXPECT_FALSE(unique_origin.IsSameOriginWith(origin)); |
| 62 | EXPECT_FALSE(origin.IsSameOriginWith(unique_origin)); |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 63 | |
| 64 | ExpectParsedUrlsEqual(GURL(origin.Serialize()), origin.GetURL()); |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 65 | } |
| 66 | } |
| 67 | |
| 68 | TEST(OriginTest, ConstructFromGURL) { |
| 69 | url::Origin different_origin(GURL("https://not-in-the-list.test/")); |
| 70 | |
| 71 | struct TestCases { |
| 72 | const char* const url; |
| 73 | const char* const expected_scheme; |
| 74 | const char* const expected_host; |
avi | c0c6031 | 2015-12-21 21:03:50 | [diff] [blame] | 75 | const uint16_t expected_port; |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 76 | } cases[] = { |
| 77 | // IP Addresses |
| 78 | {"http://192.168.9.1/", "http", "192.168.9.1", 80}, |
| 79 | {"http://[2001:db8::1]/", "http", "[2001:db8::1]", 80}, |
| 80 | |
| 81 | // Punycode |
| 82 | {"http://☃.net/", "http", "xn--n3h.net", 80}, |
| 83 | {"blob:http://☃.net/", "http", "xn--n3h.net", 80}, |
| 84 | |
| 85 | // Generic URLs |
| 86 | {"http://example.com/", "http", "example.com", 80}, |
| 87 | {"http://example.com:123/", "http", "example.com", 123}, |
| 88 | {"https://example.com/", "https", "example.com", 443}, |
| 89 | {"https://example.com:123/", "https", "example.com", 123}, |
| 90 | {"http://user:[email protected]/", "http", "example.com", 80}, |
| 91 | {"http://example.com:123/?query", "http", "example.com", 123}, |
| 92 | {"https://example.com/#1234", "https", "example.com", 443}, |
| 93 | {"https://u:[email protected]:123/?query#1234", "https", "example.com", 123}, |
| 94 | |
| 95 | // Registered URLs |
| 96 | {"ftp://example.com/", "ftp", "example.com", 21}, |
| 97 | {"gopher://example.com/", "gopher", "example.com", 70}, |
| 98 | {"ws://example.com/", "ws", "example.com", 80}, |
| 99 | {"wss://example.com/", "wss", "example.com", 443}, |
| 100 | |
| 101 | // file: URLs |
| 102 | {"file:///etc/passwd", "file", "", 0}, |
| 103 | {"file://example.com/etc/passwd", "file", "example.com", 0}, |
| 104 | |
| 105 | // Filesystem: |
| 106 | {"filesystem:http://example.com/type/", "http", "example.com", 80}, |
| 107 | {"filesystem:http://example.com:123/type/", "http", "example.com", 123}, |
| 108 | {"filesystem:https://example.com/type/", "https", "example.com", 443}, |
| 109 | {"filesystem:https://example.com:123/type/", "https", "example.com", 123}, |
| 110 | |
| 111 | // Blob: |
| 112 | {"blob:http://example.com/guid-goes-here", "http", "example.com", 80}, |
| 113 | {"blob:http://example.com:123/guid-goes-here", "http", "example.com", 123}, |
| 114 | {"blob:https://example.com/guid-goes-here", "https", "example.com", 443}, |
| 115 | {"blob:http://u:[email protected]/guid-goes-here", "http", "example.com", 80}, |
| 116 | }; |
| 117 | |
| 118 | for (const auto& test_case : cases) { |
| 119 | SCOPED_TRACE(test_case.url); |
| 120 | GURL url(test_case.url); |
| 121 | EXPECT_TRUE(url.is_valid()); |
| 122 | url::Origin origin(url); |
| 123 | EXPECT_EQ(test_case.expected_scheme, origin.scheme()); |
| 124 | EXPECT_EQ(test_case.expected_host, origin.host()); |
| 125 | EXPECT_EQ(test_case.expected_port, origin.port()); |
| 126 | EXPECT_FALSE(origin.unique()); |
| 127 | EXPECT_TRUE(origin.IsSameOriginWith(origin)); |
| 128 | EXPECT_FALSE(different_origin.IsSameOriginWith(origin)); |
| 129 | EXPECT_FALSE(origin.IsSameOriginWith(different_origin)); |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 130 | |
| 131 | ExpectParsedUrlsEqual(GURL(origin.Serialize()), origin.GetURL()); |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 132 | } |
| 133 | } |
| 134 | |
| 135 | TEST(OriginTest, Serialization) { |
| 136 | struct TestCases { |
| 137 | const char* const url; |
| 138 | const char* const expected; |
| 139 | } cases[] = { |
| 140 | {"http://192.168.9.1/", "http://192.168.9.1"}, |
| 141 | {"http://[2001:db8::1]/", "http://[2001:db8::1]"}, |
| 142 | {"http://☃.net/", "http://xn--n3h.net"}, |
| 143 | {"http://example.com/", "http://example.com"}, |
| 144 | {"http://example.com:123/", "http://example.com:123"}, |
| 145 | {"https://example.com/", "https://example.com"}, |
| 146 | {"https://example.com:123/", "https://example.com:123"}, |
| 147 | {"file:///etc/passwd", "file://"}, |
| 148 | {"file://example.com/etc/passwd", "file://"}, |
| 149 | }; |
| 150 | |
| 151 | for (const auto& test_case : cases) { |
| 152 | SCOPED_TRACE(test_case.url); |
| 153 | GURL url(test_case.url); |
| 154 | EXPECT_TRUE(url.is_valid()); |
| 155 | url::Origin origin(url); |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 156 | std::string serialized = origin.Serialize(); |
| 157 | ExpectParsedUrlsEqual(GURL(serialized), origin.GetURL()); |
| 158 | |
| 159 | EXPECT_EQ(test_case.expected, serialized); |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 160 | |
| 161 | // The '<<' operator should produce the same serialization as Serialize(). |
| 162 | std::stringstream out; |
| 163 | out << origin; |
| 164 | EXPECT_EQ(test_case.expected, out.str()); |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | TEST(OriginTest, Comparison) { |
| 169 | // These URLs are arranged in increasing order: |
| 170 | const char* const urls[] = { |
| 171 | "data:uniqueness", |
| 172 | "http://a:80", |
| 173 | "http://b:80", |
| 174 | "https://a:80", |
| 175 | "https://b:80", |
| 176 | "http://a:81", |
| 177 | "http://b:81", |
| 178 | "https://a:81", |
| 179 | "https://b:81", |
| 180 | }; |
| 181 | |
| 182 | for (size_t i = 0; i < arraysize(urls); i++) { |
| 183 | GURL current_url(urls[i]); |
| 184 | url::Origin current(current_url); |
| 185 | for (size_t j = i; j < arraysize(urls); j++) { |
| 186 | GURL compare_url(urls[j]); |
| 187 | url::Origin to_compare(compare_url); |
| 188 | EXPECT_EQ(i < j, current < to_compare) << i << " < " << j; |
| 189 | EXPECT_EQ(j < i, to_compare < current) << j << " < " << i; |
| 190 | } |
| 191 | } |
| 192 | } |
| 193 | |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 194 | TEST(OriginTest, UnsafelyCreate) { |
| 195 | struct TestCase { |
| 196 | const char* scheme; |
| 197 | const char* host; |
avi | c0c6031 | 2015-12-21 21:03:50 | [diff] [blame] | 198 | uint16_t port; |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 199 | } cases[] = { |
| 200 | {"http", "example.com", 80}, |
| 201 | {"http", "example.com", 123}, |
| 202 | {"https", "example.com", 443}, |
| 203 | {"https", "example.com", 123}, |
| 204 | {"file", "", 0}, |
| 205 | {"file", "example.com", 0}, |
| 206 | }; |
| 207 | |
| 208 | for (const auto& test : cases) { |
| 209 | SCOPED_TRACE(testing::Message() << test.scheme << "://" << test.host << ":" |
| 210 | << test.port); |
| 211 | url::Origin origin = url::Origin::UnsafelyCreateOriginWithoutNormalization( |
| 212 | test.scheme, test.host, test.port); |
| 213 | EXPECT_EQ(test.scheme, origin.scheme()); |
| 214 | EXPECT_EQ(test.host, origin.host()); |
| 215 | EXPECT_EQ(test.port, origin.port()); |
| 216 | EXPECT_FALSE(origin.unique()); |
| 217 | EXPECT_TRUE(origin.IsSameOriginWith(origin)); |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 218 | |
| 219 | ExpectParsedUrlsEqual(GURL(origin.Serialize()), origin.GetURL()); |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 220 | } |
| 221 | } |
| 222 | |
| 223 | TEST(OriginTest, UnsafelyCreateUniqueOnInvalidInput) { |
| 224 | struct TestCases { |
| 225 | const char* scheme; |
| 226 | const char* host; |
avi | c0c6031 | 2015-12-21 21:03:50 | [diff] [blame] | 227 | uint16_t port; |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 228 | } cases[] = {{"", "", 0}, |
| 229 | {"data", "", 0}, |
| 230 | {"blob", "", 0}, |
| 231 | {"filesystem", "", 0}, |
| 232 | {"data", "example.com", 80}, |
| 233 | {"http", "☃.net", 80}, |
| 234 | {"http\nmore", "example.com", 80}, |
| 235 | {"http\rmore", "example.com", 80}, |
| 236 | {"http\n", "example.com", 80}, |
| 237 | {"http\r", "example.com", 80}, |
| 238 | {"http", "example.com\nnot-example.com", 80}, |
| 239 | {"http", "example.com\rnot-example.com", 80}, |
| 240 | {"http", "example.com\n", 80}, |
| 241 | {"http", "example.com\r", 80}, |
| 242 | {"http", "example.com", 0}, |
| 243 | {"file", "", 80}}; |
| 244 | |
| 245 | for (const auto& test : cases) { |
| 246 | SCOPED_TRACE(testing::Message() << test.scheme << "://" << test.host << ":" |
| 247 | << test.port); |
| 248 | url::Origin origin = url::Origin::UnsafelyCreateOriginWithoutNormalization( |
| 249 | test.scheme, test.host, test.port); |
| 250 | EXPECT_EQ("", origin.scheme()); |
| 251 | EXPECT_EQ("", origin.host()); |
| 252 | EXPECT_EQ(0, origin.port()); |
| 253 | EXPECT_TRUE(origin.unique()); |
| 254 | EXPECT_FALSE(origin.IsSameOriginWith(origin)); |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 255 | |
| 256 | ExpectParsedUrlsEqual(GURL(origin.Serialize()), origin.GetURL()); |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 257 | } |
| 258 | } |
| 259 | |
| 260 | TEST(OriginTest, UnsafelyCreateUniqueViaEmbeddedNulls) { |
| 261 | struct TestCases { |
| 262 | const char* scheme; |
| 263 | size_t scheme_length; |
| 264 | const char* host; |
| 265 | size_t host_length; |
avi | c0c6031 | 2015-12-21 21:03:50 | [diff] [blame] | 266 | uint16_t port; |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 267 | } cases[] = {{"http\0more", 9, "example.com", 11, 80}, |
| 268 | {"http\0", 5, "example.com", 11, 80}, |
| 269 | {"\0http", 5, "example.com", 11, 80}, |
| 270 | {"http", 4, "example.com\0not-example.com", 27, 80}, |
| 271 | {"http", 4, "example.com\0", 12, 80}, |
| 272 | {"http", 4, "\0example.com", 12, 80}}; |
| 273 | |
| 274 | for (const auto& test : cases) { |
| 275 | SCOPED_TRACE(testing::Message() << test.scheme << "://" << test.host << ":" |
| 276 | << test.port); |
| 277 | url::Origin origin = url::Origin::UnsafelyCreateOriginWithoutNormalization( |
| 278 | std::string(test.scheme, test.scheme_length), |
| 279 | std::string(test.host, test.host_length), test.port); |
| 280 | EXPECT_EQ("", origin.scheme()); |
| 281 | EXPECT_EQ("", origin.host()); |
| 282 | EXPECT_EQ(0, origin.port()); |
| 283 | EXPECT_TRUE(origin.unique()); |
| 284 | EXPECT_FALSE(origin.IsSameOriginWith(origin)); |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 285 | |
| 286 | ExpectParsedUrlsEqual(GURL(origin.Serialize()), origin.GetURL()); |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 287 | } |
| 288 | } |
| 289 | |
pkalinnikov | 054f403 | 2016-08-31 10:54:17 | [diff] [blame] | 290 | TEST(OriginTest, DomainIs) { |
| 291 | const struct { |
| 292 | const char* url; |
| 293 | const char* lower_ascii_domain; |
| 294 | bool expected_domain_is; |
| 295 | } kTestCases[] = { |
| 296 | {"http://google.com/foo", "google.com", true}, |
| 297 | {"http://www.google.com:99/foo", "google.com", true}, |
| 298 | {"http://www.google.com.cn/foo", "google.com", false}, |
| 299 | {"http://www.google.comm", "google.com", false}, |
| 300 | {"http://www.iamnotgoogle.com/foo", "google.com", false}, |
| 301 | {"http://www.google.com/foo", "Google.com", false}, |
| 302 | |
| 303 | // If the host ends with a dot, it matches domains with or without a dot. |
| 304 | {"http://www.google.com./foo", "google.com", true}, |
| 305 | {"http://www.google.com./foo", "google.com.", true}, |
| 306 | {"http://www.google.com./foo", ".com", true}, |
| 307 | {"http://www.google.com./foo", ".com.", true}, |
| 308 | |
| 309 | // But, if the host doesn't end with a dot and the input domain does, then |
| 310 | // it's considered to not match. |
| 311 | {"http://google.com/foo", "google.com.", false}, |
| 312 | |
| 313 | // If the host ends with two dots, it doesn't match. |
| 314 | {"http://www.google.com../foo", "google.com", false}, |
| 315 | |
| 316 | // Filesystem scheme. |
| 317 | {"filesystem:http://www.google.com:99/foo/", "google.com", true}, |
| 318 | {"filesystem:http://www.iamnotgoogle.com/foo/", "google.com", false}, |
| 319 | |
| 320 | // File scheme. |
| 321 | {"file:///home/user/text.txt", "", false}, |
| 322 | {"file:///home/user/text.txt", "txt", false}, |
| 323 | }; |
| 324 | |
| 325 | for (const auto& test_case : kTestCases) { |
| 326 | SCOPED_TRACE(testing::Message() << "(url, domain): (" << test_case.url |
| 327 | << ", " << test_case.lower_ascii_domain |
| 328 | << ")"); |
| 329 | GURL url(test_case.url); |
| 330 | ASSERT_TRUE(url.is_valid()); |
| 331 | url::Origin origin(url); |
| 332 | |
| 333 | EXPECT_EQ(test_case.expected_domain_is, |
| 334 | origin.DomainIs(test_case.lower_ascii_domain)); |
| 335 | } |
| 336 | |
| 337 | // If the URL is invalid, DomainIs returns false. |
| 338 | GURL invalid_url("google.com"); |
| 339 | ASSERT_FALSE(invalid_url.is_valid()); |
| 340 | EXPECT_FALSE(url::Origin(invalid_url).DomainIs("google.com")); |
| 341 | |
| 342 | // Unique origins. |
| 343 | EXPECT_FALSE(url::Origin().DomainIs("")); |
| 344 | EXPECT_FALSE(url::Origin().DomainIs("com")); |
| 345 | } |
| 346 | |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 347 | } // namespace url |