diff options
author | markusheintz@chromium.org <markusheintz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-06 08:04:43 +0000 |
---|---|---|
committer | markusheintz@chromium.org <markusheintz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-06 08:04:43 +0000 |
commit | a49cf1180910069e5fa25c8585d71b73df05858c (patch) | |
tree | cedd5024683d9810aaebb19a3c95bab51272bd9a /chrome | |
parent | d068d962e4c2a23c9095c4baf64640b74c231841 (diff) | |
download | chromium_src-a49cf1180910069e5fa25c8585d71b73df05858c.zip chromium_src-a49cf1180910069e5fa25c8585d71b73df05858c.tar.gz chromium_src-a49cf1180910069e5fa25c8585d71b73df05858c.tar.bz2 |
Allow invalid ContentSettingsPatterns to be compared.
Modify the ContentSettingsPatterns::Compare method so that it describes an order on content settings patterns.
BUG=63656, 84644
TEST=content_settings_pattern_unittest.cc
Review URL: http://codereview.chromium.org/6969095
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@87971 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
3 files changed, 177 insertions, 47 deletions
diff --git a/chrome/browser/content_settings/content_settings_pattern.cc b/chrome/browser/content_settings/content_settings_pattern.cc index ee15564..333df76 100644 --- a/chrome/browser/content_settings/content_settings_pattern.cc +++ b/chrome/browser/content_settings/content_settings_pattern.cc @@ -4,6 +4,9 @@ #include "chrome/browser/content_settings/content_settings_pattern.h" +#include <vector> + +#include "base/string_split.h" #include "base/string_util.h" #include "base/scoped_ptr.h" #include "chrome/browser/content_settings/content_settings_pattern_parser.h" @@ -41,6 +44,37 @@ bool IsSubDomainOrEqual(const std::string sub_domain, return true; } +// Compares two domain names. +int CompareDomainNames(const std::string& str1, const std::string& str2) { + std::vector<std::string> domain_name1; + std::vector<std::string> domain_name2; + + base::SplitString(str1, '.', &domain_name1); + base::SplitString(str2, '.', &domain_name2); + + int i1 = domain_name1.size() - 1; + int i2 = domain_name2.size() - 1; + int rv; + while (i1 >= 0 && i2 >= 0) { + // domain names are stored in puny code. So it's fine to use the compare + // method. + rv = domain_name1[i1].compare(domain_name2[i2]); + if (rv != 0) + return rv; + --i1; + --i2; + } + + if (i1 > i2) + return 1; + + if (i1 < i2) + return -1; + + // The domain names are identical. + return 0; +} + typedef ContentSettingsPattern::BuilderInterface BuilderInterface; } // namespace @@ -343,24 +377,33 @@ const std::string ContentSettingsPattern::ToString() const { ContentSettingsPattern::Relation ContentSettingsPattern::Compare( const ContentSettingsPattern& other) const { - if (this == &other) + // Two invalid patterns are identical in the way they behave. They don't match + // anything and are represented as an empty string. So it's fair to treat them + // as identical. + if ((this == &other) || + (!is_valid_ && !other.is_valid_)) return IDENTITY; - if (!is_valid_ || !other.is_valid_) { - NOTREACHED(); - return DISJOINT; - } + if (!is_valid_ && other.is_valid_) + return DISJOINT_ORDER_POST; + if (is_valid_ && !other.is_valid_) + return DISJOINT_ORDER_PRE; // If either host, port or scheme are disjoint return immediately. Relation host_relation = CompareHost(parts_, other.parts_); - if (host_relation == DISJOINT) - return DISJOINT; + if (host_relation == DISJOINT_ORDER_PRE || + host_relation == DISJOINT_ORDER_POST) + return host_relation; + Relation port_relation = ComparePort(parts_, other.parts_); - if (port_relation == DISJOINT) - return DISJOINT; + if (port_relation == DISJOINT_ORDER_PRE || + port_relation == DISJOINT_ORDER_POST) + return port_relation; + Relation scheme_relation = CompareScheme(parts_, other.parts_); - if (scheme_relation == DISJOINT) - return DISJOINT; + if (scheme_relation == DISJOINT_ORDER_PRE || + scheme_relation == DISJOINT_ORDER_POST) + return scheme_relation; if (host_relation != IDENTITY) return host_relation; @@ -369,17 +412,33 @@ ContentSettingsPattern::Relation ContentSettingsPattern::Compare( return scheme_relation; } +bool ContentSettingsPattern::operator==( + const ContentSettingsPattern& other) const { + return Compare(other) == IDENTITY; +} + +bool ContentSettingsPattern::operator<( + const ContentSettingsPattern& other) const { + return Compare(other) < 0; +} + +bool ContentSettingsPattern::operator>( + const ContentSettingsPattern& other) const { + return Compare(other) > 0; +} + // static ContentSettingsPattern::Relation ContentSettingsPattern::CompareHost( const ContentSettingsPattern::PatternParts& parts, const ContentSettingsPattern::PatternParts& other_parts) { if (!parts.has_domain_wildcard && !other_parts.has_domain_wildcard) { // Case 1: No host starts with a wild card - if (parts.host == other_parts.host) { + int result = CompareDomainNames(parts.host, other_parts.host); + if (result == 0) return ContentSettingsPattern::IDENTITY; - } else { - return ContentSettingsPattern::DISJOINT; - } + if (result < 0) + return ContentSettingsPattern::DISJOINT_ORDER_PRE; + return ContentSettingsPattern::DISJOINT_ORDER_POST; } else if (parts.has_domain_wildcard && !other_parts.has_domain_wildcard) { // Case 2: |host| starts with a domain wildcard and |other_host| does not // start with a domain wildcard. @@ -404,7 +463,9 @@ ContentSettingsPattern::Relation ContentSettingsPattern::CompareHost( if (IsSubDomainOrEqual(other_parts.host, parts.host)) { return ContentSettingsPattern::SUCCESSOR; } else { - return ContentSettingsPattern::DISJOINT; + if (CompareDomainNames(parts.host, other_parts.host) < 0) + return ContentSettingsPattern::DISJOINT_ORDER_PRE; + return ContentSettingsPattern::DISJOINT_ORDER_POST; } } else if (!parts.has_domain_wildcard && other_parts.has_domain_wildcard) { // Case 3: |host| starts NOT with a domain wildcard and |other_host| starts @@ -412,7 +473,9 @@ ContentSettingsPattern::Relation ContentSettingsPattern::CompareHost( if (IsSubDomainOrEqual(parts.host, other_parts.host)) { return ContentSettingsPattern::PREDECESSOR; } else { - return ContentSettingsPattern::DISJOINT; + if (CompareDomainNames(parts.host, other_parts.host) < 0) + return ContentSettingsPattern::DISJOINT_ORDER_PRE; + return ContentSettingsPattern::DISJOINT_ORDER_POST; } } else if (parts.has_domain_wildcard && other_parts.has_domain_wildcard) { // Case 4: |host| and |other_host| both start with a domain wildcard. @@ -441,7 +504,9 @@ ContentSettingsPattern::Relation ContentSettingsPattern::CompareHost( } else if (IsSubDomainOrEqual(parts.host, other_parts.host)) { return ContentSettingsPattern::PREDECESSOR; } else { - return ContentSettingsPattern::DISJOINT; + if (CompareDomainNames(parts.host, other_parts.host) < 0) + return ContentSettingsPattern::DISJOINT_ORDER_PRE; + return ContentSettingsPattern::DISJOINT_ORDER_POST; } } @@ -457,9 +522,13 @@ ContentSettingsPattern::Relation ContentSettingsPattern::CompareScheme( return ContentSettingsPattern::SUCCESSOR; if (!parts.is_scheme_wildcard && other_parts.is_scheme_wildcard) return ContentSettingsPattern::PREDECESSOR; - if (parts.scheme != other_parts.scheme) - return ContentSettingsPattern::DISJOINT; - return ContentSettingsPattern::IDENTITY; + + int result = parts.scheme.compare(other_parts.scheme); + if (result == 0) + return ContentSettingsPattern::IDENTITY; + if (result > 0) + return ContentSettingsPattern::DISJOINT_ORDER_PRE; + return ContentSettingsPattern::DISJOINT_ORDER_POST; } // static @@ -470,7 +539,11 @@ ContentSettingsPattern::Relation ContentSettingsPattern::ComparePort( return ContentSettingsPattern::SUCCESSOR; if (!parts.is_port_wildcard && other_parts.is_port_wildcard) return ContentSettingsPattern::PREDECESSOR; - if (parts.port != other_parts.port) - return ContentSettingsPattern::DISJOINT; - return ContentSettingsPattern::IDENTITY; + + int result = parts.port.compare(other_parts.port); + if (result == 0) + return ContentSettingsPattern::IDENTITY; + if (result > 0) + return ContentSettingsPattern::DISJOINT_ORDER_PRE; + return ContentSettingsPattern::DISJOINT_ORDER_POST; } diff --git a/chrome/browser/content_settings/content_settings_pattern.h b/chrome/browser/content_settings/content_settings_pattern.h index 5bfb6d8..445d0cd 100644 --- a/chrome/browser/content_settings/content_settings_pattern.h +++ b/chrome/browser/content_settings/content_settings_pattern.h @@ -26,21 +26,33 @@ class ContentSettingsPattern { // Each content settings pattern describes a set of origins. Patterns, and the // sets they describe, have specific relations. |Relation| describes the // relation of two patterns A and B. When pattern A is compared with pattern B - // (|A.Compare(B)|) interesting relations are: - // - IDENTITY: Pattern A and B are identical. The patterns are equal. - // - DISJOINT: Pattern A and B have no intersection. A and B never both - // match the origin of a URL. - // - SUCCESSOR: Pattern A and B have an intersection. But pattern B has a - // higher precedence than pattern A for URLs that are matched - // by both pattern. - // - PREDECESSOR: Pattern A and B have an intersection. But pattern A has a - // higher precedence than pattern B for URLs that are matched - // by both pattern. + // (A compare B) interesting relations are: + // - IDENTITY: + // Pattern A and B are identical. The patterns are equal. + // + // - DISJOINT_ORDER_PRE: + // Pattern A and B have no intersection. A and B never match the origin of + // a URL at the same time. But pattern A has a higher precedence than + // pattern B when patterns are sorted. + // + // - DISJOINT_ORDER_POST: + // Pattern A and B have no intersection. A and B never match the origin of + // a URL at the same time. But pattern A has a lower precedence than + // pattern B when patterns are sorted. + // + // - SUCCESSOR: + // Pattern A and B have an intersection. But pattern B has a higher + // precedence than pattern A for URLs that are matched by both pattern. + // + // - PREDECESSOR: + // Pattern A and B have an intersection. But pattern A has a higher + // precedence than pattern B for URLs that are matched by both pattern. enum Relation { - DISJOINT = -2, + DISJOINT_ORDER_POST = -2, SUCCESSOR = -1, IDENTITY = 0, PREDECESSOR = 1, + DISJOINT_ORDER_PRE = 2, }; class BuilderInterface { @@ -118,9 +130,14 @@ class ContentSettingsPattern { // |Relation| of the two patterns. Relation Compare(const ContentSettingsPattern& other) const; - bool operator==(const ContentSettingsPattern& other) const { - return Compare(other) == IDENTITY; - } + // Returns true if the pattern and the |other| pattern are identical. + bool operator==(const ContentSettingsPattern& other) const; + + // Returns true if the pattern has a lower priority than the |other| pattern. + bool operator<(const ContentSettingsPattern& other) const; + + // Returns true if the pattern has a higher priority than the |other| pattern. + bool operator>(const ContentSettingsPattern& other) const; private: friend class content_settings::PatternParser; diff --git a/chrome/browser/content_settings/content_settings_pattern_unittest.cc b/chrome/browser/content_settings/content_settings_pattern_unittest.cc index 11bef1e..a985697 100644 --- a/chrome/browser/content_settings/content_settings_pattern_unittest.cc +++ b/chrome/browser/content_settings/content_settings_pattern_unittest.cc @@ -373,30 +373,70 @@ TEST(ContentSettingsPatternTest, Compare) { Pattern("*://[*.]google.com:*").Compare( Pattern("*://[*.]google.com:*"))); - // Test disjoint patterns. - EXPECT_EQ(ContentSettingsPattern::DISJOINT, + ContentSettingsPattern invalid_pattern1 = ContentSettingsPattern(); + ContentSettingsPattern invalid_pattern2 = Pattern("www.google.com*"); + + // Compare invalid patterns. + EXPECT_TRUE(!invalid_pattern1.IsValid()); + EXPECT_TRUE(!invalid_pattern2.IsValid()); + EXPECT_EQ(ContentSettingsPattern::IDENTITY, + invalid_pattern1.Compare(invalid_pattern2)); + EXPECT_TRUE(invalid_pattern1 == invalid_pattern2); + + // Compare a pattern with an IPv4 addresse to a pattern with a domain name. + EXPECT_EQ(ContentSettingsPattern::DISJOINT_ORDER_POST, + Pattern("http://www.google.com").Compare( + Pattern("127.0.0.1"))); + EXPECT_EQ(ContentSettingsPattern::DISJOINT_ORDER_PRE, + Pattern("127.0.0.1").Compare( + Pattern("http://www.google.com"))); + EXPECT_TRUE(Pattern("127.0.0.1") > Pattern("http://www.google.com")); + EXPECT_TRUE(Pattern("http://www.google.com") < Pattern("127.0.0.1")); + + // Compare a pattern with an IPv6 address to a patterns with a domain name. + EXPECT_EQ(ContentSettingsPattern::DISJOINT_ORDER_POST, + Pattern("http://www.google.com").Compare( + Pattern("[::1]"))); + EXPECT_EQ(ContentSettingsPattern::DISJOINT_ORDER_PRE, + Pattern("[::1]").Compare( + Pattern("http://www.google.com"))); + EXPECT_TRUE(Pattern("[::1]") > Pattern("http://www.google.com")); + EXPECT_TRUE(Pattern("http://www.google.com") < Pattern("[::1]")); + + // Compare a pattern with an IPv6 addresse to a pattern with an IPv4 addresse. + EXPECT_EQ(ContentSettingsPattern::DISJOINT_ORDER_PRE, + Pattern("127.0.0.1").Compare( + Pattern("[::1]"))); + EXPECT_EQ(ContentSettingsPattern::DISJOINT_ORDER_POST, + Pattern("[::1]").Compare( + Pattern("127.0.0.1"))); + EXPECT_TRUE(Pattern("[::1]") < Pattern("127.0.0.1")); + EXPECT_TRUE(Pattern("127.0.0.1") > Pattern("[::1]")); + + EXPECT_EQ(ContentSettingsPattern::DISJOINT_ORDER_PRE, Pattern("http://www.google.com").Compare( Pattern("http://www.youtube.com"))); - EXPECT_EQ(ContentSettingsPattern::DISJOINT, + EXPECT_EQ(ContentSettingsPattern::DISJOINT_ORDER_PRE, Pattern("http://[*.]google.com").Compare( Pattern("http://[*.]youtube.com"))); - EXPECT_EQ(ContentSettingsPattern::DISJOINT, + + EXPECT_EQ(ContentSettingsPattern::DISJOINT_ORDER_POST, Pattern("http://[*.]host.com").Compare( Pattern("http://[*.]evilhost.com"))); - EXPECT_EQ(ContentSettingsPattern::DISJOINT, + EXPECT_EQ(ContentSettingsPattern::DISJOINT_ORDER_POST, Pattern("*://www.google.com:80").Compare( Pattern("*://www.google.com:8080"))); - EXPECT_EQ(ContentSettingsPattern::DISJOINT, + EXPECT_EQ(ContentSettingsPattern::DISJOINT_ORDER_PRE, Pattern("https://www.google.com:80").Compare( Pattern("http://www.google.com:80"))); - EXPECT_EQ(ContentSettingsPattern::DISJOINT, + EXPECT_EQ(ContentSettingsPattern::DISJOINT_ORDER_PRE, Pattern("http://[*.]google.com:90").Compare( Pattern("http://mail.google.com:80"))); - EXPECT_EQ(ContentSettingsPattern::DISJOINT, + EXPECT_EQ(ContentSettingsPattern::DISJOINT_ORDER_PRE, Pattern("https://[*.]google.com:80").Compare( Pattern("http://mail.google.com:80"))); - EXPECT_EQ(ContentSettingsPattern::DISJOINT, + EXPECT_EQ(ContentSettingsPattern::DISJOINT_ORDER_PRE, Pattern("https://mail.google.com:*").Compare( Pattern("http://mail.google.com:80"))); |