Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/common/extensions/url_pattern.h" | 5 #include "chrome/common/extensions/url_pattern.h" |
| 6 | 6 |
| 7 #include "base/string_number_conversions.h" | 7 #include "base/string_number_conversions.h" |
| 8 #include "base/string_piece.h" | 8 #include "base/string_piece.h" |
| 9 #include "base/string_split.h" | 9 #include "base/string_split.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 60 kParseErrorInvalidHostWildcard, | 60 kParseErrorInvalidHostWildcard, |
| 61 kParseErrorEmptyPath, | 61 kParseErrorEmptyPath, |
| 62 kParseErrorInvalidPort, | 62 kParseErrorInvalidPort, |
| 63 }; | 63 }; |
| 64 | 64 |
| 65 COMPILE_ASSERT(URLPattern::NUM_PARSE_RESULTS == arraysize(kParseResultMessages), | 65 COMPILE_ASSERT(URLPattern::NUM_PARSE_RESULTS == arraysize(kParseResultMessages), |
| 66 must_add_message_for_each_parse_result); | 66 must_add_message_for_each_parse_result); |
| 67 | 67 |
| 68 const char kPathSeparator[] = "/"; | 68 const char kPathSeparator[] = "/"; |
| 69 | 69 |
| 70 bool IsStandardScheme(const std::string& scheme) { | 70 bool is_standard_scheme(const std::string& scheme) { |
|
Aaron Boodman
2012/03/21 23:51:57
Why rename this? I think the current capitalizatio
ericu
2012/03/22 00:22:14
You requested this change in your comments on patc
| |
| 71 // "*" gets the same treatment as a standard scheme. | 71 // "*" gets the same treatment as a standard scheme. |
| 72 if (scheme == "*") | 72 if (scheme == "*") |
| 73 return true; | 73 return true; |
| 74 | 74 |
| 75 return url_util::IsStandard(scheme.c_str(), | 75 return url_util::IsStandard(scheme.c_str(), |
| 76 url_parse::Component(0, static_cast<int>(scheme.length()))); | 76 url_parse::Component(0, static_cast<int>(scheme.length()))); |
| 77 } | 77 } |
| 78 | 78 |
| 79 bool IsValidPortForScheme(const std::string scheme, const std::string& port) { | 79 bool IsValidPortForScheme(const std::string scheme, const std::string& port) { |
| 80 if (port == "*") | 80 if (port == "*") |
| 81 return true; | 81 return true; |
| 82 | 82 |
| 83 // Only accept non-wildcard ports if the scheme uses ports. | 83 // Only accept non-wildcard ports if the scheme uses ports. |
| 84 if (url_canon::DefaultPortForScheme(scheme.c_str(), scheme.length()) == | 84 if (url_canon::DefaultPortForScheme(scheme.c_str(), scheme.length()) == |
| 85 url_parse::PORT_UNSPECIFIED) { | 85 url_parse::PORT_UNSPECIFIED) { |
| 86 return false; | 86 return false; |
| 87 } | 87 } |
| 88 | 88 |
| 89 int parsed_port = url_parse::PORT_UNSPECIFIED; | 89 int parsed_port = url_parse::PORT_UNSPECIFIED; |
| 90 if (!base::StringToInt(port, &parsed_port)) | 90 if (!base::StringToInt(port, &parsed_port)) |
| 91 return false; | 91 return false; |
| 92 return (parsed_port >= 0) && (parsed_port < 65536); | 92 return (parsed_port >= 0) && (parsed_port < 65536); |
| 93 } | 93 } |
| 94 | 94 |
| 95 } // namespace | 95 } // namespace |
| 96 | 96 |
| 97 URLPattern::URLPattern() | 97 URLPattern::URLPattern() |
| 98 : valid_schemes_(SCHEME_NONE), | 98 : valid_schemes_(SCHEME_NONE), |
| 99 match_all_urls_(false), | 99 match_all_urls_(false), |
| 100 match_nested_url_path_(false), | |
| 100 match_subdomains_(false), | 101 match_subdomains_(false), |
| 101 port_("*") {} | 102 port_("*") {} |
| 102 | 103 |
| 103 URLPattern::URLPattern(int valid_schemes) | 104 URLPattern::URLPattern(int valid_schemes) |
| 104 : valid_schemes_(valid_schemes), | 105 : valid_schemes_(valid_schemes), |
| 105 match_all_urls_(false), | 106 match_all_urls_(false), |
| 107 match_nested_url_path_(false), | |
| 106 match_subdomains_(false), | 108 match_subdomains_(false), |
| 107 port_("*") {} | 109 port_("*") {} |
| 108 | 110 |
| 109 URLPattern::URLPattern(int valid_schemes, const std::string& pattern) | 111 URLPattern::URLPattern(int valid_schemes, const std::string& pattern) |
| 110 // Strict error checking is used, because this constructor is only | 112 // Strict error checking is used, because this constructor is only |
| 111 // appropriate when we know |pattern| is valid. | 113 // appropriate when we know |pattern| is valid. |
| 112 : valid_schemes_(valid_schemes), | 114 : valid_schemes_(valid_schemes), |
| 113 match_all_urls_(false), | 115 match_all_urls_(false), |
| 116 match_nested_url_path_(false), | |
| 114 match_subdomains_(false), | 117 match_subdomains_(false), |
| 115 port_("*") { | 118 port_("*") { |
| 116 if (PARSE_SUCCESS != Parse(pattern)) | 119 if (PARSE_SUCCESS != Parse(pattern)) |
| 117 NOTREACHED() << "URLPattern is invalid: " << pattern; | 120 NOTREACHED() << "URLPattern is invalid: " << pattern; |
| 118 } | 121 } |
| 119 | 122 |
| 120 URLPattern::~URLPattern() { | 123 URLPattern::~URLPattern() { |
| 121 } | 124 } |
| 122 | 125 |
| 123 bool URLPattern::operator<(const URLPattern& other) const { | 126 bool URLPattern::operator<(const URLPattern& other) const { |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 149 scheme_end_pos = pattern.find(':'); | 152 scheme_end_pos = pattern.find(':'); |
| 150 has_standard_scheme_separator = false; | 153 has_standard_scheme_separator = false; |
| 151 } | 154 } |
| 152 | 155 |
| 153 if (scheme_end_pos == std::string::npos) | 156 if (scheme_end_pos == std::string::npos) |
| 154 return PARSE_ERROR_MISSING_SCHEME_SEPARATOR; | 157 return PARSE_ERROR_MISSING_SCHEME_SEPARATOR; |
| 155 | 158 |
| 156 if (!SetScheme(pattern.substr(0, scheme_end_pos))) | 159 if (!SetScheme(pattern.substr(0, scheme_end_pos))) |
| 157 return PARSE_ERROR_INVALID_SCHEME; | 160 return PARSE_ERROR_INVALID_SCHEME; |
| 158 | 161 |
| 159 bool standard_scheme = IsStandardScheme(scheme_); | 162 bool standard_scheme = is_standard_scheme(scheme_); |
| 160 if (standard_scheme != has_standard_scheme_separator) | 163 if (standard_scheme != has_standard_scheme_separator) |
| 161 return PARSE_ERROR_WRONG_SCHEME_SEPARATOR; | 164 return PARSE_ERROR_WRONG_SCHEME_SEPARATOR; |
| 162 | 165 |
| 163 // Advance past the scheme separator. | 166 // Advance past the scheme separator. |
| 164 scheme_end_pos += | 167 scheme_end_pos += |
| 165 (standard_scheme ? strlen(chrome::kStandardSchemeSeparator) : 1); | 168 (standard_scheme ? strlen(chrome::kStandardSchemeSeparator) : 1); |
| 166 if (scheme_end_pos >= pattern.size()) | 169 if (scheme_end_pos >= pattern.size()) |
| 167 return PARSE_ERROR_EMPTY_HOST; | 170 return PARSE_ERROR_EMPTY_HOST; |
| 168 | 171 |
| 169 // Parse out the host and path. | 172 // Parse out the host and path. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 242 match_all_urls_ = val; | 245 match_all_urls_ = val; |
| 243 | 246 |
| 244 if (val) { | 247 if (val) { |
| 245 match_subdomains_ = true; | 248 match_subdomains_ = true; |
| 246 scheme_ = "*"; | 249 scheme_ = "*"; |
| 247 host_.clear(); | 250 host_.clear(); |
| 248 SetPath("/*"); | 251 SetPath("/*"); |
| 249 } | 252 } |
| 250 } | 253 } |
| 251 | 254 |
| 255 void URLPattern::SetMatchNestedURLPath(bool val) { | |
|
Aaron Boodman
2012/03/21 23:51:57
This one on the other hand should be set_match_nes
ericu
2012/03/22 00:22:14
Done.
| |
| 256 match_nested_url_path_ = val; | |
| 257 } | |
| 258 | |
| 252 void URLPattern::SetMatchSubdomains(bool val) { | 259 void URLPattern::SetMatchSubdomains(bool val) { |
| 253 spec_.clear(); | 260 spec_.clear(); |
| 254 match_subdomains_ = val; | 261 match_subdomains_ = val; |
| 255 } | 262 } |
| 256 | 263 |
| 257 bool URLPattern::SetScheme(const std::string& scheme) { | 264 bool URLPattern::SetScheme(const std::string& scheme) { |
| 258 spec_.clear(); | 265 spec_.clear(); |
| 259 scheme_ = scheme; | 266 scheme_ = scheme; |
| 260 if (scheme_ == "*") { | 267 if (scheme_ == "*") { |
| 261 valid_schemes_ &= (SCHEME_HTTP | SCHEME_HTTPS); | 268 valid_schemes_ &= (SCHEME_HTTP | SCHEME_HTTPS); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 288 bool URLPattern::SetPort(const std::string& port) { | 295 bool URLPattern::SetPort(const std::string& port) { |
| 289 spec_.clear(); | 296 spec_.clear(); |
| 290 if (IsValidPortForScheme(scheme_, port)) { | 297 if (IsValidPortForScheme(scheme_, port)) { |
| 291 port_ = port; | 298 port_ = port; |
| 292 return true; | 299 return true; |
| 293 } | 300 } |
| 294 return false; | 301 return false; |
| 295 } | 302 } |
| 296 | 303 |
| 297 bool URLPattern::MatchesURL(const GURL& test) const { | 304 bool URLPattern::MatchesURL(const GURL& test) const { |
| 298 if (!MatchesScheme(test.scheme())) | 305 const GURL* test_url = &test; |
| 306 bool has_inner_url = false; | |
| 307 if (test.inner_url()) { | |
| 308 test_url = test.inner_url(); | |
| 309 has_inner_url = true; | |
| 310 } | |
| 311 | |
| 312 if (!MatchesScheme(test_url->scheme())) | |
| 299 return false; | 313 return false; |
| 300 | 314 |
| 301 if (match_all_urls_) | 315 if (match_all_urls_) |
| 302 return true; | 316 return true; |
| 303 | 317 |
| 304 return MatchesSecurityOriginHelper(test) && | 318 std::string path_for_request = test.PathForRequest(); |
| 305 MatchesPath(test.PathForRequest()); | 319 if (has_inner_url) { |
| 320 path_for_request = test_url->path() + path_for_request; | |
| 321 } | |
| 322 return MatchesSecurityOriginHelper(*test_url) && | |
| 323 MatchesPath(path_for_request, has_inner_url); | |
| 306 } | 324 } |
| 307 | 325 |
| 308 bool URLPattern::MatchesSecurityOrigin(const GURL& test) const { | 326 bool URLPattern::MatchesSecurityOrigin(const GURL& test) const { |
| 309 if (!MatchesScheme(test.scheme())) | 327 if (!MatchesScheme(test.scheme())) |
| 310 return false; | 328 return false; |
| 311 | 329 |
| 312 if (match_all_urls_) | 330 if (match_all_urls_) |
| 313 return true; | 331 return true; |
| 314 | 332 |
| 315 return MatchesSecurityOriginHelper(test); | 333 return MatchesSecurityOriginHelper(test); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 354 if (test.host().length() <= (host_.length() + 1)) | 372 if (test.host().length() <= (host_.length() + 1)) |
| 355 return false; | 373 return false; |
| 356 | 374 |
| 357 if (test.host().compare(test.host().length() - host_.length(), | 375 if (test.host().compare(test.host().length() - host_.length(), |
| 358 host_.length(), host_) != 0) | 376 host_.length(), host_) != 0) |
| 359 return false; | 377 return false; |
| 360 | 378 |
| 361 return test.host()[test.host().length() - host_.length() - 1] == '.'; | 379 return test.host()[test.host().length() - host_.length() - 1] == '.'; |
| 362 } | 380 } |
| 363 | 381 |
| 364 bool URLPattern::MatchesPath(const std::string& test) const { | 382 bool URLPattern::MatchesPath(const std::string& test, bool nested_url) |
| 383 const { | |
| 384 if (nested_url != match_nested_url_path_ && path_ != "/*") | |
| 385 return false; | |
| 365 if (!MatchPattern(test, path_escaped_)) | 386 if (!MatchPattern(test, path_escaped_)) |
| 366 return false; | 387 return false; |
| 367 | 388 |
| 368 return true; | 389 return true; |
| 369 } | 390 } |
| 370 | 391 |
| 371 bool URLPattern::MatchesPort(int port) const { | 392 bool URLPattern::MatchesPort(int port) const { |
| 372 if (port == url_parse::PORT_INVALID) | 393 if (port == url_parse::PORT_INVALID) |
| 373 return false; | 394 return false; |
| 374 | 395 |
| 375 return port_ == "*" || port_ == base::IntToString(port); | 396 return port_ == "*" || port_ == base::IntToString(port); |
| 376 } | 397 } |
| 377 | 398 |
| 378 | 399 |
| 379 const std::string& URLPattern::GetAsString() const { | 400 const std::string& URLPattern::GetAsString() const { |
| 380 if (!spec_.empty()) | 401 if (!spec_.empty()) |
| 381 return spec_; | 402 return spec_; |
| 382 | 403 |
| 383 if (match_all_urls_) { | 404 if (match_all_urls_) { |
| 384 spec_ = kAllUrlsPattern; | 405 spec_ = kAllUrlsPattern; |
| 385 return spec_; | 406 return spec_; |
| 386 } | 407 } |
| 387 | 408 |
| 388 bool standard_scheme = IsStandardScheme(scheme_); | 409 bool standard_scheme = is_standard_scheme(scheme_); |
| 389 | 410 |
| 390 std::string spec = scheme_ + | 411 std::string spec = scheme_ + |
| 391 (standard_scheme ? chrome::kStandardSchemeSeparator : ":"); | 412 (standard_scheme ? chrome::kStandardSchemeSeparator : ":"); |
| 392 | 413 |
| 393 if (scheme_ != chrome::kFileScheme && standard_scheme) { | 414 if (scheme_ != chrome::kFileScheme && standard_scheme) { |
| 394 if (match_subdomains_) { | 415 if (match_subdomains_) { |
| 395 spec += "*"; | 416 spec += "*"; |
| 396 if (!host_.empty()) | 417 if (!host_.empty()) |
| 397 spec += "."; | 418 spec += "."; |
| 398 } | 419 } |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 426 return false; | 447 return false; |
| 427 | 448 |
| 428 // We currently only use OverlapsWith() for the patterns inside | 449 // We currently only use OverlapsWith() for the patterns inside |
| 429 // URLPatternSet. In those cases, we know that the path will have only a | 450 // URLPatternSet. In those cases, we know that the path will have only a |
| 430 // single wildcard at the end. This makes figuring out overlap much easier. It | 451 // single wildcard at the end. This makes figuring out overlap much easier. It |
| 431 // seems like there is probably a computer-sciency way to solve the general | 452 // seems like there is probably a computer-sciency way to solve the general |
| 432 // case, but we don't need that yet. | 453 // case, but we don't need that yet. |
| 433 DCHECK(path_.find('*') == path_.size() - 1); | 454 DCHECK(path_.find('*') == path_.size() - 1); |
| 434 DCHECK(other.path().find('*') == other.path().size() - 1); | 455 DCHECK(other.path().find('*') == other.path().size() - 1); |
| 435 | 456 |
| 436 if (!MatchesPath(other.path().substr(0, other.path().size() - 1)) && | 457 if ((path_.size() > 2 || other.path().size() > 2) && |
| 437 !other.MatchesPath(path_.substr(0, path_.size() - 1))) | 458 match_nested_url_path_ != other.match_nested_url_path()) |
| 459 return false; | |
| 460 | |
| 461 if (!MatchesPath(other.path().substr(0, other.path().size() - 1), | |
| 462 match_nested_url_path_) && | |
| 463 !other.MatchesPath(path_.substr(0, path_.size() - 1), | |
| 464 match_nested_url_path_)) | |
| 438 return false; | 465 return false; |
| 439 | 466 |
| 440 return true; | 467 return true; |
| 441 } | 468 } |
| 442 | 469 |
| 443 bool URLPattern::MatchesAnyScheme( | 470 bool URLPattern::MatchesAnyScheme( |
| 444 const std::vector<std::string>& schemes) const { | 471 const std::vector<std::string>& schemes) const { |
| 445 for (std::vector<std::string>::const_iterator i = schemes.begin(); | 472 for (std::vector<std::string>::const_iterator i = schemes.begin(); |
| 446 i != schemes.end(); ++i) { | 473 i != schemes.end(); ++i) { |
| 447 if (MatchesScheme(*i)) | 474 if (MatchesScheme(*i)) |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 492 } | 519 } |
| 493 | 520 |
| 494 return result; | 521 return result; |
| 495 } | 522 } |
| 496 | 523 |
| 497 // static | 524 // static |
| 498 const char* URLPattern::GetParseResultString( | 525 const char* URLPattern::GetParseResultString( |
| 499 URLPattern::ParseResult parse_result) { | 526 URLPattern::ParseResult parse_result) { |
| 500 return kParseResultMessages[parse_result]; | 527 return kParseResultMessages[parse_result]; |
| 501 } | 528 } |
| OLD | NEW |