Commit 781c8289 authored by vabr@chromium.org's avatar vabr@chromium.org

Document and test case sensitivity in URL matcher attributes


BUG=160702


Review URL: https://chromiumcodereview.appspot.com/11776024

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@175762 0039d316-1c4b-4281-b951-d872f2087c98
parent 6dc54b22
......@@ -191,7 +191,7 @@
{
"id": "UrlFilter",
"type": "object",
"description": "Filters URLs for various criteria. See <a href='#filtered'>event filtering</a>.",
"description": "Filters URLs for various criteria. See <a href='#filtered'>event filtering</a>. All criteria are case sensitive.",
"nocompile": true,
"properties": {
"hostContains": {
......
......@@ -4,6 +4,8 @@
#include "chrome/common/extensions/matcher/url_matcher_factory.h"
#include "base/format_macros.h"
#include "base/stringprintf.h"
#include "base/values.h"
#include "chrome/common/extensions/matcher/url_matcher_constants.h"
#include "googleurl/src/gurl.h"
......@@ -99,4 +101,151 @@ TEST(URLMatcherFactoryTest, CreateFromURLFilterDictionary) {
EXPECT_EQ(0u, matcher.MatchURL(GURL("http://mail.example.com:81")).size());
}
// This class wraps a case sensitivity test for a single UrlFilter condition.
class UrlConditionCaseTest {
public:
// The condition is identified by the key |condition_key|. If that key is
// associated with string values, then |use_list_of_strings| should be false,
// if the key is associated with list-of-string values, then
// |use_list_of_strings| should be true. In |url| is the URL to test against.
UrlConditionCaseTest(const char* condition_key,
const bool use_list_of_strings,
const std::string& expected_value,
const std::string& incorrect_case_value,
const bool case_sensitive,
const GURL& url)
: condition_key_(condition_key),
use_list_of_strings_(use_list_of_strings),
expected_value_(expected_value),
incorrect_case_value_(incorrect_case_value),
case_sensitive_(case_sensitive),
url_(url) {}
~UrlConditionCaseTest() {}
// Match the condition against |url_|. Checks via EXPECT_* macros that
// |expected_value_| matches always, and that |incorrect_case_value_| matches
// iff |case_sensitive_| is false.
void Test() const;
private:
// Check, via EXPECT_* macros, that the the condition |condition_key_|=|value|
// fails against |url_| iff |should_fail| is true. This check is expensive,
// its value should be cached if needed multiple times.
void CheckCondition(const std::string& value, bool should_fail) const;
const char* condition_key_;
const bool use_list_of_strings_;
const std::string& expected_value_;
const std::string& incorrect_case_value_;
const bool case_sensitive_;
const GURL& url_;
// Allow implicit copy and assign, because a public copy constructor is
// needed, but never used (!), for the definition of arrays of this class.
};
void UrlConditionCaseTest::Test() const {
CheckCondition(expected_value_, false);
CheckCondition(incorrect_case_value_, case_sensitive_);
}
void UrlConditionCaseTest::CheckCondition(const std::string& value,
bool should_fail) const {
DictionaryValue condition;
if (use_list_of_strings_) {
ListValue* list = new ListValue();
list->Append(Value::CreateStringValue(value));
condition.SetWithoutPathExpansion(condition_key_, list);
} else {
condition.SetStringWithoutPathExpansion(condition_key_, value);
}
URLMatcher matcher;
std::string error;
scoped_refptr<URLMatcherConditionSet> result;
result = URLMatcherFactory::CreateFromURLFilterDictionary(
matcher.condition_factory(), &condition, 1, &error);
EXPECT_EQ("", error);
ASSERT_TRUE(result.get());
URLMatcherConditionSet::Vector conditions;
conditions.push_back(result);
matcher.AddConditionSets(conditions);
EXPECT_EQ((should_fail ? 0u : 1u), matcher.MatchURL(url_).size())
<< "while matching condition " << condition_key_ << " with value "
<< value << " against url " << url_;
}
// This tests that the UrlFilter handles case sensitivity on various parts of
// URLs correctly.
TEST(URLMatcherFactoryTest, CaseSensitivity) {
const std::string kScheme("https");
const std::string kSchemeUpper("HTTPS");
const std::string kHost("www.example.com");
const std::string kHostUpper("WWW.EXAMPLE.COM");
const std::string kPath("/path");
const std::string kPathUpper("/PATH");
const std::string kQuery("?option=value&A=B");
const std::string kQueryUpper("?OPTION=VALUE&A=B");
const std::string kUrl(kScheme + "://" + kHost + ":1234" + kPath + kQuery);
const std::string kUrlUpper(
kSchemeUpper + "://" + kHostUpper + ":1234" + kPathUpper + kQueryUpper);
const GURL url(kUrl);
// Note: according to RFC 3986, and RFC 1034, schema and host, respectively
// should be case insensitive. See crbug.com/160702, comments 6 and 7, for why
// we still require them to be case sensitive in UrlFilter.
const bool kIsSchemeCaseSensitive = true;
const bool kIsHostCaseSensitive = true;
const bool kIsPathCaseSensitive = true;
const bool kIsQueryCaseSensitive = true;
const bool kIsUrlCaseSensitive = kIsSchemeCaseSensitive ||
kIsHostCaseSensitive || kIsPathCaseSensitive || kIsQueryCaseSensitive;
const UrlConditionCaseTest case_tests[] = {
UrlConditionCaseTest(keys::kSchemesKey, true, kScheme, kSchemeUpper,
kIsSchemeCaseSensitive, url),
UrlConditionCaseTest(keys::kHostContainsKey, false, kHost, kHostUpper,
kIsHostCaseSensitive, url),
UrlConditionCaseTest(keys::kHostEqualsKey, false, kHost, kHostUpper,
kIsHostCaseSensitive, url),
UrlConditionCaseTest(keys::kHostPrefixKey, false, kHost, kHostUpper,
kIsHostCaseSensitive, url),
UrlConditionCaseTest(keys::kHostSuffixKey, false, kHost, kHostUpper,
kIsHostCaseSensitive, url),
UrlConditionCaseTest(keys::kPathContainsKey, false, kPath, kPathUpper,
kIsPathCaseSensitive, url),
UrlConditionCaseTest(keys::kPathEqualsKey, false, kPath, kPathUpper,
kIsPathCaseSensitive, url),
UrlConditionCaseTest(keys::kPathPrefixKey, false, kPath, kPathUpper,
kIsPathCaseSensitive, url),
UrlConditionCaseTest(keys::kPathSuffixKey, false, kPath, kPathUpper,
kIsPathCaseSensitive, url),
UrlConditionCaseTest(keys::kQueryContainsKey, false, kQuery, kQueryUpper,
kIsQueryCaseSensitive, url),
UrlConditionCaseTest(keys::kQueryEqualsKey, false, kQuery, kQueryUpper,
kIsQueryCaseSensitive, url),
UrlConditionCaseTest(keys::kQueryPrefixKey, false, kQuery, kQueryUpper,
kIsQueryCaseSensitive, url),
UrlConditionCaseTest(keys::kQuerySuffixKey, false, kQuery, kQueryUpper,
kIsQueryCaseSensitive, url),
// Excluding kURLMatchesKey because case sensitivity can be specified in the
// RE2 expression.
UrlConditionCaseTest(keys::kURLContainsKey, false, kUrl, kUrlUpper,
kIsUrlCaseSensitive, url),
UrlConditionCaseTest(keys::kURLEqualsKey, false, kUrl, kUrlUpper,
kIsUrlCaseSensitive, url),
UrlConditionCaseTest(keys::kURLPrefixKey, false, kUrl, kUrlUpper,
kIsUrlCaseSensitive, url),
UrlConditionCaseTest(keys::kURLSuffixKey, false, kUrl, kUrlUpper,
kIsUrlCaseSensitive, url),
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(case_tests); ++i) {
SCOPED_TRACE(base::StringPrintf("Iteration: %" PRIuS, i));
case_tests[i].Test();
}
}
} // namespace extensions
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment