| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/browser/content_settings/content_settings_pattern.h" | 5 #include "chrome/browser/content_settings/content_settings_pattern.h" |
| 6 | 6 |
| 7 #include <vector> |
| 8 |
| 9 #include "base/string_split.h" |
| 7 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| 8 #include "base/scoped_ptr.h" | 11 #include "base/scoped_ptr.h" |
| 9 #include "chrome/browser/content_settings/content_settings_pattern_parser.h" | 12 #include "chrome/browser/content_settings/content_settings_pattern_parser.h" |
| 10 #include "chrome/common/url_constants.h" | 13 #include "chrome/common/url_constants.h" |
| 11 #include "net/base/dns_util.h" | 14 #include "net/base/dns_util.h" |
| 12 #include "net/base/net_util.h" | 15 #include "net/base/net_util.h" |
| 13 #include "googleurl/src/gurl.h" | 16 #include "googleurl/src/gurl.h" |
| 14 #include "googleurl/src/url_canon.h" | 17 #include "googleurl/src/url_canon.h" |
| 15 | 18 |
| 16 namespace { | 19 namespace { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 34 return true; | 37 return true; |
| 35 const size_t match = sub_domain.rfind(domain); | 38 const size_t match = sub_domain.rfind(domain); |
| 36 if (match == std::string::npos || | 39 if (match == std::string::npos || |
| 37 (match > 0 && sub_domain[match - 1] != '.') || | 40 (match > 0 && sub_domain[match - 1] != '.') || |
| 38 (match + domain.length() != sub_domain.length())) { | 41 (match + domain.length() != sub_domain.length())) { |
| 39 return false; | 42 return false; |
| 40 } | 43 } |
| 41 return true; | 44 return true; |
| 42 } | 45 } |
| 43 | 46 |
| 47 // Compares two domain names. |
| 48 int CompareDomainNames(const std::string& str1, const std::string& str2) { |
| 49 std::vector<std::string> domain_name1; |
| 50 std::vector<std::string> domain_name2; |
| 51 |
| 52 base::SplitString(str1, '.', &domain_name1); |
| 53 base::SplitString(str2, '.', &domain_name2); |
| 54 |
| 55 int i1 = domain_name1.size() - 1; |
| 56 int i2 = domain_name2.size() - 1; |
| 57 int rv; |
| 58 while (i1 >= 0 && i2 >= 0) { |
| 59 // domain names are stored in puny code. So it's fine to use the compare |
| 60 // method. |
| 61 rv = domain_name1[i1].compare(domain_name2[i2]); |
| 62 if (rv != 0) |
| 63 return rv; |
| 64 --i1; |
| 65 --i2; |
| 66 } |
| 67 |
| 68 if (i1 > i2) |
| 69 return 1; |
| 70 |
| 71 if (i1 < i2) |
| 72 return -1; |
| 73 |
| 74 // The domain names are identical. |
| 75 return 0; |
| 76 } |
| 77 |
| 44 typedef ContentSettingsPattern::BuilderInterface BuilderInterface; | 78 typedef ContentSettingsPattern::BuilderInterface BuilderInterface; |
| 45 | 79 |
| 46 } // namespace | 80 } // namespace |
| 47 | 81 |
| 48 // //////////////////////////////////////////////////////////////////////////// | 82 // //////////////////////////////////////////////////////////////////////////// |
| 49 // ContentSettingsPattern::Builder | 83 // ContentSettingsPattern::Builder |
| 50 // | 84 // |
| 51 | 85 |
| 52 ContentSettingsPattern::Builder::Builder() : invalid_(false) {} | 86 ContentSettingsPattern::Builder::Builder() : invalid_(false) {} |
| 53 | 87 |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 | 370 |
| 337 const std::string ContentSettingsPattern::ToString() const { | 371 const std::string ContentSettingsPattern::ToString() const { |
| 338 if (IsValid()) | 372 if (IsValid()) |
| 339 return content_settings::PatternParser::ToString(parts_); | 373 return content_settings::PatternParser::ToString(parts_); |
| 340 else | 374 else |
| 341 return ""; | 375 return ""; |
| 342 } | 376 } |
| 343 | 377 |
| 344 ContentSettingsPattern::Relation ContentSettingsPattern::Compare( | 378 ContentSettingsPattern::Relation ContentSettingsPattern::Compare( |
| 345 const ContentSettingsPattern& other) const { | 379 const ContentSettingsPattern& other) const { |
| 346 if (this == &other) | 380 // Two invalid patterns are identical in the way they behave. They don't match |
| 381 // anything and are represented as an empty string. So it's fair to treat them |
| 382 // as identical. |
| 383 if ((this == &other) || |
| 384 (!is_valid_ && !other.is_valid_)) |
| 347 return IDENTITY; | 385 return IDENTITY; |
| 348 | 386 |
| 349 if (!is_valid_ || !other.is_valid_) { | 387 if (!is_valid_ && other.is_valid_) |
| 350 NOTREACHED(); | 388 return DISJOINT_ORDER_POST; |
| 351 return DISJOINT; | 389 if (is_valid_ && !other.is_valid_) |
| 352 } | 390 return DISJOINT_ORDER_PRE; |
| 353 | 391 |
| 354 // If either host, port or scheme are disjoint return immediately. | 392 // If either host, port or scheme are disjoint return immediately. |
| 355 Relation host_relation = CompareHost(parts_, other.parts_); | 393 Relation host_relation = CompareHost(parts_, other.parts_); |
| 356 if (host_relation == DISJOINT) | 394 if (host_relation == DISJOINT_ORDER_PRE || |
| 357 return DISJOINT; | 395 host_relation == DISJOINT_ORDER_POST) |
| 396 return host_relation; |
| 397 |
| 358 Relation port_relation = ComparePort(parts_, other.parts_); | 398 Relation port_relation = ComparePort(parts_, other.parts_); |
| 359 if (port_relation == DISJOINT) | 399 if (port_relation == DISJOINT_ORDER_PRE || |
| 360 return DISJOINT; | 400 port_relation == DISJOINT_ORDER_POST) |
| 401 return port_relation; |
| 402 |
| 361 Relation scheme_relation = CompareScheme(parts_, other.parts_); | 403 Relation scheme_relation = CompareScheme(parts_, other.parts_); |
| 362 if (scheme_relation == DISJOINT) | 404 if (scheme_relation == DISJOINT_ORDER_PRE || |
| 363 return DISJOINT; | 405 scheme_relation == DISJOINT_ORDER_POST) |
| 406 return scheme_relation; |
| 364 | 407 |
| 365 if (host_relation != IDENTITY) | 408 if (host_relation != IDENTITY) |
| 366 return host_relation; | 409 return host_relation; |
| 367 if (port_relation != IDENTITY) | 410 if (port_relation != IDENTITY) |
| 368 return port_relation; | 411 return port_relation; |
| 369 return scheme_relation; | 412 return scheme_relation; |
| 370 } | 413 } |
| 371 | 414 |
| 415 bool ContentSettingsPattern::operator==( |
| 416 const ContentSettingsPattern& other) const { |
| 417 return Compare(other) == IDENTITY; |
| 418 } |
| 419 |
| 420 bool ContentSettingsPattern::operator<( |
| 421 const ContentSettingsPattern& other) const { |
| 422 return Compare(other) < 0; |
| 423 } |
| 424 |
| 425 bool ContentSettingsPattern::operator>( |
| 426 const ContentSettingsPattern& other) const { |
| 427 return Compare(other) > 0; |
| 428 } |
| 429 |
| 372 // static | 430 // static |
| 373 ContentSettingsPattern::Relation ContentSettingsPattern::CompareHost( | 431 ContentSettingsPattern::Relation ContentSettingsPattern::CompareHost( |
| 374 const ContentSettingsPattern::PatternParts& parts, | 432 const ContentSettingsPattern::PatternParts& parts, |
| 375 const ContentSettingsPattern::PatternParts& other_parts) { | 433 const ContentSettingsPattern::PatternParts& other_parts) { |
| 376 if (!parts.has_domain_wildcard && !other_parts.has_domain_wildcard) { | 434 if (!parts.has_domain_wildcard && !other_parts.has_domain_wildcard) { |
| 377 // Case 1: No host starts with a wild card | 435 // Case 1: No host starts with a wild card |
| 378 if (parts.host == other_parts.host) { | 436 int result = CompareDomainNames(parts.host, other_parts.host); |
| 437 if (result == 0) |
| 379 return ContentSettingsPattern::IDENTITY; | 438 return ContentSettingsPattern::IDENTITY; |
| 380 } else { | 439 if (result < 0) |
| 381 return ContentSettingsPattern::DISJOINT; | 440 return ContentSettingsPattern::DISJOINT_ORDER_PRE; |
| 382 } | 441 return ContentSettingsPattern::DISJOINT_ORDER_POST; |
| 383 } else if (parts.has_domain_wildcard && !other_parts.has_domain_wildcard) { | 442 } else if (parts.has_domain_wildcard && !other_parts.has_domain_wildcard) { |
| 384 // Case 2: |host| starts with a domain wildcard and |other_host| does not | 443 // Case 2: |host| starts with a domain wildcard and |other_host| does not |
| 385 // start with a domain wildcard. | 444 // start with a domain wildcard. |
| 386 // Examples: | 445 // Examples: |
| 387 // "this" host: [*.]google.com | 446 // "this" host: [*.]google.com |
| 388 // "other" host: google.com | 447 // "other" host: google.com |
| 389 // | 448 // |
| 390 // [*.]google.com | 449 // [*.]google.com |
| 391 // mail.google.com | 450 // mail.google.com |
| 392 // | 451 // |
| 393 // [*.]mail.google.com | 452 // [*.]mail.google.com |
| 394 // google.com | 453 // google.com |
| 395 // | 454 // |
| 396 // [*.]youtube.com | 455 // [*.]youtube.com |
| 397 // google.de | 456 // google.de |
| 398 // | 457 // |
| 399 // [*.]youtube.com | 458 // [*.]youtube.com |
| 400 // mail.google.com | 459 // mail.google.com |
| 401 // | 460 // |
| 402 // * | 461 // * |
| 403 // google.de | 462 // google.de |
| 404 if (IsSubDomainOrEqual(other_parts.host, parts.host)) { | 463 if (IsSubDomainOrEqual(other_parts.host, parts.host)) { |
| 405 return ContentSettingsPattern::SUCCESSOR; | 464 return ContentSettingsPattern::SUCCESSOR; |
| 406 } else { | 465 } else { |
| 407 return ContentSettingsPattern::DISJOINT; | 466 if (CompareDomainNames(parts.host, other_parts.host) < 0) |
| 467 return ContentSettingsPattern::DISJOINT_ORDER_PRE; |
| 468 return ContentSettingsPattern::DISJOINT_ORDER_POST; |
| 408 } | 469 } |
| 409 } else if (!parts.has_domain_wildcard && other_parts.has_domain_wildcard) { | 470 } else if (!parts.has_domain_wildcard && other_parts.has_domain_wildcard) { |
| 410 // Case 3: |host| starts NOT with a domain wildcard and |other_host| starts | 471 // Case 3: |host| starts NOT with a domain wildcard and |other_host| starts |
| 411 // with a domain wildcard. | 472 // with a domain wildcard. |
| 412 if (IsSubDomainOrEqual(parts.host, other_parts.host)) { | 473 if (IsSubDomainOrEqual(parts.host, other_parts.host)) { |
| 413 return ContentSettingsPattern::PREDECESSOR; | 474 return ContentSettingsPattern::PREDECESSOR; |
| 414 } else { | 475 } else { |
| 415 return ContentSettingsPattern::DISJOINT; | 476 if (CompareDomainNames(parts.host, other_parts.host) < 0) |
| 477 return ContentSettingsPattern::DISJOINT_ORDER_PRE; |
| 478 return ContentSettingsPattern::DISJOINT_ORDER_POST; |
| 416 } | 479 } |
| 417 } else if (parts.has_domain_wildcard && other_parts.has_domain_wildcard) { | 480 } else if (parts.has_domain_wildcard && other_parts.has_domain_wildcard) { |
| 418 // Case 4: |host| and |other_host| both start with a domain wildcard. | 481 // Case 4: |host| and |other_host| both start with a domain wildcard. |
| 419 // Examples: | 482 // Examples: |
| 420 // [*.]google.com | 483 // [*.]google.com |
| 421 // [*.]google.com | 484 // [*.]google.com |
| 422 // | 485 // |
| 423 // [*.]google.com | 486 // [*.]google.com |
| 424 // [*.]mail.google.com | 487 // [*.]mail.google.com |
| 425 // | 488 // |
| 426 // [*.]youtube.com | 489 // [*.]youtube.com |
| 427 // [*.]google.de | 490 // [*.]google.de |
| 428 // | 491 // |
| 429 // [*.]youtube.com | 492 // [*.]youtube.com |
| 430 // [*.]mail.google.com | 493 // [*.]mail.google.com |
| 431 // | 494 // |
| 432 // [*.]youtube.com | 495 // [*.]youtube.com |
| 433 // * | 496 // * |
| 434 // | 497 // |
| 435 // * | 498 // * |
| 436 // [*.]youtube.com | 499 // [*.]youtube.com |
| 437 if (parts.host == other_parts.host) { | 500 if (parts.host == other_parts.host) { |
| 438 return ContentSettingsPattern::IDENTITY; | 501 return ContentSettingsPattern::IDENTITY; |
| 439 } else if (IsSubDomainOrEqual(other_parts.host, parts.host)) { | 502 } else if (IsSubDomainOrEqual(other_parts.host, parts.host)) { |
| 440 return ContentSettingsPattern::SUCCESSOR; | 503 return ContentSettingsPattern::SUCCESSOR; |
| 441 } else if (IsSubDomainOrEqual(parts.host, other_parts.host)) { | 504 } else if (IsSubDomainOrEqual(parts.host, other_parts.host)) { |
| 442 return ContentSettingsPattern::PREDECESSOR; | 505 return ContentSettingsPattern::PREDECESSOR; |
| 443 } else { | 506 } else { |
| 444 return ContentSettingsPattern::DISJOINT; | 507 if (CompareDomainNames(parts.host, other_parts.host) < 0) |
| 508 return ContentSettingsPattern::DISJOINT_ORDER_PRE; |
| 509 return ContentSettingsPattern::DISJOINT_ORDER_POST; |
| 445 } | 510 } |
| 446 } | 511 } |
| 447 | 512 |
| 448 NOTREACHED(); | 513 NOTREACHED(); |
| 449 return ContentSettingsPattern::IDENTITY; | 514 return ContentSettingsPattern::IDENTITY; |
| 450 } | 515 } |
| 451 | 516 |
| 452 // static | 517 // static |
| 453 ContentSettingsPattern::Relation ContentSettingsPattern::CompareScheme( | 518 ContentSettingsPattern::Relation ContentSettingsPattern::CompareScheme( |
| 454 const ContentSettingsPattern::PatternParts& parts, | 519 const ContentSettingsPattern::PatternParts& parts, |
| 455 const ContentSettingsPattern::PatternParts& other_parts) { | 520 const ContentSettingsPattern::PatternParts& other_parts) { |
| 456 if (parts.is_scheme_wildcard && !other_parts.is_scheme_wildcard) | 521 if (parts.is_scheme_wildcard && !other_parts.is_scheme_wildcard) |
| 457 return ContentSettingsPattern::SUCCESSOR; | 522 return ContentSettingsPattern::SUCCESSOR; |
| 458 if (!parts.is_scheme_wildcard && other_parts.is_scheme_wildcard) | 523 if (!parts.is_scheme_wildcard && other_parts.is_scheme_wildcard) |
| 459 return ContentSettingsPattern::PREDECESSOR; | 524 return ContentSettingsPattern::PREDECESSOR; |
| 460 if (parts.scheme != other_parts.scheme) | 525 |
| 461 return ContentSettingsPattern::DISJOINT; | 526 int result = parts.scheme.compare(other_parts.scheme); |
| 462 return ContentSettingsPattern::IDENTITY; | 527 if (result == 0) |
| 528 return ContentSettingsPattern::IDENTITY; |
| 529 if (result > 0) |
| 530 return ContentSettingsPattern::DISJOINT_ORDER_PRE; |
| 531 return ContentSettingsPattern::DISJOINT_ORDER_POST; |
| 463 } | 532 } |
| 464 | 533 |
| 465 // static | 534 // static |
| 466 ContentSettingsPattern::Relation ContentSettingsPattern::ComparePort( | 535 ContentSettingsPattern::Relation ContentSettingsPattern::ComparePort( |
| 467 const ContentSettingsPattern::PatternParts& parts, | 536 const ContentSettingsPattern::PatternParts& parts, |
| 468 const ContentSettingsPattern::PatternParts& other_parts) { | 537 const ContentSettingsPattern::PatternParts& other_parts) { |
| 469 if (parts.is_port_wildcard && !other_parts.is_port_wildcard) | 538 if (parts.is_port_wildcard && !other_parts.is_port_wildcard) |
| 470 return ContentSettingsPattern::SUCCESSOR; | 539 return ContentSettingsPattern::SUCCESSOR; |
| 471 if (!parts.is_port_wildcard && other_parts.is_port_wildcard) | 540 if (!parts.is_port_wildcard && other_parts.is_port_wildcard) |
| 472 return ContentSettingsPattern::PREDECESSOR; | 541 return ContentSettingsPattern::PREDECESSOR; |
| 473 if (parts.port != other_parts.port) | 542 |
| 474 return ContentSettingsPattern::DISJOINT; | 543 int result = parts.port.compare(other_parts.port); |
| 475 return ContentSettingsPattern::IDENTITY; | 544 if (result == 0) |
| 545 return ContentSettingsPattern::IDENTITY; |
| 546 if (result > 0) |
| 547 return ContentSettingsPattern::DISJOINT_ORDER_PRE; |
| 548 return ContentSettingsPattern::DISJOINT_ORDER_POST; |
| 476 } | 549 } |
| OLD | NEW |