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/matcher/url_matcher_factory.h" | 5 #include "chrome/common/extensions/matcher/url_matcher_factory.h" |
6 | 6 |
| 7 #include "base/format_macros.h" |
| 8 #include "base/stringprintf.h" |
7 #include "base/values.h" | 9 #include "base/values.h" |
8 #include "chrome/common/extensions/matcher/url_matcher_constants.h" | 10 #include "chrome/common/extensions/matcher/url_matcher_constants.h" |
9 #include "googleurl/src/gurl.h" | 11 #include "googleurl/src/gurl.h" |
10 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
11 | 13 |
12 namespace extensions { | 14 namespace extensions { |
13 | 15 |
14 namespace keys = url_matcher_constants; | 16 namespace keys = url_matcher_constants; |
15 | 17 |
16 TEST(URLMatcherFactoryTest, CreateFromURLFilterDictionary) { | 18 TEST(URLMatcherFactoryTest, CreateFromURLFilterDictionary) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 EXPECT_EQ(1u, matcher.MatchURL(GURL("http://www.example.com:80")).size()); | 94 EXPECT_EQ(1u, matcher.MatchURL(GURL("http://www.example.com:80")).size()); |
93 EXPECT_EQ(1u, matcher.MatchURL(GURL("http://www.example.com:1000")).size()); | 95 EXPECT_EQ(1u, matcher.MatchURL(GURL("http://www.example.com:1000")).size()); |
94 // Wrong scheme. | 96 // Wrong scheme. |
95 EXPECT_EQ(0u, matcher.MatchURL(GURL("https://www.example.com:80")).size()); | 97 EXPECT_EQ(0u, matcher.MatchURL(GURL("https://www.example.com:80")).size()); |
96 // Wrong port. | 98 // Wrong port. |
97 EXPECT_EQ(0u, matcher.MatchURL(GURL("http://www.example.com:81")).size()); | 99 EXPECT_EQ(0u, matcher.MatchURL(GURL("http://www.example.com:81")).size()); |
98 // Unfulfilled host prefix. | 100 // Unfulfilled host prefix. |
99 EXPECT_EQ(0u, matcher.MatchURL(GURL("http://mail.example.com:81")).size()); | 101 EXPECT_EQ(0u, matcher.MatchURL(GURL("http://mail.example.com:81")).size()); |
100 } | 102 } |
101 | 103 |
| 104 // This class wraps a case sensitivity test for a single UrlFilter condition. |
| 105 class UrlConditionCaseTest { |
| 106 public: |
| 107 // The condition is identified by the key |condition_key|. If that key is |
| 108 // associated with string values, then |use_list_of_strings| should be false, |
| 109 // if the key is associated with list-of-string values, then |
| 110 // |use_list_of_strings| should be true. In |url| is the URL to test against. |
| 111 UrlConditionCaseTest(const char* condition_key, |
| 112 const bool use_list_of_strings, |
| 113 const std::string& expected_value, |
| 114 const std::string& incorrect_case_value, |
| 115 const bool case_sensitive, |
| 116 const GURL& url) |
| 117 : condition_key_(condition_key), |
| 118 use_list_of_strings_(use_list_of_strings), |
| 119 expected_value_(expected_value), |
| 120 incorrect_case_value_(incorrect_case_value), |
| 121 case_sensitive_(case_sensitive), |
| 122 url_(url) {} |
| 123 |
| 124 ~UrlConditionCaseTest() {} |
| 125 |
| 126 // Match the condition against |url_|. Checks via EXPECT_* macros that |
| 127 // |expected_value_| matches always, and that |incorrect_case_value_| matches |
| 128 // iff |case_sensitive_| is false. |
| 129 void Test() const; |
| 130 |
| 131 private: |
| 132 // Check, via EXPECT_* macros, that the the condition |condition_key_|=|value| |
| 133 // fails against |url_| iff |should_fail| is true. This check is expensive, |
| 134 // its value should be cached if needed multiple times. |
| 135 void CheckCondition(const std::string& value, bool should_fail) const; |
| 136 |
| 137 const char* condition_key_; |
| 138 const bool use_list_of_strings_; |
| 139 const std::string& expected_value_; |
| 140 const std::string& incorrect_case_value_; |
| 141 const bool case_sensitive_; |
| 142 const GURL& url_; |
| 143 |
| 144 // Allow implicit copy and assign, because a public copy constructor is |
| 145 // needed, but never used (!), for the definition of arrays of this class. |
| 146 }; |
| 147 |
| 148 void UrlConditionCaseTest::Test() const { |
| 149 CheckCondition(expected_value_, false); |
| 150 CheckCondition(incorrect_case_value_, case_sensitive_); |
| 151 } |
| 152 |
| 153 void UrlConditionCaseTest::CheckCondition(const std::string& value, |
| 154 bool should_fail) const { |
| 155 DictionaryValue condition; |
| 156 if (use_list_of_strings_) { |
| 157 ListValue* list = new ListValue(); |
| 158 list->Append(Value::CreateStringValue(value)); |
| 159 condition.SetWithoutPathExpansion(condition_key_, list); |
| 160 } else { |
| 161 condition.SetStringWithoutPathExpansion(condition_key_, value); |
| 162 } |
| 163 |
| 164 URLMatcher matcher; |
| 165 std::string error; |
| 166 scoped_refptr<URLMatcherConditionSet> result; |
| 167 |
| 168 result = URLMatcherFactory::CreateFromURLFilterDictionary( |
| 169 matcher.condition_factory(), &condition, 1, &error); |
| 170 EXPECT_EQ("", error); |
| 171 ASSERT_TRUE(result.get()); |
| 172 |
| 173 URLMatcherConditionSet::Vector conditions; |
| 174 conditions.push_back(result); |
| 175 matcher.AddConditionSets(conditions); |
| 176 EXPECT_EQ((should_fail ? 0u : 1u), matcher.MatchURL(url_).size()) |
| 177 << "while matching condition " << condition_key_ << " with value " |
| 178 << value << " against url " << url_; |
| 179 } |
| 180 |
| 181 // This tests that the UrlFilter handles case sensitivity on various parts of |
| 182 // URLs correctly. |
| 183 TEST(URLMatcherFactoryTest, CaseSensitivity) { |
| 184 const std::string kScheme("https"); |
| 185 const std::string kSchemeUpper("HTTPS"); |
| 186 const std::string kHost("www.example.com"); |
| 187 const std::string kHostUpper("WWW.EXAMPLE.COM"); |
| 188 const std::string kPath("/path"); |
| 189 const std::string kPathUpper("/PATH"); |
| 190 const std::string kQuery("?option=value&A=B"); |
| 191 const std::string kQueryUpper("?OPTION=VALUE&A=B"); |
| 192 const std::string kUrl(kScheme + "://" + kHost + ":1234" + kPath + kQuery); |
| 193 const std::string kUrlUpper( |
| 194 kSchemeUpper + "://" + kHostUpper + ":1234" + kPathUpper + kQueryUpper); |
| 195 const GURL url(kUrl); |
| 196 // Note: according to RFC 3986, and RFC 1034, schema and host, respectively |
| 197 // should be case insensitive. See crbug.com/160702, comments 6 and 7, for why |
| 198 // we still require them to be case sensitive in UrlFilter. |
| 199 const bool kIsSchemeCaseSensitive = true; |
| 200 const bool kIsHostCaseSensitive = true; |
| 201 const bool kIsPathCaseSensitive = true; |
| 202 const bool kIsQueryCaseSensitive = true; |
| 203 const bool kIsUrlCaseSensitive = kIsSchemeCaseSensitive || |
| 204 kIsHostCaseSensitive || kIsPathCaseSensitive || kIsQueryCaseSensitive; |
| 205 |
| 206 const UrlConditionCaseTest case_tests[] = { |
| 207 UrlConditionCaseTest(keys::kSchemesKey, true, kScheme, kSchemeUpper, |
| 208 kIsSchemeCaseSensitive, url), |
| 209 UrlConditionCaseTest(keys::kHostContainsKey, false, kHost, kHostUpper, |
| 210 kIsHostCaseSensitive, url), |
| 211 UrlConditionCaseTest(keys::kHostEqualsKey, false, kHost, kHostUpper, |
| 212 kIsHostCaseSensitive, url), |
| 213 UrlConditionCaseTest(keys::kHostPrefixKey, false, kHost, kHostUpper, |
| 214 kIsHostCaseSensitive, url), |
| 215 UrlConditionCaseTest(keys::kHostSuffixKey, false, kHost, kHostUpper, |
| 216 kIsHostCaseSensitive, url), |
| 217 UrlConditionCaseTest(keys::kPathContainsKey, false, kPath, kPathUpper, |
| 218 kIsPathCaseSensitive, url), |
| 219 UrlConditionCaseTest(keys::kPathEqualsKey, false, kPath, kPathUpper, |
| 220 kIsPathCaseSensitive, url), |
| 221 UrlConditionCaseTest(keys::kPathPrefixKey, false, kPath, kPathUpper, |
| 222 kIsPathCaseSensitive, url), |
| 223 UrlConditionCaseTest(keys::kPathSuffixKey, false, kPath, kPathUpper, |
| 224 kIsPathCaseSensitive, url), |
| 225 UrlConditionCaseTest(keys::kQueryContainsKey, false, kQuery, kQueryUpper, |
| 226 kIsQueryCaseSensitive, url), |
| 227 UrlConditionCaseTest(keys::kQueryEqualsKey, false, kQuery, kQueryUpper, |
| 228 kIsQueryCaseSensitive, url), |
| 229 UrlConditionCaseTest(keys::kQueryPrefixKey, false, kQuery, kQueryUpper, |
| 230 kIsQueryCaseSensitive, url), |
| 231 UrlConditionCaseTest(keys::kQuerySuffixKey, false, kQuery, kQueryUpper, |
| 232 kIsQueryCaseSensitive, url), |
| 233 // Excluding kURLMatchesKey because case sensitivity can be specified in the |
| 234 // RE2 expression. |
| 235 UrlConditionCaseTest(keys::kURLContainsKey, false, kUrl, kUrlUpper, |
| 236 kIsUrlCaseSensitive, url), |
| 237 UrlConditionCaseTest(keys::kURLEqualsKey, false, kUrl, kUrlUpper, |
| 238 kIsUrlCaseSensitive, url), |
| 239 UrlConditionCaseTest(keys::kURLPrefixKey, false, kUrl, kUrlUpper, |
| 240 kIsUrlCaseSensitive, url), |
| 241 UrlConditionCaseTest(keys::kURLSuffixKey, false, kUrl, kUrlUpper, |
| 242 kIsUrlCaseSensitive, url), |
| 243 }; |
| 244 |
| 245 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(case_tests); ++i) { |
| 246 SCOPED_TRACE(base::StringPrintf("Iteration: %" PRIuS, i)); |
| 247 case_tests[i].Test(); |
| 248 } |
| 249 } |
| 250 |
102 } // namespace extensions | 251 } // namespace extensions |
OLD | NEW |