summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authormarkusheintz@chromium.org <markusheintz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-06 08:04:43 +0000
committermarkusheintz@chromium.org <markusheintz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-06 08:04:43 +0000
commita49cf1180910069e5fa25c8585d71b73df05858c (patch)
treecedd5024683d9810aaebb19a3c95bab51272bd9a /chrome
parentd068d962e4c2a23c9095c4baf64640b74c231841 (diff)
downloadchromium_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')
-rw-r--r--chrome/browser/content_settings/content_settings_pattern.cc121
-rw-r--r--chrome/browser/content_settings/content_settings_pattern.h45
-rw-r--r--chrome/browser/content_settings/content_settings_pattern_unittest.cc58
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")));