| 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/content_settings_pattern.h" | 5 #include "chrome/common/content_settings_pattern.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/strings/string_split.h" | 10 #include "base/strings/string_split.h" |
| 11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 12 #include "chrome/common/content_settings_pattern_parser.h" | 12 #include "chrome/common/content_settings_pattern_parser.h" |
| 13 #include "chrome/common/render_messages.h" | 13 #include "components/content_settings/core/common/embedder_variables.h" |
| 14 #include "chrome/common/url_constants.h" | |
| 15 #include "extensions/common/constants.h" | |
| 16 #include "ipc/ipc_message_utils.h" | |
| 17 #include "net/base/dns_util.h" | 14 #include "net/base/dns_util.h" |
| 18 #include "net/base/net_util.h" | 15 #include "net/base/net_util.h" |
| 19 #include "url/gurl.h" | 16 #include "url/gurl.h" |
| 20 #include "url/url_canon.h" | |
| 21 | 17 |
| 22 namespace { | 18 namespace { |
| 23 | 19 |
| 24 std::string GetDefaultPort(const std::string& scheme) { | 20 std::string GetDefaultPort(const std::string& scheme) { |
| 25 if (scheme == url::kHttpScheme) | 21 if (scheme == url::kHttpScheme) |
| 26 return "80"; | 22 return "80"; |
| 27 if (scheme == url::kHttpsScheme) | 23 if (scheme == url::kHttpsScheme) |
| 28 return "443"; | 24 return "443"; |
| 29 return std::string(); | 25 return std::string(); |
| 30 } | 26 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 return 0; | 74 return 0; |
| 79 } | 75 } |
| 80 | 76 |
| 81 typedef ContentSettingsPattern::BuilderInterface BuilderInterface; | 77 typedef ContentSettingsPattern::BuilderInterface BuilderInterface; |
| 82 | 78 |
| 83 } // namespace | 79 } // namespace |
| 84 | 80 |
| 85 // //////////////////////////////////////////////////////////////////////////// | 81 // //////////////////////////////////////////////////////////////////////////// |
| 86 // ContentSettingsPattern::Builder | 82 // ContentSettingsPattern::Builder |
| 87 // | 83 // |
| 84 class ContentSettingsPattern::Builder : |
| 85 public ContentSettingsPattern::BuilderInterface { |
| 86 public: |
| 87 explicit Builder(bool use_legacy_validate); |
| 88 virtual ~Builder(); |
| 89 |
| 90 // BuilderInterface: |
| 91 virtual BuilderInterface* WithPort(const std::string& port) OVERRIDE; |
| 92 virtual BuilderInterface* WithPortWildcard() OVERRIDE; |
| 93 virtual BuilderInterface* WithHost(const std::string& host) OVERRIDE; |
| 94 virtual BuilderInterface* WithDomainWildcard() OVERRIDE; |
| 95 virtual BuilderInterface* WithScheme(const std::string& scheme) OVERRIDE; |
| 96 virtual BuilderInterface* WithSchemeWildcard() OVERRIDE; |
| 97 virtual BuilderInterface* WithPath(const std::string& path) OVERRIDE; |
| 98 virtual BuilderInterface* WithPathWildcard() OVERRIDE; |
| 99 virtual BuilderInterface* Invalid() OVERRIDE; |
| 100 virtual ContentSettingsPattern Build() OVERRIDE; |
| 101 |
| 102 private: |
| 103 // Canonicalizes the pattern parts so that they are ASCII only, either |
| 104 // in original (if it was already ASCII) or punycode form. Returns true if |
| 105 // the canonicalization was successful. |
| 106 static bool Canonicalize(PatternParts* parts); |
| 107 |
| 108 // Returns true when the pattern |parts| represent a valid pattern. |
| 109 static bool Validate(const PatternParts& parts); |
| 110 |
| 111 static bool LegacyValidate(const PatternParts& parts); |
| 112 |
| 113 bool is_valid_; |
| 114 |
| 115 bool use_legacy_validate_; |
| 116 |
| 117 PatternParts parts_; |
| 118 |
| 119 DISALLOW_COPY_AND_ASSIGN(Builder); |
| 120 }; |
| 121 |
| 88 ContentSettingsPattern::Builder::Builder(bool use_legacy_validate) | 122 ContentSettingsPattern::Builder::Builder(bool use_legacy_validate) |
| 89 : is_valid_(true), | 123 : is_valid_(true), |
| 90 use_legacy_validate_(use_legacy_validate) {} | 124 use_legacy_validate_(use_legacy_validate) {} |
| 91 | 125 |
| 92 ContentSettingsPattern::Builder::~Builder() {} | 126 ContentSettingsPattern::Builder::~Builder() {} |
| 93 | 127 |
| 94 BuilderInterface* ContentSettingsPattern::Builder::WithPort( | 128 BuilderInterface* ContentSettingsPattern::Builder::WithPort( |
| 95 const std::string& port) { | 129 const std::string& port) { |
| 96 parts_.port = port; | 130 parts_.port = port; |
| 97 parts_.is_port_wildcard = false; | 131 parts_.is_port_wildcard = false; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 if (parts.has_domain_wildcard || !parts.host.empty() || !parts.port.empty()) | 251 if (parts.has_domain_wildcard || !parts.host.empty() || !parts.port.empty()) |
| 218 return false; | 252 return false; |
| 219 if (parts.is_path_wildcard) | 253 if (parts.is_path_wildcard) |
| 220 return parts.path.empty(); | 254 return parts.path.empty(); |
| 221 return (!parts.path.empty() && | 255 return (!parts.path.empty() && |
| 222 parts.path != "/" && | 256 parts.path != "/" && |
| 223 parts.path.find("*") == std::string::npos); | 257 parts.path.find("*") == std::string::npos); |
| 224 } | 258 } |
| 225 | 259 |
| 226 // If the pattern is for an extension URL test if it is valid. | 260 // If the pattern is for an extension URL test if it is valid. |
| 227 if (parts.scheme == std::string(extensions::kExtensionScheme) && | 261 if (content_settings::IsNonPortScheme(parts.scheme) && |
| 228 parts.port.empty() && | 262 parts.port.empty() && |
| 229 !parts.is_port_wildcard) { | 263 !parts.is_port_wildcard) { |
| 230 return true; | 264 return true; |
| 231 } | 265 } |
| 232 | 266 |
| 233 // Non-file patterns are invalid if either the scheme, host or port part is | 267 // Non-file patterns are invalid if either the scheme, host or port part is |
| 234 // empty. | 268 // empty. |
| 235 if ((parts.scheme.empty() && !parts.is_scheme_wildcard) || | 269 if ((parts.scheme.empty() && !parts.is_scheme_wildcard) || |
| 236 (parts.host.empty() && !parts.has_domain_wildcard) || | 270 (parts.host.empty() && !parts.has_domain_wildcard) || |
| 237 (parts.port.empty() && !parts.is_port_wildcard)) { | 271 (parts.port.empty() && !parts.is_port_wildcard)) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 254 bool ContentSettingsPattern::Builder::LegacyValidate( | 288 bool ContentSettingsPattern::Builder::LegacyValidate( |
| 255 const PatternParts& parts) { | 289 const PatternParts& parts) { |
| 256 // If the pattern is for a "file-pattern" test if it is valid. | 290 // If the pattern is for a "file-pattern" test if it is valid. |
| 257 if (parts.scheme == std::string(url::kFileScheme) && | 291 if (parts.scheme == std::string(url::kFileScheme) && |
| 258 !parts.is_scheme_wildcard && | 292 !parts.is_scheme_wildcard && |
| 259 parts.host.empty() && | 293 parts.host.empty() && |
| 260 parts.port.empty()) | 294 parts.port.empty()) |
| 261 return true; | 295 return true; |
| 262 | 296 |
| 263 // If the pattern is for an extension URL test if it is valid. | 297 // If the pattern is for an extension URL test if it is valid. |
| 264 if (parts.scheme == std::string(extensions::kExtensionScheme) && | 298 if (content_settings::IsNonPortScheme(parts.scheme) && |
| 265 !parts.is_scheme_wildcard && | 299 !parts.is_scheme_wildcard && |
| 266 !parts.host.empty() && | 300 !parts.host.empty() && |
| 267 !parts.has_domain_wildcard && | 301 !parts.has_domain_wildcard && |
| 268 parts.port.empty() && | 302 parts.port.empty() && |
| 269 !parts.is_port_wildcard) | 303 !parts.is_port_wildcard) |
| 270 return true; | 304 return true; |
| 271 | 305 |
| 272 // Non-file patterns are invalid if either the scheme, host or port part is | 306 // Non-file patterns are invalid if either the scheme, host or port part is |
| 273 // empty. | 307 // empty. |
| 274 if ((!parts.is_scheme_wildcard) || | 308 if ((!parts.is_scheme_wildcard) || |
| (...skipping 29 matching lines...) Expand all Loading... |
| 304 // following patterns: | 338 // following patterns: |
| 305 // - [*.]domain.tld (matches domain.tld and all sub-domains) | 339 // - [*.]domain.tld (matches domain.tld and all sub-domains) |
| 306 // - host (matches an exact hostname) | 340 // - host (matches an exact hostname) |
| 307 // - a.b.c.d (matches an exact IPv4 ip) | 341 // - a.b.c.d (matches an exact IPv4 ip) |
| 308 // - [a:b:c:d:e:f:g:h] (matches an exact IPv6 ip) | 342 // - [a:b:c:d:e:f:g:h] (matches an exact IPv6 ip) |
| 309 // - file:///tmp/test.html (a complete URL without a host) | 343 // - file:///tmp/test.html (a complete URL without a host) |
| 310 // Version 2 adds a resource identifier for plugins. | 344 // Version 2 adds a resource identifier for plugins. |
| 311 // TODO(jochen): update once this feature is no longer behind a flag. | 345 // TODO(jochen): update once this feature is no longer behind a flag. |
| 312 const int ContentSettingsPattern::kContentSettingsPatternVersion = 1; | 346 const int ContentSettingsPattern::kContentSettingsPatternVersion = 1; |
| 313 | 347 |
| 314 // TODO(markusheintz): These two constants were moved to the Pattern Parser. | |
| 315 // Remove once the dependency of the ContentSettingsBaseProvider is removed. | |
| 316 const char* ContentSettingsPattern::kDomainWildcard = "[*.]"; | |
| 317 const size_t ContentSettingsPattern::kDomainWildcardLength = 4; | |
| 318 | |
| 319 // static | 348 // static |
| 320 BuilderInterface* ContentSettingsPattern::CreateBuilder( | 349 BuilderInterface* ContentSettingsPattern::CreateBuilder( |
| 321 bool validate) { | 350 bool validate) { |
| 322 return new Builder(validate); | 351 return new Builder(validate); |
| 323 } | 352 } |
| 324 | 353 |
| 325 // static | 354 // static |
| 326 ContentSettingsPattern ContentSettingsPattern::FromURL( | 355 ContentSettingsPattern ContentSettingsPattern::FromURL( |
| 327 const GURL& url) { | 356 const GURL& url) { |
| 328 scoped_ptr<ContentSettingsPattern::BuilderInterface> builder( | 357 scoped_ptr<ContentSettingsPattern::BuilderInterface> builder( |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 } | 410 } |
| 382 } | 411 } |
| 383 return builder->Build(); | 412 return builder->Build(); |
| 384 } | 413 } |
| 385 | 414 |
| 386 // static | 415 // static |
| 387 ContentSettingsPattern ContentSettingsPattern::FromString( | 416 ContentSettingsPattern ContentSettingsPattern::FromString( |
| 388 const std::string& pattern_spec) { | 417 const std::string& pattern_spec) { |
| 389 scoped_ptr<ContentSettingsPattern::BuilderInterface> builder( | 418 scoped_ptr<ContentSettingsPattern::BuilderInterface> builder( |
| 390 ContentSettingsPattern::CreateBuilder(false)); | 419 ContentSettingsPattern::CreateBuilder(false)); |
| 391 content_settings::PatternParser::Parse(pattern_spec, builder.get()); | 420 content_settings::PatternParser::Parse(pattern_spec, |
| 421 builder.get()); |
| 392 return builder->Build(); | 422 return builder->Build(); |
| 393 } | 423 } |
| 394 | 424 |
| 395 // static | |
| 396 ContentSettingsPattern ContentSettingsPattern::LegacyFromString( | |
| 397 const std::string& pattern_spec) { | |
| 398 scoped_ptr<ContentSettingsPattern::BuilderInterface> builder( | |
| 399 ContentSettingsPattern::CreateBuilder(true)); | |
| 400 content_settings::PatternParser::Parse(pattern_spec, builder.get()); | |
| 401 return builder->Build(); | |
| 402 } | |
| 403 | |
| 404 // static | 425 // static |
| 405 ContentSettingsPattern ContentSettingsPattern::Wildcard() { | 426 ContentSettingsPattern ContentSettingsPattern::Wildcard() { |
| 406 scoped_ptr<ContentSettingsPattern::BuilderInterface> builder( | 427 scoped_ptr<ContentSettingsPattern::BuilderInterface> builder( |
| 407 ContentSettingsPattern::CreateBuilder(true)); | 428 ContentSettingsPattern::CreateBuilder(true)); |
| 408 builder->WithSchemeWildcard()->WithDomainWildcard()->WithPortWildcard()-> | 429 builder->WithSchemeWildcard()->WithDomainWildcard()->WithPortWildcard()-> |
| 409 WithPathWildcard(); | 430 WithPathWildcard(); |
| 410 return builder->Build(); | 431 return builder->Build(); |
| 411 } | 432 } |
| 412 | 433 |
| 413 ContentSettingsPattern::ContentSettingsPattern() | 434 ContentSettingsPattern::ContentSettingsPattern() |
| 414 : is_valid_(false) { | 435 : is_valid_(false) { |
| 415 } | 436 } |
| 416 | 437 |
| 417 ContentSettingsPattern::ContentSettingsPattern( | 438 ContentSettingsPattern::ContentSettingsPattern( |
| 418 const PatternParts& parts, | 439 const PatternParts& parts, |
| 419 bool valid) | 440 bool valid) |
| 420 : parts_(parts), | 441 : parts_(parts), |
| 421 is_valid_(valid) { | 442 is_valid_(valid) { |
| 422 } | 443 } |
| 423 | 444 |
| 424 void ContentSettingsPattern::WriteToMessage(IPC::Message* m) const { | |
| 425 IPC::WriteParam(m, is_valid_); | |
| 426 IPC::WriteParam(m, parts_); | |
| 427 } | |
| 428 | |
| 429 bool ContentSettingsPattern::ReadFromMessage(const IPC::Message* m, | |
| 430 PickleIterator* iter) { | |
| 431 return IPC::ReadParam(m, iter, &is_valid_) && | |
| 432 IPC::ReadParam(m, iter, &parts_); | |
| 433 } | |
| 434 | |
| 435 bool ContentSettingsPattern::Matches( | 445 bool ContentSettingsPattern::Matches( |
| 436 const GURL& url) const { | 446 const GURL& url) const { |
| 437 // An invalid pattern matches nothing. | 447 // An invalid pattern matches nothing. |
| 438 if (!is_valid_) | 448 if (!is_valid_) |
| 439 return false; | 449 return false; |
| 440 | 450 |
| 441 const GURL* local_url = &url; | 451 const GURL* local_url = &url; |
| 442 if (url.SchemeIsFileSystem() && url.inner_url()) { | 452 if (url.SchemeIsFileSystem() && url.inner_url()) { |
| 443 local_url = url.inner_url(); | 453 local_url = url.inner_url(); |
| 444 } | 454 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 465 const std::string host(net::TrimEndingDot(local_url->host())); | 475 const std::string host(net::TrimEndingDot(local_url->host())); |
| 466 if (!parts_.has_domain_wildcard) { | 476 if (!parts_.has_domain_wildcard) { |
| 467 if (parts_.host != host) | 477 if (parts_.host != host) |
| 468 return false; | 478 return false; |
| 469 } else { | 479 } else { |
| 470 if (!IsSubDomainOrEqual(host, parts_.host)) | 480 if (!IsSubDomainOrEqual(host, parts_.host)) |
| 471 return false; | 481 return false; |
| 472 } | 482 } |
| 473 | 483 |
| 474 // For chrome extensions URLs ignore the port. | 484 // For chrome extensions URLs ignore the port. |
| 475 if (parts_.scheme == std::string(extensions::kExtensionScheme)) | 485 if (content_settings::IsNonPortScheme(parts_.scheme)) |
| 476 return true; | 486 return true; |
| 477 | 487 |
| 478 // Match the port part. | 488 // Match the port part. |
| 479 std::string port(local_url->port()); | 489 std::string port(local_url->port()); |
| 480 | 490 |
| 481 // Use the default port if the port string is empty. GURL returns an empty | 491 // Use the default port if the port string is empty. GURL returns an empty |
| 482 // string if no port at all was specified or if the default port was | 492 // string if no port at all was specified or if the default port was |
| 483 // specified. | 493 // specified. |
| 484 if (port.empty()) { | 494 if (port.empty()) { |
| 485 port = GetDefaultPort(scheme); | 495 port = GetDefaultPort(scheme); |
| 486 } | 496 } |
| 487 | 497 |
| 488 if (!parts_.is_port_wildcard && | 498 if (!parts_.is_port_wildcard && |
| 489 parts_.port != port ) { | 499 parts_.port != port ) { |
| 490 return false; | 500 return false; |
| 491 } | 501 } |
| 492 | 502 |
| 493 return true; | 503 return true; |
| 494 } | 504 } |
| 495 | 505 |
| 496 bool ContentSettingsPattern::MatchesAllHosts() const { | 506 bool ContentSettingsPattern::MatchesAllHosts() const { |
| 497 return parts_.has_domain_wildcard && parts_.host.empty(); | 507 return parts_.has_domain_wildcard && parts_.host.empty(); |
| 498 } | 508 } |
| 499 | 509 |
| 500 const std::string ContentSettingsPattern::ToString() const { | 510 std::string ContentSettingsPattern::ToString() const { |
| 501 if (IsValid()) | 511 if (IsValid()) |
| 502 return content_settings::PatternParser::ToString(parts_); | 512 return content_settings::PatternParser::ToString(parts_); |
| 503 else | 513 else |
| 504 return std::string(); | 514 return std::string(); |
| 505 } | 515 } |
| 506 | 516 |
| 507 ContentSettingsPattern::Relation ContentSettingsPattern::Compare( | 517 ContentSettingsPattern::Relation ContentSettingsPattern::Compare( |
| 508 const ContentSettingsPattern& other) const { | 518 const ContentSettingsPattern& other) const { |
| 509 // Two invalid patterns are identical in the way they behave. They don't match | 519 // Two invalid patterns are identical in the way they behave. They don't match |
| 510 // anything and are represented as an empty string. So it's fair to treat them | 520 // anything and are represented as an empty string. So it's fair to treat them |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 if (!parts.is_port_wildcard && other_parts.is_port_wildcard) | 684 if (!parts.is_port_wildcard && other_parts.is_port_wildcard) |
| 675 return ContentSettingsPattern::PREDECESSOR; | 685 return ContentSettingsPattern::PREDECESSOR; |
| 676 | 686 |
| 677 int result = parts.port.compare(other_parts.port); | 687 int result = parts.port.compare(other_parts.port); |
| 678 if (result == 0) | 688 if (result == 0) |
| 679 return ContentSettingsPattern::IDENTITY; | 689 return ContentSettingsPattern::IDENTITY; |
| 680 if (result > 0) | 690 if (result > 0) |
| 681 return ContentSettingsPattern::DISJOINT_ORDER_PRE; | 691 return ContentSettingsPattern::DISJOINT_ORDER_PRE; |
| 682 return ContentSettingsPattern::DISJOINT_ORDER_POST; | 692 return ContentSettingsPattern::DISJOINT_ORDER_POST; |
| 683 } | 693 } |
| OLD | NEW |