1// Copyright (c) 2012 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 "base/memory/scoped_ptr.h" 6#include "extensions/common/url_pattern.h" 7#include "testing/gtest/include/gtest/gtest.h" 8#include "url/gurl.h" 9 10namespace { 11 12// See url_pattern.h for examples of valid and invalid patterns. 13 14static const int kAllSchemes = 15 URLPattern::SCHEME_HTTP | 16 URLPattern::SCHEME_HTTPS | 17 URLPattern::SCHEME_FILE | 18 URLPattern::SCHEME_FTP | 19 URLPattern::SCHEME_CHROMEUI | 20 URLPattern::SCHEME_EXTENSION | 21 URLPattern::SCHEME_FILESYSTEM; 22 23TEST(ExtensionURLPatternTest, ParseInvalid) { 24 const struct { 25 const char* pattern; 26 URLPattern::ParseResult expected_result; 27 } kInvalidPatterns[] = { 28 { "http", URLPattern::PARSE_ERROR_MISSING_SCHEME_SEPARATOR }, 29 { "http:", URLPattern::PARSE_ERROR_WRONG_SCHEME_SEPARATOR }, 30 { "http:/", URLPattern::PARSE_ERROR_WRONG_SCHEME_SEPARATOR }, 31 { "about://", URLPattern::PARSE_ERROR_WRONG_SCHEME_SEPARATOR }, 32 { "http://", URLPattern::PARSE_ERROR_EMPTY_HOST }, 33 { "http:///", URLPattern::PARSE_ERROR_EMPTY_HOST }, 34 { "http:// /", URLPattern::PARSE_ERROR_EMPTY_HOST }, 35 { "http://*foo/bar", URLPattern::PARSE_ERROR_INVALID_HOST_WILDCARD }, 36 { "http://foo.*.bar/baz", URLPattern::PARSE_ERROR_INVALID_HOST_WILDCARD }, 37 { "http://fo.*.ba:123/baz", URLPattern::PARSE_ERROR_INVALID_HOST_WILDCARD }, 38 { "http:/bar", URLPattern::PARSE_ERROR_WRONG_SCHEME_SEPARATOR }, 39 { "http://bar", URLPattern::PARSE_ERROR_EMPTY_PATH }, 40 }; 41 42 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kInvalidPatterns); ++i) { 43 URLPattern pattern(URLPattern::SCHEME_ALL); 44 EXPECT_EQ(kInvalidPatterns[i].expected_result, 45 pattern.Parse(kInvalidPatterns[i].pattern)) 46 << kInvalidPatterns[i].pattern; 47 } 48 49 { 50 // Cannot use a C string, because this contains a null byte. 51 std::string null_host("http://\0www/", 12); 52 URLPattern pattern(URLPattern::SCHEME_ALL); 53 EXPECT_EQ(URLPattern::PARSE_ERROR_INVALID_HOST, 54 pattern.Parse(null_host)) 55 << null_host; 56 } 57} 58 59TEST(ExtensionURLPatternTest, Ports) { 60 const struct { 61 const char* pattern; 62 URLPattern::ParseResult expected_result; 63 const char* expected_port; 64 } kTestPatterns[] = { 65 { "http://foo:1234/", URLPattern::PARSE_SUCCESS, "1234" }, 66 { "http://foo:1234/bar", URLPattern::PARSE_SUCCESS, "1234" }, 67 { "http://*.foo:1234/", URLPattern::PARSE_SUCCESS, "1234" }, 68 { "http://*.foo:1234/bar", URLPattern::PARSE_SUCCESS, "1234" }, 69 { "http://:1234/", URLPattern::PARSE_SUCCESS, "1234" }, 70 { "http://foo:/", URLPattern::PARSE_ERROR_INVALID_PORT, "*" }, 71 { "http://foo:*/", URLPattern::PARSE_SUCCESS, "*" }, 72 { "http://*.foo:/", URLPattern::PARSE_ERROR_INVALID_PORT, "*" }, 73 { "http://foo:com/", URLPattern::PARSE_ERROR_INVALID_PORT, "*" }, 74 { "http://foo:123456/", URLPattern::PARSE_ERROR_INVALID_PORT, "*" }, 75 { "http://foo:80:80/monkey", URLPattern::PARSE_ERROR_INVALID_PORT, "*" }, 76 { "file://foo:1234/bar", URLPattern::PARSE_SUCCESS, "*" }, 77 { "chrome://foo:1234/bar", URLPattern::PARSE_ERROR_INVALID_PORT, "*" }, 78 79 // Port-like strings in the path should not trigger a warning. 80 { "http://*/:1234", URLPattern::PARSE_SUCCESS, "*" }, 81 { "http://*.foo/bar:1234", URLPattern::PARSE_SUCCESS, "*" }, 82 { "http://foo/bar:1234/path", URLPattern::PARSE_SUCCESS, "*" }, 83 }; 84 85 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestPatterns); ++i) { 86 URLPattern pattern(URLPattern::SCHEME_ALL); 87 EXPECT_EQ(kTestPatterns[i].expected_result, 88 pattern.Parse(kTestPatterns[i].pattern)) 89 << "Got unexpected result for URL pattern: " 90 << kTestPatterns[i].pattern; 91 EXPECT_EQ(kTestPatterns[i].expected_port, pattern.port()) 92 << "Got unexpected port for URL pattern: " << kTestPatterns[i].pattern; 93 } 94} 95 96// all pages for a given scheme 97TEST(ExtensionURLPatternTest, Match1) { 98 URLPattern pattern(kAllSchemes); 99 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("http://*/*")); 100 EXPECT_EQ("http", pattern.scheme()); 101 EXPECT_EQ("", pattern.host()); 102 EXPECT_TRUE(pattern.match_subdomains()); 103 EXPECT_FALSE(pattern.match_all_urls()); 104 EXPECT_EQ("/*", pattern.path()); 105 EXPECT_TRUE(pattern.MatchesURL(GURL("http://google.com"))); 106 EXPECT_TRUE(pattern.MatchesURL(GURL("http://yahoo.com"))); 107 EXPECT_TRUE(pattern.MatchesURL(GURL("http://google.com/foo"))); 108 EXPECT_FALSE(pattern.MatchesURL(GURL("https://google.com"))); 109 EXPECT_TRUE(pattern.MatchesURL(GURL("http://74.125.127.100/search"))); 110} 111 112// all domains 113TEST(ExtensionURLPatternTest, Match2) { 114 URLPattern pattern(kAllSchemes); 115 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("https://*/foo*")); 116 EXPECT_EQ("https", pattern.scheme()); 117 EXPECT_EQ("", pattern.host()); 118 EXPECT_TRUE(pattern.match_subdomains()); 119 EXPECT_FALSE(pattern.match_all_urls()); 120 EXPECT_EQ("/foo*", pattern.path()); 121 EXPECT_TRUE(pattern.MatchesURL(GURL("https://www.google.com/foo"))); 122 EXPECT_TRUE(pattern.MatchesURL(GURL("https://www.google.com/foobar"))); 123 EXPECT_FALSE(pattern.MatchesURL(GURL("http://www.google.com/foo"))); 124 EXPECT_FALSE(pattern.MatchesURL(GURL("https://www.google.com/"))); 125 EXPECT_TRUE(pattern.MatchesURL( 126 GURL("filesystem:https://www.google.com/foobar/"))); 127} 128 129// subdomains 130TEST(URLPatternTest, Match3) { 131 URLPattern pattern(kAllSchemes); 132 EXPECT_EQ(URLPattern::PARSE_SUCCESS, 133 pattern.Parse("http://*.google.com/foo*bar")); 134 EXPECT_EQ("http", pattern.scheme()); 135 EXPECT_EQ("google.com", pattern.host()); 136 EXPECT_TRUE(pattern.match_subdomains()); 137 EXPECT_FALSE(pattern.match_all_urls()); 138 EXPECT_EQ("/foo*bar", pattern.path()); 139 EXPECT_TRUE(pattern.MatchesURL(GURL("http://google.com/foobar"))); 140 EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.google.com/foo?bar"))); 141 EXPECT_TRUE(pattern.MatchesURL( 142 GURL("http://monkey.images.google.com/foooobar"))); 143 EXPECT_FALSE(pattern.MatchesURL(GURL("http://yahoo.com/foobar"))); 144 EXPECT_TRUE(pattern.MatchesURL( 145 GURL("filesystem:http://google.com/foo/bar"))); 146 EXPECT_FALSE(pattern.MatchesURL( 147 GURL("filesystem:http://google.com/temporary/foobar"))); 148} 149 150// glob escaping 151TEST(ExtensionURLPatternTest, Match5) { 152 URLPattern pattern(kAllSchemes); 153 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("file:///foo?bar\\*baz")); 154 EXPECT_EQ("file", pattern.scheme()); 155 EXPECT_EQ("", pattern.host()); 156 EXPECT_FALSE(pattern.match_subdomains()); 157 EXPECT_FALSE(pattern.match_all_urls()); 158 EXPECT_EQ("/foo?bar\\*baz", pattern.path()); 159 EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foo?bar\\hellobaz"))); 160 EXPECT_FALSE(pattern.MatchesURL(GURL("file:///fooXbar\\hellobaz"))); 161} 162 163// ip addresses 164TEST(ExtensionURLPatternTest, Match6) { 165 URLPattern pattern(kAllSchemes); 166 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("http://127.0.0.1/*")); 167 EXPECT_EQ("http", pattern.scheme()); 168 EXPECT_EQ("127.0.0.1", pattern.host()); 169 EXPECT_FALSE(pattern.match_subdomains()); 170 EXPECT_FALSE(pattern.match_all_urls()); 171 EXPECT_EQ("/*", pattern.path()); 172 EXPECT_TRUE(pattern.MatchesURL(GURL("http://127.0.0.1"))); 173} 174 175// subdomain matching with ip addresses 176TEST(ExtensionURLPatternTest, Match7) { 177 URLPattern pattern(kAllSchemes); 178 // allowed, but useless 179 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("http://*.0.0.1/*")); 180 EXPECT_EQ("http", pattern.scheme()); 181 EXPECT_EQ("0.0.1", pattern.host()); 182 EXPECT_TRUE(pattern.match_subdomains()); 183 EXPECT_FALSE(pattern.match_all_urls()); 184 EXPECT_EQ("/*", pattern.path()); 185 // Subdomain matching is never done if the argument has an IP address host. 186 EXPECT_FALSE(pattern.MatchesURL(GURL("http://127.0.0.1"))); 187} 188 189// unicode 190TEST(ExtensionURLPatternTest, Match8) { 191 URLPattern pattern(kAllSchemes); 192 // The below is the ASCII encoding of the following URL: 193 // http://*.\xe1\x80\xbf/a\xc2\x81\xe1* 194 EXPECT_EQ(URLPattern::PARSE_SUCCESS, 195 pattern.Parse("http://*.xn--gkd/a%C2%81%E1*")); 196 EXPECT_EQ("http", pattern.scheme()); 197 EXPECT_EQ("xn--gkd", pattern.host()); 198 EXPECT_TRUE(pattern.match_subdomains()); 199 EXPECT_FALSE(pattern.match_all_urls()); 200 EXPECT_EQ("/a%C2%81%E1*", pattern.path()); 201 EXPECT_TRUE(pattern.MatchesURL( 202 GURL("http://abc.\xe1\x80\xbf/a\xc2\x81\xe1xyz"))); 203 EXPECT_TRUE(pattern.MatchesURL( 204 GURL("http://\xe1\x80\xbf/a\xc2\x81\xe1\xe1"))); 205} 206 207// chrome:// 208TEST(ExtensionURLPatternTest, Match9) { 209 URLPattern pattern(kAllSchemes); 210 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("chrome://favicon/*")); 211 EXPECT_EQ("chrome", pattern.scheme()); 212 EXPECT_EQ("favicon", pattern.host()); 213 EXPECT_FALSE(pattern.match_subdomains()); 214 EXPECT_FALSE(pattern.match_all_urls()); 215 EXPECT_EQ("/*", pattern.path()); 216 EXPECT_TRUE(pattern.MatchesURL(GURL("chrome://favicon/http://google.com"))); 217 EXPECT_TRUE(pattern.MatchesURL(GURL("chrome://favicon/https://google.com"))); 218 EXPECT_FALSE(pattern.MatchesURL(GURL("chrome://history"))); 219} 220 221// *:// 222TEST(ExtensionURLPatternTest, Match10) { 223 URLPattern pattern(kAllSchemes); 224 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("*://*/*")); 225 EXPECT_TRUE(pattern.MatchesScheme("http")); 226 EXPECT_TRUE(pattern.MatchesScheme("https")); 227 EXPECT_FALSE(pattern.MatchesScheme("chrome")); 228 EXPECT_FALSE(pattern.MatchesScheme("file")); 229 EXPECT_FALSE(pattern.MatchesScheme("ftp")); 230 EXPECT_TRUE(pattern.match_subdomains()); 231 EXPECT_FALSE(pattern.match_all_urls()); 232 EXPECT_EQ("/*", pattern.path()); 233 EXPECT_TRUE(pattern.MatchesURL(GURL("http://127.0.0.1"))); 234 EXPECT_FALSE(pattern.MatchesURL(GURL("chrome://favicon/http://google.com"))); 235 EXPECT_FALSE(pattern.MatchesURL(GURL("file:///foo/bar"))); 236 EXPECT_FALSE(pattern.MatchesURL(GURL("file://localhost/foo/bar"))); 237} 238 239// <all_urls> 240TEST(ExtensionURLPatternTest, Match11) { 241 URLPattern pattern(kAllSchemes); 242 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("<all_urls>")); 243 EXPECT_TRUE(pattern.MatchesScheme("chrome")); 244 EXPECT_TRUE(pattern.MatchesScheme("http")); 245 EXPECT_TRUE(pattern.MatchesScheme("https")); 246 EXPECT_TRUE(pattern.MatchesScheme("file")); 247 EXPECT_TRUE(pattern.MatchesScheme("filesystem")); 248 EXPECT_TRUE(pattern.MatchesScheme("chrome-extension")); 249 EXPECT_TRUE(pattern.match_subdomains()); 250 EXPECT_TRUE(pattern.match_all_urls()); 251 EXPECT_EQ("/*", pattern.path()); 252 EXPECT_TRUE(pattern.MatchesURL(GURL("chrome://favicon/http://google.com"))); 253 EXPECT_TRUE(pattern.MatchesURL(GURL("http://127.0.0.1"))); 254 EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foo/bar"))); 255 EXPECT_TRUE(pattern.MatchesURL(GURL("file://localhost/foo/bar"))); 256 257 // Make sure the properties are the same when creating an <all_urls> pattern 258 // via SetMatchAllURLs and by parsing <all_urls>. 259 URLPattern pattern2(kAllSchemes); 260 pattern2.SetMatchAllURLs(true); 261 262 EXPECT_EQ(pattern.valid_schemes(), pattern2.valid_schemes()); 263 EXPECT_EQ(pattern.match_subdomains(), pattern2.match_subdomains()); 264 EXPECT_EQ(pattern.path(), pattern2.path()); 265 EXPECT_EQ(pattern.match_all_urls(), pattern2.match_all_urls()); 266 EXPECT_EQ(pattern.scheme(), pattern2.scheme()); 267 EXPECT_EQ(pattern.port(), pattern2.port()); 268 EXPECT_EQ(pattern.GetAsString(), pattern2.GetAsString()); 269} 270 271// SCHEME_ALL matches all schemes. 272TEST(ExtensionURLPatternTest, Match12) { 273 URLPattern pattern(URLPattern::SCHEME_ALL); 274 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("<all_urls>")); 275 EXPECT_TRUE(pattern.MatchesScheme("chrome")); 276 EXPECT_TRUE(pattern.MatchesScheme("http")); 277 EXPECT_TRUE(pattern.MatchesScheme("https")); 278 EXPECT_TRUE(pattern.MatchesScheme("file")); 279 EXPECT_TRUE(pattern.MatchesScheme("filesystem")); 280 EXPECT_TRUE(pattern.MatchesScheme("javascript")); 281 EXPECT_TRUE(pattern.MatchesScheme("data")); 282 EXPECT_TRUE(pattern.MatchesScheme("about")); 283 EXPECT_TRUE(pattern.MatchesScheme("chrome-extension")); 284 EXPECT_TRUE(pattern.match_subdomains()); 285 EXPECT_TRUE(pattern.match_all_urls()); 286 EXPECT_EQ("/*", pattern.path()); 287 EXPECT_TRUE(pattern.MatchesURL(GURL("chrome://favicon/http://google.com"))); 288 EXPECT_TRUE(pattern.MatchesURL(GURL("http://127.0.0.1"))); 289 EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foo/bar"))); 290 EXPECT_TRUE(pattern.MatchesURL(GURL("file://localhost/foo/bar"))); 291 EXPECT_TRUE(pattern.MatchesURL(GURL("chrome://newtab"))); 292 EXPECT_TRUE(pattern.MatchesURL(GURL("about:blank"))); 293 EXPECT_TRUE(pattern.MatchesURL(GURL("about:version"))); 294 EXPECT_TRUE(pattern.MatchesURL( 295 GURL("data:text/html;charset=utf-8,<html>asdf</html>"))); 296} 297 298static const struct MatchPatterns { 299 const char* pattern; 300 const char* matches; 301} kMatch13UrlPatternTestCases[] = { 302 {"about:*", "about:blank"}, 303 {"about:blank", "about:blank"}, 304 {"about:*", "about:version"}, 305 {"chrome-extension://*/*", "chrome-extension://FTW"}, 306 {"data:*", "data:monkey"}, 307 {"javascript:*", "javascript:atemyhomework"}, 308}; 309 310// SCHEME_ALL and specific schemes. 311TEST(ExtensionURLPatternTest, Match13) { 312 for (size_t i = 0; i < arraysize(kMatch13UrlPatternTestCases); ++i) { 313 URLPattern pattern(URLPattern::SCHEME_ALL); 314 EXPECT_EQ(URLPattern::PARSE_SUCCESS, 315 pattern.Parse(kMatch13UrlPatternTestCases[i].pattern)) 316 << " while parsing " << kMatch13UrlPatternTestCases[i].pattern; 317 EXPECT_TRUE(pattern.MatchesURL( 318 GURL(kMatch13UrlPatternTestCases[i].matches))) 319 << " while matching " << kMatch13UrlPatternTestCases[i].matches; 320 } 321 322 // Negative test. 323 URLPattern pattern(URLPattern::SCHEME_ALL); 324 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("data:*")); 325 EXPECT_FALSE(pattern.MatchesURL(GURL("about:blank"))); 326} 327 328// file scheme with empty hostname 329TEST(ExtensionURLPatternTest, Match14) { 330 URLPattern pattern(kAllSchemes); 331 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("file:///foo*")); 332 EXPECT_EQ("file", pattern.scheme()); 333 EXPECT_EQ("", pattern.host()); 334 EXPECT_FALSE(pattern.match_subdomains()); 335 EXPECT_FALSE(pattern.match_all_urls()); 336 EXPECT_EQ("/foo*", pattern.path()); 337 EXPECT_FALSE(pattern.MatchesURL(GURL("file://foo"))); 338 EXPECT_FALSE(pattern.MatchesURL(GURL("file://foobar"))); 339 EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foo"))); 340 EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foobar"))); 341 EXPECT_TRUE(pattern.MatchesURL(GURL("file://localhost/foo"))); 342} 343 344// file scheme without hostname part 345TEST(ExtensionURLPatternTest, Match15) { 346 URLPattern pattern(kAllSchemes); 347 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("file://foo*")); 348 EXPECT_EQ("file", pattern.scheme()); 349 EXPECT_EQ("", pattern.host()); 350 EXPECT_FALSE(pattern.match_subdomains()); 351 EXPECT_FALSE(pattern.match_all_urls()); 352 EXPECT_EQ("/foo*", pattern.path()); 353 EXPECT_FALSE(pattern.MatchesURL(GURL("file://foo"))); 354 EXPECT_FALSE(pattern.MatchesURL(GURL("file://foobar"))); 355 EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foo"))); 356 EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foobar"))); 357 EXPECT_TRUE(pattern.MatchesURL(GURL("file://localhost/foo"))); 358} 359 360// file scheme with hostname 361TEST(ExtensionURLPatternTest, Match16) { 362 URLPattern pattern(kAllSchemes); 363 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("file://localhost/foo*")); 364 EXPECT_EQ("file", pattern.scheme()); 365 // Since hostname is ignored for file://. 366 EXPECT_EQ("", pattern.host()); 367 EXPECT_FALSE(pattern.match_subdomains()); 368 EXPECT_FALSE(pattern.match_all_urls()); 369 EXPECT_EQ("/foo*", pattern.path()); 370 EXPECT_FALSE(pattern.MatchesURL(GURL("file://foo"))); 371 EXPECT_FALSE(pattern.MatchesURL(GURL("file://foobar"))); 372 EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foo"))); 373 EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foobar"))); 374 EXPECT_TRUE(pattern.MatchesURL(GURL("file://localhost/foo"))); 375} 376 377// Specific port 378TEST(ExtensionURLPatternTest, Match17) { 379 URLPattern pattern(kAllSchemes); 380 EXPECT_EQ(URLPattern::PARSE_SUCCESS, 381 pattern.Parse("http://www.example.com:80/foo")); 382 EXPECT_EQ("http", pattern.scheme()); 383 EXPECT_EQ("www.example.com", pattern.host()); 384 EXPECT_FALSE(pattern.match_subdomains()); 385 EXPECT_FALSE(pattern.match_all_urls()); 386 EXPECT_EQ("/foo", pattern.path()); 387 EXPECT_EQ("80", pattern.port()); 388 EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.example.com:80/foo"))); 389 EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.example.com/foo"))); 390 EXPECT_FALSE(pattern.MatchesURL(GURL("http://www.example.com:8080/foo"))); 391 EXPECT_FALSE(pattern.MatchesURL( 392 GURL("filesystem:http://www.example.com:8080/foo/"))); 393 EXPECT_FALSE(pattern.MatchesURL( 394 GURL("filesystem:http://www.example.com/f/foo"))); 395} 396 397// Explicit port wildcard 398TEST(ExtensionURLPatternTest, Match18) { 399 URLPattern pattern(kAllSchemes); 400 EXPECT_EQ(URLPattern::PARSE_SUCCESS, 401 pattern.Parse("http://www.example.com:*/foo")); 402 EXPECT_EQ("http", pattern.scheme()); 403 EXPECT_EQ("www.example.com", pattern.host()); 404 EXPECT_FALSE(pattern.match_subdomains()); 405 EXPECT_FALSE(pattern.match_all_urls()); 406 EXPECT_EQ("/foo", pattern.path()); 407 EXPECT_EQ("*", pattern.port()); 408 EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.example.com:80/foo"))); 409 EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.example.com/foo"))); 410 EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.example.com:8080/foo"))); 411 EXPECT_FALSE(pattern.MatchesURL( 412 GURL("filesystem:http://www.example.com:8080/foo/"))); 413} 414 415// chrome-extension:// 416TEST(ExtensionURLPatternTest, Match19) { 417 URLPattern pattern(URLPattern::SCHEME_EXTENSION); 418 EXPECT_EQ(URLPattern::PARSE_SUCCESS, 419 pattern.Parse("chrome-extension://ftw/*")); 420 EXPECT_EQ("chrome-extension", pattern.scheme()); 421 EXPECT_EQ("ftw", pattern.host()); 422 EXPECT_FALSE(pattern.match_subdomains()); 423 EXPECT_FALSE(pattern.match_all_urls()); 424 EXPECT_EQ("/*", pattern.path()); 425 EXPECT_TRUE(pattern.MatchesURL(GURL("chrome-extension://ftw"))); 426 EXPECT_TRUE(pattern.MatchesURL( 427 GURL("chrome-extension://ftw/http://google.com"))); 428 EXPECT_TRUE(pattern.MatchesURL( 429 GURL("chrome-extension://ftw/https://google.com"))); 430 EXPECT_FALSE(pattern.MatchesURL(GURL("chrome-extension://foobar"))); 431 EXPECT_TRUE(pattern.MatchesURL( 432 GURL("filesystem:chrome-extension://ftw/t/file.txt"))); 433} 434 435static const struct GetAsStringPatterns { 436 const char* pattern; 437} kGetAsStringTestCases[] = { 438 { "http://www/" }, 439 { "http://*/*" }, 440 { "chrome://*/*" }, 441 { "chrome://newtab/" }, 442 { "about:*" }, 443 { "about:blank" }, 444 { "chrome-extension://*/*" }, 445 { "chrome-extension://FTW/" }, 446 { "data:*" }, 447 { "data:monkey" }, 448 { "javascript:*" }, 449 { "javascript:atemyhomework" }, 450 { "http://www.example.com:8080/foo" }, 451}; 452 453TEST(ExtensionURLPatternTest, GetAsString) { 454 for (size_t i = 0; i < arraysize(kGetAsStringTestCases); ++i) { 455 URLPattern pattern(URLPattern::SCHEME_ALL); 456 EXPECT_EQ(URLPattern::PARSE_SUCCESS, 457 pattern.Parse(kGetAsStringTestCases[i].pattern)) 458 << "Error parsing " << kGetAsStringTestCases[i].pattern; 459 EXPECT_EQ(kGetAsStringTestCases[i].pattern, 460 pattern.GetAsString()); 461 } 462} 463 464testing::AssertionResult Overlaps(const URLPattern& pattern1, 465 const URLPattern& pattern2) { 466 if (!pattern1.OverlapsWith(pattern2)) { 467 return testing::AssertionFailure() 468 << pattern1.GetAsString() << " does not overlap " << 469 pattern2.GetAsString(); 470 } 471 if (!pattern2.OverlapsWith(pattern1)) { 472 return testing::AssertionFailure() 473 << pattern2.GetAsString() << " does not overlap " << 474 pattern1.GetAsString(); 475 } 476 return testing::AssertionSuccess() 477 << pattern1.GetAsString() << " overlaps with " << pattern2.GetAsString(); 478} 479 480TEST(ExtensionURLPatternTest, Overlaps) { 481 URLPattern pattern1(kAllSchemes, "http://www.google.com/foo/*"); 482 URLPattern pattern2(kAllSchemes, "https://www.google.com/foo/*"); 483 URLPattern pattern3(kAllSchemes, "http://*.google.com/foo/*"); 484 URLPattern pattern4(kAllSchemes, "http://*.yahooo.com/foo/*"); 485 URLPattern pattern5(kAllSchemes, "http://www.yahooo.com/bar/*"); 486 URLPattern pattern6(kAllSchemes, 487 "http://www.yahooo.com/bar/baz/*"); 488 URLPattern pattern7(kAllSchemes, "file:///*"); 489 URLPattern pattern8(kAllSchemes, "*://*/*"); 490 URLPattern pattern9(URLPattern::SCHEME_HTTPS, "*://*/*"); 491 URLPattern pattern10(kAllSchemes, "<all_urls>"); 492 493 EXPECT_TRUE(Overlaps(pattern1, pattern1)); 494 EXPECT_FALSE(Overlaps(pattern1, pattern2)); 495 EXPECT_TRUE(Overlaps(pattern1, pattern3)); 496 EXPECT_FALSE(Overlaps(pattern1, pattern4)); 497 EXPECT_FALSE(Overlaps(pattern3, pattern4)); 498 EXPECT_FALSE(Overlaps(pattern4, pattern5)); 499 EXPECT_TRUE(Overlaps(pattern5, pattern6)); 500 501 // Test that scheme restrictions work. 502 EXPECT_TRUE(Overlaps(pattern1, pattern8)); 503 EXPECT_FALSE(Overlaps(pattern1, pattern9)); 504 EXPECT_TRUE(Overlaps(pattern1, pattern10)); 505 506 // Test that '<all_urls>' includes file URLs, while scheme '*' does not. 507 EXPECT_FALSE(Overlaps(pattern7, pattern8)); 508 EXPECT_TRUE(Overlaps(pattern7, pattern10)); 509 510 // Test that wildcard schemes are handled correctly, especially when compared 511 // to each-other. 512 URLPattern pattern11(kAllSchemes, "http://example.com/*"); 513 URLPattern pattern12(kAllSchemes, "*://example.com/*"); 514 URLPattern pattern13(kAllSchemes, "*://example.com/foo/*"); 515 URLPattern pattern14(kAllSchemes, "*://google.com/*"); 516 EXPECT_TRUE(Overlaps(pattern8, pattern12)); 517 EXPECT_TRUE(Overlaps(pattern9, pattern12)); 518 EXPECT_TRUE(Overlaps(pattern10, pattern12)); 519 EXPECT_TRUE(Overlaps(pattern11, pattern12)); 520 EXPECT_TRUE(Overlaps(pattern12, pattern13)); 521 EXPECT_TRUE(Overlaps(pattern11, pattern13)); 522 EXPECT_FALSE(Overlaps(pattern14, pattern12)); 523 EXPECT_FALSE(Overlaps(pattern14, pattern13)); 524} 525 526TEST(ExtensionURLPatternTest, ConvertToExplicitSchemes) { 527 URLPatternList all_urls(URLPattern( 528 kAllSchemes, 529 "<all_urls>").ConvertToExplicitSchemes()); 530 531 URLPatternList all_schemes(URLPattern( 532 kAllSchemes, 533 "*://google.com/foo").ConvertToExplicitSchemes()); 534 535 URLPatternList monkey(URLPattern( 536 URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS | 537 URLPattern::SCHEME_FTP, 538 "http://google.com/monkey").ConvertToExplicitSchemes()); 539 540 ASSERT_EQ(7u, all_urls.size()); 541 ASSERT_EQ(2u, all_schemes.size()); 542 ASSERT_EQ(1u, monkey.size()); 543 544 EXPECT_EQ("http://*/*", all_urls[0].GetAsString()); 545 EXPECT_EQ("https://*/*", all_urls[1].GetAsString()); 546 EXPECT_EQ("file:///*", all_urls[2].GetAsString()); 547 EXPECT_EQ("ftp://*/*", all_urls[3].GetAsString()); 548 EXPECT_EQ("chrome://*/*", all_urls[4].GetAsString()); 549 550 EXPECT_EQ("http://google.com/foo", all_schemes[0].GetAsString()); 551 EXPECT_EQ("https://google.com/foo", all_schemes[1].GetAsString()); 552 553 EXPECT_EQ("http://google.com/monkey", monkey[0].GetAsString()); 554} 555 556TEST(ExtensionURLPatternTest, IgnorePorts) { 557 std::string pattern_str = "http://www.example.com:8080/foo"; 558 GURL url("http://www.example.com:1234/foo"); 559 560 URLPattern pattern(kAllSchemes); 561 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse(pattern_str)); 562 563 EXPECT_EQ(pattern_str, pattern.GetAsString()); 564 EXPECT_FALSE(pattern.MatchesURL(url)); 565} 566 567TEST(ExtensionURLPatternTest, IgnoreMissingBackslashes) { 568 std::string pattern_str1 = "http://www.example.com/example"; 569 std::string pattern_str2 = "http://www.example.com/example/*"; 570 GURL url1("http://www.example.com/example"); 571 GURL url2("http://www.example.com/example/"); 572 573 URLPattern pattern1(kAllSchemes); 574 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern1.Parse(pattern_str1)); 575 URLPattern pattern2(kAllSchemes); 576 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern2.Parse(pattern_str2)); 577 578 // Same patterns should match same urls. 579 EXPECT_TRUE(pattern1.MatchesURL(url1)); 580 EXPECT_TRUE(pattern2.MatchesURL(url2)); 581 // The not terminated path should match the terminated pattern. 582 EXPECT_TRUE(pattern2.MatchesURL(url1)); 583 // The terminated path however should not match the unterminated pattern. 584 EXPECT_FALSE(pattern1.MatchesURL(url2)); 585} 586 587TEST(ExtensionURLPatternTest, Equals) { 588 const struct { 589 const char* pattern1; 590 const char* pattern2; 591 bool expected_equal; 592 } kEqualsTestCases[] = { 593 // schemes 594 { "http://en.google.com/blah/*/foo", 595 "https://en.google.com/blah/*/foo", 596 false 597 }, 598 { "https://en.google.com/blah/*/foo", 599 "https://en.google.com/blah/*/foo", 600 true 601 }, 602 { "https://en.google.com/blah/*/foo", 603 "ftp://en.google.com/blah/*/foo", 604 false 605 }, 606 607 // subdomains 608 { "https://en.google.com/blah/*/foo", 609 "https://fr.google.com/blah/*/foo", 610 false 611 }, 612 { "https://www.google.com/blah/*/foo", 613 "https://*.google.com/blah/*/foo", 614 false 615 }, 616 { "https://*.google.com/blah/*/foo", 617 "https://*.google.com/blah/*/foo", 618 true 619 }, 620 621 // domains 622 { "http://en.example.com/blah/*/foo", 623 "http://en.google.com/blah/*/foo", 624 false 625 }, 626 627 // ports 628 { "http://en.google.com:8000/blah/*/foo", 629 "http://en.google.com/blah/*/foo", 630 false 631 }, 632 { "http://fr.google.com:8000/blah/*/foo", 633 "http://fr.google.com:8000/blah/*/foo", 634 true 635 }, 636 { "http://en.google.com:8000/blah/*/foo", 637 "http://en.google.com:8080/blah/*/foo", 638 false 639 }, 640 641 // paths 642 { "http://en.google.com/blah/*/foo", 643 "http://en.google.com/blah/*", 644 false 645 }, 646 { "http://en.google.com/*", 647 "http://en.google.com/", 648 false 649 }, 650 { "http://en.google.com/*", 651 "http://en.google.com/*", 652 true 653 }, 654 655 // all_urls 656 { "<all_urls>", 657 "<all_urls>", 658 true 659 }, 660 { "<all_urls>", 661 "http://*/*", 662 false 663 } 664 }; 665 666 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kEqualsTestCases); ++i) { 667 std::string message = kEqualsTestCases[i].pattern1; 668 message += " "; 669 message += kEqualsTestCases[i].pattern2; 670 671 URLPattern pattern1(URLPattern::SCHEME_ALL); 672 URLPattern pattern2(URLPattern::SCHEME_ALL); 673 674 pattern1.Parse(kEqualsTestCases[i].pattern1); 675 pattern2.Parse(kEqualsTestCases[i].pattern2); 676 EXPECT_EQ(kEqualsTestCases[i].expected_equal, pattern1 == pattern2) 677 << message; 678 } 679} 680 681TEST(ExtensionURLPatternTest, CanReusePatternWithParse) { 682 URLPattern pattern1(URLPattern::SCHEME_ALL); 683 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern1.Parse("http://aa.com/*")); 684 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern1.Parse("http://bb.com/*")); 685 686 EXPECT_TRUE(pattern1.MatchesURL(GURL("http://bb.com/path"))); 687 EXPECT_FALSE(pattern1.MatchesURL(GURL("http://aa.com/path"))); 688 689 URLPattern pattern2(URLPattern::SCHEME_ALL, URLPattern::kAllUrlsPattern); 690 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern2.Parse("http://aa.com/*")); 691 692 EXPECT_FALSE(pattern2.MatchesURL(GURL("http://bb.com/path"))); 693 EXPECT_TRUE(pattern2.MatchesURL(GURL("http://aa.com/path"))); 694 EXPECT_FALSE(pattern2.MatchesURL(GURL("http://sub.aa.com/path"))); 695 696 URLPattern pattern3(URLPattern::SCHEME_ALL, "http://aa.com/*"); 697 EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern3.Parse("http://aa.com:88/*")); 698 EXPECT_FALSE(pattern3.MatchesURL(GURL("http://aa.com/path"))); 699 EXPECT_TRUE(pattern3.MatchesURL(GURL("http://aa.com:88/path"))); 700} 701 702// Returns success if neither |a| nor |b| encompasses the other. 703testing::AssertionResult NeitherContains(const URLPattern& a, 704 const URLPattern& b) { 705 if (a.Contains(b)) 706 return testing::AssertionFailure() << a.GetAsString() << " encompasses " << 707 b.GetAsString(); 708 if (b.Contains(a)) 709 return testing::AssertionFailure() << b.GetAsString() << " encompasses " << 710 a.GetAsString(); 711 return testing::AssertionSuccess() << 712 "Neither " << a.GetAsString() << " nor " << b.GetAsString() << 713 " encompass the other"; 714} 715 716// Returns success if |a| encompasses |b| but not the other way around. 717testing::AssertionResult StrictlyContains(const URLPattern& a, 718 const URLPattern& b) { 719 if (!a.Contains(b)) 720 return testing::AssertionFailure() << a.GetAsString() << 721 " does not encompass " << 722 b.GetAsString(); 723 if (b.Contains(a)) 724 return testing::AssertionFailure() << b.GetAsString() << " encompasses " << 725 a.GetAsString(); 726 return testing::AssertionSuccess() << a.GetAsString() << 727 " strictly encompasses " << 728 b.GetAsString(); 729} 730 731TEST(ExtensionURLPatternTest, Subset) { 732 URLPattern pattern1(kAllSchemes, "http://www.google.com/foo/*"); 733 URLPattern pattern2(kAllSchemes, "https://www.google.com/foo/*"); 734 URLPattern pattern3(kAllSchemes, "http://*.google.com/foo/*"); 735 URLPattern pattern4(kAllSchemes, "http://*.yahooo.com/foo/*"); 736 URLPattern pattern5(kAllSchemes, "http://www.yahooo.com/bar/*"); 737 URLPattern pattern6(kAllSchemes, "http://www.yahooo.com/bar/baz/*"); 738 URLPattern pattern7(kAllSchemes, "file:///*"); 739 URLPattern pattern8(kAllSchemes, "*://*/*"); 740 URLPattern pattern9(URLPattern::SCHEME_HTTPS, "*://*/*"); 741 URLPattern pattern10(kAllSchemes, "<all_urls>"); 742 URLPattern pattern11(kAllSchemes, "http://example.com/*"); 743 URLPattern pattern12(kAllSchemes, "*://example.com/*"); 744 URLPattern pattern13(kAllSchemes, "*://example.com/foo/*"); 745 746 // All patterns should encompass themselves. 747 EXPECT_TRUE(pattern1.Contains(pattern1)); 748 EXPECT_TRUE(pattern2.Contains(pattern2)); 749 EXPECT_TRUE(pattern3.Contains(pattern3)); 750 EXPECT_TRUE(pattern4.Contains(pattern4)); 751 EXPECT_TRUE(pattern5.Contains(pattern5)); 752 EXPECT_TRUE(pattern6.Contains(pattern6)); 753 EXPECT_TRUE(pattern7.Contains(pattern7)); 754 EXPECT_TRUE(pattern8.Contains(pattern8)); 755 EXPECT_TRUE(pattern9.Contains(pattern9)); 756 EXPECT_TRUE(pattern10.Contains(pattern10)); 757 EXPECT_TRUE(pattern11.Contains(pattern11)); 758 EXPECT_TRUE(pattern12.Contains(pattern12)); 759 EXPECT_TRUE(pattern13.Contains(pattern13)); 760 761 // pattern1's relationship to the other patterns. 762 EXPECT_TRUE(NeitherContains(pattern1, pattern2)); 763 EXPECT_TRUE(StrictlyContains(pattern3, pattern1)); 764 EXPECT_TRUE(NeitherContains(pattern1, pattern4)); 765 EXPECT_TRUE(NeitherContains(pattern1, pattern5)); 766 EXPECT_TRUE(NeitherContains(pattern1, pattern6)); 767 EXPECT_TRUE(NeitherContains(pattern1, pattern7)); 768 EXPECT_TRUE(StrictlyContains(pattern8, pattern1)); 769 EXPECT_TRUE(NeitherContains(pattern1, pattern9)); 770 EXPECT_TRUE(StrictlyContains(pattern10, pattern1)); 771 EXPECT_TRUE(NeitherContains(pattern1, pattern11)); 772 EXPECT_TRUE(NeitherContains(pattern1, pattern12)); 773 EXPECT_TRUE(NeitherContains(pattern1, pattern13)); 774 775 // pattern2's relationship to the other patterns. 776 EXPECT_TRUE(NeitherContains(pattern2, pattern3)); 777 EXPECT_TRUE(NeitherContains(pattern2, pattern4)); 778 EXPECT_TRUE(NeitherContains(pattern2, pattern5)); 779 EXPECT_TRUE(NeitherContains(pattern2, pattern6)); 780 EXPECT_TRUE(NeitherContains(pattern2, pattern7)); 781 EXPECT_TRUE(StrictlyContains(pattern8, pattern2)); 782 EXPECT_TRUE(StrictlyContains(pattern9, pattern2)); 783 EXPECT_TRUE(StrictlyContains(pattern10, pattern2)); 784 EXPECT_TRUE(NeitherContains(pattern2, pattern11)); 785 EXPECT_TRUE(NeitherContains(pattern2, pattern12)); 786 EXPECT_TRUE(NeitherContains(pattern2, pattern13)); 787 788 // Specifically test file:// URLs. 789 EXPECT_TRUE(NeitherContains(pattern7, pattern8)); 790 EXPECT_TRUE(NeitherContains(pattern7, pattern9)); 791 EXPECT_TRUE(StrictlyContains(pattern10, pattern7)); 792 793 // <all_urls> encompasses everything. 794 EXPECT_TRUE(StrictlyContains(pattern10, pattern1)); 795 EXPECT_TRUE(StrictlyContains(pattern10, pattern2)); 796 EXPECT_TRUE(StrictlyContains(pattern10, pattern3)); 797 EXPECT_TRUE(StrictlyContains(pattern10, pattern4)); 798 EXPECT_TRUE(StrictlyContains(pattern10, pattern5)); 799 EXPECT_TRUE(StrictlyContains(pattern10, pattern6)); 800 EXPECT_TRUE(StrictlyContains(pattern10, pattern7)); 801 EXPECT_TRUE(StrictlyContains(pattern10, pattern8)); 802 EXPECT_TRUE(StrictlyContains(pattern10, pattern9)); 803 EXPECT_TRUE(StrictlyContains(pattern10, pattern11)); 804 EXPECT_TRUE(StrictlyContains(pattern10, pattern12)); 805 EXPECT_TRUE(StrictlyContains(pattern10, pattern13)); 806 807 // More... 808 EXPECT_TRUE(StrictlyContains(pattern12, pattern11)); 809 EXPECT_TRUE(NeitherContains(pattern11, pattern13)); 810 EXPECT_TRUE(StrictlyContains(pattern12, pattern13)); 811} 812 813TEST(ExtensionURLPatternTest, MatchesSingleOrigin) { 814 EXPECT_FALSE( 815 URLPattern(URLPattern::SCHEME_ALL, "http://*/").MatchesSingleOrigin()); 816 EXPECT_FALSE(URLPattern(URLPattern::SCHEME_ALL, "https://*.google.com/*") 817 .MatchesSingleOrigin()); 818 EXPECT_TRUE(URLPattern(URLPattern::SCHEME_ALL, "http://google.com/") 819 .MatchesSingleOrigin()); 820 EXPECT_TRUE(URLPattern(URLPattern::SCHEME_ALL, "http://google.com/*") 821 .MatchesSingleOrigin()); 822 EXPECT_TRUE(URLPattern(URLPattern::SCHEME_ALL, "http://www.google.com/") 823 .MatchesSingleOrigin()); 824 EXPECT_FALSE(URLPattern(URLPattern::SCHEME_ALL, "*://www.google.com/") 825 .MatchesSingleOrigin()); 826 EXPECT_FALSE(URLPattern(URLPattern::SCHEME_ALL, "http://*.com/") 827 .MatchesSingleOrigin()); 828 EXPECT_FALSE(URLPattern(URLPattern::SCHEME_ALL, "http://*.google.com/foo/bar") 829 .MatchesSingleOrigin()); 830 EXPECT_TRUE( 831 URLPattern(URLPattern::SCHEME_ALL, "http://www.google.com/foo/bar") 832 .MatchesSingleOrigin()); 833 EXPECT_FALSE(URLPattern(URLPattern::SCHEME_HTTPS, "*://*.google.com/foo/bar") 834 .MatchesSingleOrigin()); 835 EXPECT_TRUE(URLPattern(URLPattern::SCHEME_HTTPS, "https://www.google.com/") 836 .MatchesSingleOrigin()); 837 EXPECT_FALSE(URLPattern(URLPattern::SCHEME_HTTP, 838 "http://*.google.com/foo/bar").MatchesSingleOrigin()); 839 EXPECT_TRUE( 840 URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/foo/bar") 841 .MatchesSingleOrigin()); 842} 843 844} // namespace 845