Commit 11f9afd5 authored by Robert Sesek's avatar Robert Sesek Committed by Commit Bot

Convert TemplateURLParser's ParameterFilter to be a callback.

This removes a hurdle around object lifetimes for an upcoming change that
makes TemplateURLParser asynchronous.

Bug: 699342
Change-Id: I92d88f221d7c06f48d6f3e3a9e21f34514c70661
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1877188Reviewed-by: default avatarKevin Bailey <krb@chromium.org>
Reviewed-by: default avatarMax Moroz <mmoroz@chromium.org>
Reviewed-by: default avatarIlya Sherman <isherman@chromium.org>
Commit-Queue: Robert Sesek <rsesek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#709248}
parent 1d8cf4e9
...@@ -65,26 +65,16 @@ namespace { ...@@ -65,26 +65,16 @@ namespace {
// FirefoxURLParameterFilter is used to remove parameter mentioning Firefox from // FirefoxURLParameterFilter is used to remove parameter mentioning Firefox from
// the search URL when importing search engines. // the search URL when importing search engines.
class FirefoxURLParameterFilter : public TemplateURLParser::ParameterFilter { bool FirefoxURLParameterFilter(const std::string& key,
public: const std::string& value) {
FirefoxURLParameterFilter() {} std::string low_value = base::ToLowerASCII(value);
~FirefoxURLParameterFilter() override {} if (low_value.find("mozilla") != std::string::npos ||
low_value.find("firefox") != std::string::npos ||
// TemplateURLParser::ParameterFilter method. low_value.find("moz:") != std::string::npos) {
bool KeepParameter(const std::string& key, return false;
const std::string& value) override {
std::string low_value = base::ToLowerASCII(value);
if (low_value.find("mozilla") != std::string::npos ||
low_value.find("firefox") != std::string::npos ||
low_value.find("moz:") != std::string::npos) {
return false;
}
return true;
} }
return true;
private: }
DISALLOW_COPY_AND_ASSIGN(FirefoxURLParameterFilter);
};
// Attempts to create a TemplateURL from the provided data. |title| is optional. // Attempts to create a TemplateURL from the provided data. |title| is optional.
// If TemplateURL creation fails, returns null. // If TemplateURL creation fails, returns null.
...@@ -110,15 +100,14 @@ void ParseSearchEnginesFromFirefoxXMLData( ...@@ -110,15 +100,14 @@ void ParseSearchEnginesFromFirefoxXMLData(
DCHECK(search_engines); DCHECK(search_engines);
std::map<std::string, std::unique_ptr<TemplateURL>> search_engine_for_url; std::map<std::string, std::unique_ptr<TemplateURL>> search_engine_for_url;
FirefoxURLParameterFilter param_filter;
// The first XML file represents the default search engine in Firefox 3, so we // The first XML file represents the default search engine in Firefox 3, so we
// need to keep it on top of the list. // need to keep it on top of the list.
auto default_turl = search_engine_for_url.end(); auto default_turl = search_engine_for_url.end();
for (auto xml_iter = xml_data.begin(); xml_iter != xml_data.end(); for (auto xml_iter = xml_data.begin(); xml_iter != xml_data.end();
++xml_iter) { ++xml_iter) {
std::unique_ptr<TemplateURL> template_url = std::unique_ptr<TemplateURL> template_url = TemplateURLParser::Parse(
TemplateURLParser::Parse(UIThreadSearchTermsData(), xml_iter->data(), UIThreadSearchTermsData(), xml_iter->data(), xml_iter->length(),
xml_iter->length(), &param_filter); base::BindRepeating(&FirefoxURLParameterFilter));
if (template_url) { if (template_url) {
auto iter = search_engine_for_url.find(template_url->url()); auto iter = search_engine_for_url.find(template_url->url());
if (iter == search_engine_for_url.end()) { if (iter == search_engine_for_url.end()) {
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "components/search_engines/template_url_parser.h" #include "components/search_engines/template_url_parser.h"
#include "base/bind.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/path_service.h" #include "base/path_service.h"
...@@ -15,40 +17,16 @@ ...@@ -15,40 +17,16 @@
using base::ASCIIToUTF16; using base::ASCIIToUTF16;
// ParamFilterImpl ------------------------------------------------------------ // Filters any param which as an occurrence of |name_str| in its |key| or an
// occurrence of |value_str| in its |value|.
// Filters any param which as an occurrence of name_str_ in its name or an bool TestFilter(const std::string& name_str,
// occurrence of value_str_ in its value. const std::string& value_str,
class ParamFilterImpl : public TemplateURLParser::ParameterFilter { const std::string& key,
public: const std::string& value) {
ParamFilterImpl(const std::string& name_str, const std::string& value_str); return (name_str.empty() || key.find(name_str) == std::string::npos) &&
~ParamFilterImpl() override; (value_str.empty() || value.find(value_str) == std::string::npos);
bool KeepParameter(const std::string& key, const std::string& value) override;
private:
std::string name_str_;
std::string value_str_;
DISALLOW_COPY_AND_ASSIGN(ParamFilterImpl);
};
ParamFilterImpl::ParamFilterImpl(const std::string& name_str,
const std::string& value_str)
: name_str_(name_str), value_str_(value_str) {}
ParamFilterImpl::~ParamFilterImpl() {
}
bool ParamFilterImpl::KeepParameter(const std::string& key,
const std::string& value) {
return (name_str_.empty() || key.find(name_str_) == std::string::npos) &&
(value_str_.empty() || value.find(value_str_) == std::string::npos);
} }
// TemplateURLParserTest ------------------------------------------------------
class TemplateURLParserTest : public testing::Test { class TemplateURLParserTest : public testing::Test {
protected: protected:
TemplateURLParserTest(); TemplateURLParserTest();
...@@ -59,7 +37,7 @@ class TemplateURLParserTest : public testing::Test { ...@@ -59,7 +37,7 @@ class TemplateURLParserTest : public testing::Test {
// Parses the OpenSearch description document at file_name (relative to the // Parses the OpenSearch description document at file_name (relative to the
// data dir). The TemplateURL is placed in |template_url_|. // data dir). The TemplateURL is placed in |template_url_|.
void ParseFile(const std::string& file_name, void ParseFile(const std::string& file_name,
TemplateURLParser::ParameterFilter* filter); const TemplateURLParser::ParameterFilter& filter);
// ParseFile parses the results into this template_url. // ParseFile parses the results into this template_url.
std::unique_ptr<TemplateURL> template_url_; std::unique_ptr<TemplateURL> template_url_;
...@@ -82,7 +60,7 @@ void TemplateURLParserTest::SetUp() { ...@@ -82,7 +60,7 @@ void TemplateURLParserTest::SetUp() {
void TemplateURLParserTest::ParseFile( void TemplateURLParserTest::ParseFile(
const std::string& file_name, const std::string& file_name,
TemplateURLParser::ParameterFilter* filter) { const TemplateURLParser::ParameterFilter& filter) {
base::FilePath full_path = osdd_dir_.AppendASCII(file_name); base::FilePath full_path = osdd_dir_.AppendASCII(file_name);
ASSERT_TRUE(base::PathExists(full_path)); ASSERT_TRUE(base::PathExists(full_path));
...@@ -95,22 +73,26 @@ void TemplateURLParserTest::ParseFile( ...@@ -95,22 +73,26 @@ void TemplateURLParserTest::ParseFile(
// Actual tests --------------------------------------------------------------- // Actual tests ---------------------------------------------------------------
TEST_F(TemplateURLParserTest, FailOnBogusURL) { TEST_F(TemplateURLParserTest, FailOnBogusURL) {
ASSERT_NO_FATAL_FAILURE(ParseFile("bogus.xml", nullptr)); ASSERT_NO_FATAL_FAILURE(
ParseFile("bogus.xml", TemplateURLParser::ParameterFilter()));
EXPECT_FALSE(template_url_); EXPECT_FALSE(template_url_);
} }
TEST_F(TemplateURLParserTest, PassOnHTTPS) { TEST_F(TemplateURLParserTest, PassOnHTTPS) {
ASSERT_NO_FATAL_FAILURE(ParseFile("https.xml", nullptr)); ASSERT_NO_FATAL_FAILURE(
ParseFile("https.xml", TemplateURLParser::ParameterFilter()));
EXPECT_TRUE(template_url_); EXPECT_TRUE(template_url_);
} }
TEST_F(TemplateURLParserTest, FailOnPost) { TEST_F(TemplateURLParserTest, FailOnPost) {
ASSERT_NO_FATAL_FAILURE(ParseFile("post.xml", nullptr)); ASSERT_NO_FATAL_FAILURE(
ParseFile("post.xml", TemplateURLParser::ParameterFilter()));
EXPECT_FALSE(template_url_); EXPECT_FALSE(template_url_);
} }
TEST_F(TemplateURLParserTest, TestDictionary) { TEST_F(TemplateURLParserTest, TestDictionary) {
ASSERT_NO_FATAL_FAILURE(ParseFile("dictionary.xml", nullptr)); ASSERT_NO_FATAL_FAILURE(
ParseFile("dictionary.xml", TemplateURLParser::ParameterFilter()));
ASSERT_TRUE(template_url_); ASSERT_TRUE(template_url_);
EXPECT_EQ(ASCIIToUTF16("Dictionary.com"), template_url_->short_name()); EXPECT_EQ(ASCIIToUTF16("Dictionary.com"), template_url_->short_name());
EXPECT_EQ(GURL("http://cache.lexico.com/g/d/favicon.ico"), EXPECT_EQ(GURL("http://cache.lexico.com/g/d/favicon.ico"),
...@@ -121,7 +103,8 @@ TEST_F(TemplateURLParserTest, TestDictionary) { ...@@ -121,7 +103,8 @@ TEST_F(TemplateURLParserTest, TestDictionary) {
} }
TEST_F(TemplateURLParserTest, TestMSDN) { TEST_F(TemplateURLParserTest, TestMSDN) {
ASSERT_NO_FATAL_FAILURE(ParseFile("msdn.xml", nullptr)); ASSERT_NO_FATAL_FAILURE(
ParseFile("msdn.xml", TemplateURLParser::ParameterFilter()));
ASSERT_TRUE(template_url_); ASSERT_TRUE(template_url_);
EXPECT_EQ(ASCIIToUTF16("Search \" MSDN"), template_url_->short_name()); EXPECT_EQ(ASCIIToUTF16("Search \" MSDN"), template_url_->short_name());
EXPECT_EQ(GURL("http://search.msdn.microsoft.com/search/favicon.ico"), EXPECT_EQ(GURL("http://search.msdn.microsoft.com/search/favicon.ico"),
...@@ -133,7 +116,8 @@ TEST_F(TemplateURLParserTest, TestMSDN) { ...@@ -133,7 +116,8 @@ TEST_F(TemplateURLParserTest, TestMSDN) {
} }
TEST_F(TemplateURLParserTest, TestWikipedia) { TEST_F(TemplateURLParserTest, TestWikipedia) {
ASSERT_NO_FATAL_FAILURE(ParseFile("wikipedia.xml", nullptr)); ASSERT_NO_FATAL_FAILURE(
ParseFile("wikipedia.xml", TemplateURLParser::ParameterFilter()));
ASSERT_TRUE(template_url_); ASSERT_TRUE(template_url_);
EXPECT_EQ(ASCIIToUTF16("Wikipedia (English)"), template_url_->short_name()); EXPECT_EQ(ASCIIToUTF16("Wikipedia (English)"), template_url_->short_name());
EXPECT_EQ(GURL("http://en.wikipedia.org/favicon.ico"), EXPECT_EQ(GURL("http://en.wikipedia.org/favicon.ico"),
...@@ -153,14 +137,16 @@ TEST_F(TemplateURLParserTest, TestWikipedia) { ...@@ -153,14 +137,16 @@ TEST_F(TemplateURLParserTest, TestWikipedia) {
} }
TEST_F(TemplateURLParserTest, NoCrashOnEmptyAttributes) { TEST_F(TemplateURLParserTest, NoCrashOnEmptyAttributes) {
ASSERT_NO_FATAL_FAILURE(ParseFile("url_with_no_attributes.xml", nullptr)); ASSERT_NO_FATAL_FAILURE(ParseFile("url_with_no_attributes.xml",
TemplateURLParser::ParameterFilter()));
} }
TEST_F(TemplateURLParserTest, TestFirefoxEbay) { TEST_F(TemplateURLParserTest, TestFirefoxEbay) {
// This file uses the Parameter extension // This file uses the Parameter extension
// (see http://www.opensearch.org/Specifications/OpenSearch/Extensions/Parameter/1.0) // (see http://www.opensearch.org/Specifications/OpenSearch/Extensions/Parameter/1.0)
ParamFilterImpl filter("ebay", "ebay"); TemplateURLParser::ParameterFilter filter =
ASSERT_NO_FATAL_FAILURE(ParseFile("firefox_ebay.xml", &filter)); base::BindRepeating(&TestFilter, "ebay", "ebay");
ASSERT_NO_FATAL_FAILURE(ParseFile("firefox_ebay.xml", filter));
ASSERT_TRUE(template_url_); ASSERT_TRUE(template_url_);
EXPECT_EQ(ASCIIToUTF16("eBay"), template_url_->short_name()); EXPECT_EQ(ASCIIToUTF16("eBay"), template_url_->short_name());
EXPECT_TRUE(template_url_->url_ref().SupportsReplacement(SearchTermsData())); EXPECT_TRUE(template_url_->url_ref().SupportsReplacement(SearchTermsData()));
...@@ -176,8 +162,9 @@ TEST_F(TemplateURLParserTest, TestFirefoxEbay) { ...@@ -176,8 +162,9 @@ TEST_F(TemplateURLParserTest, TestFirefoxEbay) {
TEST_F(TemplateURLParserTest, TestFirefoxWebster) { TEST_F(TemplateURLParserTest, TestFirefoxWebster) {
// This XML file uses a namespace. // This XML file uses a namespace.
ParamFilterImpl filter(std::string(), "Mozilla"); TemplateURLParser::ParameterFilter filter =
ASSERT_NO_FATAL_FAILURE(ParseFile("firefox_webster.xml", &filter)); base::BindRepeating(&TestFilter, std::string(), "Mozilla");
ASSERT_NO_FATAL_FAILURE(ParseFile("firefox_webster.xml", filter));
ASSERT_TRUE(template_url_); ASSERT_TRUE(template_url_);
EXPECT_EQ(ASCIIToUTF16("Webster"), template_url_->short_name()); EXPECT_EQ(ASCIIToUTF16("Webster"), template_url_->short_name());
EXPECT_TRUE(template_url_->url_ref().SupportsReplacement(SearchTermsData())); EXPECT_TRUE(template_url_->url_ref().SupportsReplacement(SearchTermsData()));
...@@ -191,8 +178,9 @@ TEST_F(TemplateURLParserTest, TestFirefoxWebster) { ...@@ -191,8 +178,9 @@ TEST_F(TemplateURLParserTest, TestFirefoxWebster) {
TEST_F(TemplateURLParserTest, TestFirefoxYahoo) { TEST_F(TemplateURLParserTest, TestFirefoxYahoo) {
// This XML file uses a namespace. // This XML file uses a namespace.
ParamFilterImpl filter(std::string(), "Mozilla"); TemplateURLParser::ParameterFilter filter =
ASSERT_NO_FATAL_FAILURE(ParseFile("firefox_yahoo.xml", &filter)); base::BindRepeating(&TestFilter, std::string(), "Mozilla");
ASSERT_NO_FATAL_FAILURE(ParseFile("firefox_yahoo.xml", filter));
ASSERT_TRUE(template_url_); ASSERT_TRUE(template_url_);
EXPECT_EQ(ASCIIToUTF16("Yahoo"), template_url_->short_name()); EXPECT_EQ(ASCIIToUTF16("Yahoo"), template_url_->short_name());
EXPECT_TRUE(template_url_->url_ref().SupportsReplacement(SearchTermsData())); EXPECT_TRUE(template_url_->url_ref().SupportsReplacement(SearchTermsData()));
...@@ -211,8 +199,9 @@ TEST_F(TemplateURLParserTest, TestFirefoxYahoo) { ...@@ -211,8 +199,9 @@ TEST_F(TemplateURLParserTest, TestFirefoxYahoo) {
// firefox_yahoo.xml, the suggestion method was just changed to POST). // firefox_yahoo.xml, the suggestion method was just changed to POST).
TEST_F(TemplateURLParserTest, TestPostSuggestion) { TEST_F(TemplateURLParserTest, TestPostSuggestion) {
// This XML file uses a namespace. // This XML file uses a namespace.
ParamFilterImpl filter(std::string(), "Mozilla"); TemplateURLParser::ParameterFilter filter =
ASSERT_NO_FATAL_FAILURE(ParseFile("post_suggestion.xml", &filter)); base::BindRepeating(&TestFilter, std::string(), "Mozilla");
ASSERT_NO_FATAL_FAILURE(ParseFile("post_suggestion.xml", filter));
ASSERT_TRUE(template_url_); ASSERT_TRUE(template_url_);
EXPECT_EQ(ASCIIToUTF16("Yahoo"), template_url_->short_name()); EXPECT_EQ(ASCIIToUTF16("Yahoo"), template_url_->short_name());
EXPECT_TRUE(template_url_->url_ref().SupportsReplacement(SearchTermsData())); EXPECT_TRUE(template_url_->url_ref().SupportsReplacement(SearchTermsData()));
...@@ -227,7 +216,8 @@ TEST_F(TemplateURLParserTest, TestPostSuggestion) { ...@@ -227,7 +216,8 @@ TEST_F(TemplateURLParserTest, TestPostSuggestion) {
// <Alias> tags are parsed and used as keyword for the template URL. // <Alias> tags are parsed and used as keyword for the template URL.
TEST_F(TemplateURLParserTest, TestKeyword) { TEST_F(TemplateURLParserTest, TestKeyword) {
ASSERT_NO_FATAL_FAILURE(ParseFile("keyword.xml", nullptr)); ASSERT_NO_FATAL_FAILURE(
ParseFile("keyword.xml", TemplateURLParser::ParameterFilter()));
ASSERT_TRUE(template_url_); ASSERT_TRUE(template_url_);
EXPECT_EQ(ASCIIToUTF16("Example"), template_url_->short_name()); EXPECT_EQ(ASCIIToUTF16("Example"), template_url_->short_name());
EXPECT_EQ("https://www.example.com/search?q={searchTerms}", EXPECT_EQ("https://www.example.com/search?q={searchTerms}",
...@@ -238,7 +228,8 @@ TEST_F(TemplateURLParserTest, TestKeyword) { ...@@ -238,7 +228,8 @@ TEST_F(TemplateURLParserTest, TestKeyword) {
// Empty <Alias> tags are ignored and the default keyword is used instead // Empty <Alias> tags are ignored and the default keyword is used instead
// (because empty keywords are not allowed). // (because empty keywords are not allowed).
TEST_F(TemplateURLParserTest, TestEmptyKeyword) { TEST_F(TemplateURLParserTest, TestEmptyKeyword) {
ASSERT_NO_FATAL_FAILURE(ParseFile("empty_keyword.xml", nullptr)); ASSERT_NO_FATAL_FAILURE(
ParseFile("empty_keyword.xml", TemplateURLParser::ParameterFilter()));
ASSERT_TRUE(template_url_); ASSERT_TRUE(template_url_);
EXPECT_EQ(ASCIIToUTF16("Example"), template_url_->short_name()); EXPECT_EQ(ASCIIToUTF16("Example"), template_url_->short_name());
EXPECT_EQ("https://www.example.com/search?q={searchTerms}", EXPECT_EQ("https://www.example.com/search?q={searchTerms}",
...@@ -249,12 +240,8 @@ TEST_F(TemplateURLParserTest, TestEmptyKeyword) { ...@@ -249,12 +240,8 @@ TEST_F(TemplateURLParserTest, TestEmptyKeyword) {
// An invalid template URL should not crash the parser. // An invalid template URL should not crash the parser.
// crbug.com/770734 // crbug.com/770734
TEST_F(TemplateURLParserTest, InvalidInput) { TEST_F(TemplateURLParserTest, InvalidInput) {
struct DumbFilter : TemplateURLParser::ParameterFilter { TemplateURLParser::ParameterFilter filter = base::BindRepeating(
bool KeepParameter(const std::string& key, [](const std::string&, const std::string&) -> bool { return true; });
const std::string& value) override {
return true;
}
} filter;
constexpr char char_data[] = R"( constexpr char char_data[] = R"(
<OpenSearchDescription> <OpenSearchDescription>
<Url template=")R:RRR?>RRR0" type="application/x-suggestions+json"> <Url template=")R:RRR?>RRR0" type="application/x-suggestions+json">
...@@ -263,5 +250,5 @@ TEST_F(TemplateURLParserTest, InvalidInput) { ...@@ -263,5 +250,5 @@ TEST_F(TemplateURLParserTest, InvalidInput) {
</OpenSearchDescription> </OpenSearchDescription>
)"; )";
TemplateURLParser::Parse(SearchTermsData(), char_data, base::size(char_data), TemplateURLParser::Parse(SearchTermsData(), char_data, base::size(char_data),
&filter); filter);
} }
...@@ -160,7 +160,8 @@ void TemplateURLFetcher::RequestDelegate::OnSimpleLoaderComplete( ...@@ -160,7 +160,8 @@ void TemplateURLFetcher::RequestDelegate::OnSimpleLoaderComplete(
template_url_ = TemplateURLParser::Parse( template_url_ = TemplateURLParser::Parse(
fetcher_->template_url_service_->search_terms_data(), fetcher_->template_url_service_->search_terms_data(),
response_body->data(), response_body->length(), nullptr); response_body->data(), response_body->length(),
TemplateURLParser::ParameterFilter());
if (!template_url_ || if (!template_url_ ||
!template_url_->url_ref().SupportsReplacement( !template_url_->url_ref().SupportsReplacement(
fetcher_->template_url_service_->search_terms_data())) { fetcher_->template_url_service_->search_terms_data())) {
......
...@@ -132,7 +132,7 @@ class TemplateURLParsingContext { ...@@ -132,7 +132,7 @@ class TemplateURLParsingContext {
typedef std::pair<std::string, std::string> Param; typedef std::pair<std::string, std::string> Param;
explicit TemplateURLParsingContext( explicit TemplateURLParsingContext(
TemplateURLParser::ParameterFilter* parameter_filter); const TemplateURLParser::ParameterFilter& parameter_filter);
static void StartElementImpl(void* ctx, static void StartElementImpl(void* ctx,
const xmlChar* name, const xmlChar* name,
...@@ -173,7 +173,7 @@ class TemplateURLParsingContext { ...@@ -173,7 +173,7 @@ class TemplateURLParsingContext {
// Character content for the current element. // Character content for the current element.
base::string16 string_; base::string16 string_;
TemplateURLParser::ParameterFilter* parameter_filter_; const TemplateURLParser::ParameterFilter& parameter_filter_;
// The list of parameters parsed in the Param nodes of a Url node. // The list of parameters parsed in the Param nodes of a Url node.
std::vector<Param> extra_params_; std::vector<Param> extra_params_;
...@@ -202,7 +202,7 @@ TemplateURLParsingContext::ElementNameToElementTypeMap* ...@@ -202,7 +202,7 @@ TemplateURLParsingContext::ElementNameToElementTypeMap*
TemplateURLParsingContext::kElementNameToElementTypeMap = nullptr; TemplateURLParsingContext::kElementNameToElementTypeMap = nullptr;
TemplateURLParsingContext::TemplateURLParsingContext( TemplateURLParsingContext::TemplateURLParsingContext(
TemplateURLParser::ParameterFilter* parameter_filter) const TemplateURLParser::ParameterFilter& parameter_filter)
: image_is_valid_for_favicon_(false), : image_is_valid_for_favicon_(false),
parameter_filter_(parameter_filter), parameter_filter_(parameter_filter),
method_(GET), method_(GET),
...@@ -428,12 +428,12 @@ void TemplateURLParsingContext::ParseParam(const xmlChar** atts) { ...@@ -428,12 +428,12 @@ void TemplateURLParsingContext::ParseParam(const xmlChar** atts) {
} }
if (!key.empty() && if (!key.empty() &&
(!parameter_filter_ || parameter_filter_->KeepParameter(key, value))) (parameter_filter_.is_null() || parameter_filter_.Run(key, value)))
extra_params_.push_back(Param(key, value)); extra_params_.push_back(Param(key, value));
} }
void TemplateURLParsingContext::ProcessURLParams() { void TemplateURLParsingContext::ProcessURLParams() {
if (!parameter_filter_ && extra_params_.empty()) if (parameter_filter_.is_null() && extra_params_.empty())
return; return;
GURL url(is_suggest_url_ ? data_.suggestions_url : data_.url()); GURL url(is_suggest_url_ ? data_.suggestions_url : data_.url());
...@@ -444,14 +444,14 @@ void TemplateURLParsingContext::ProcessURLParams() { ...@@ -444,14 +444,14 @@ void TemplateURLParsingContext::ProcessURLParams() {
// unwanted parameter. // unwanted parameter.
std::string new_query; std::string new_query;
bool modified = false; bool modified = false;
if (parameter_filter_) { if (!parameter_filter_.is_null()) {
url::Component query = url.parsed_for_possibly_invalid_spec().query; url::Component query = url.parsed_for_possibly_invalid_spec().query;
url::Component key, value; url::Component key, value;
const char* url_spec = url.spec().c_str(); const char* url_spec = url.spec().c_str();
while (url::ExtractQueryKeyValue(url_spec, &query, &key, &value)) { while (url::ExtractQueryKeyValue(url_spec, &query, &key, &value)) {
std::string key_str(url_spec, key.begin, key.len); std::string key_str(url_spec, key.begin, key.len);
std::string value_str(url_spec, value.begin, value.len); std::string value_str(url_spec, value.begin, value.len);
if (parameter_filter_->KeepParameter(key_str, value_str)) { if (parameter_filter_.Run(key_str, value_str)) {
AppendParamToQuery(key_str, value_str, &new_query); AppendParamToQuery(key_str, value_str, &new_query);
} else { } else {
modified = true; modified = true;
...@@ -497,7 +497,7 @@ std::unique_ptr<TemplateURL> TemplateURLParser::Parse( ...@@ -497,7 +497,7 @@ std::unique_ptr<TemplateURL> TemplateURLParser::Parse(
const SearchTermsData& search_terms_data, const SearchTermsData& search_terms_data,
const char* data, const char* data,
size_t length, size_t length,
TemplateURLParser::ParameterFilter* param_filter) { const TemplateURLParser::ParameterFilter& param_filter) {
// xmlSubstituteEntitiesDefault(1) makes it so that &amp; isn't mapped to // xmlSubstituteEntitiesDefault(1) makes it so that &amp; isn't mapped to
// &#38; . Unfortunately xmlSubstituteEntitiesDefault affects global state. // &#38; . Unfortunately xmlSubstituteEntitiesDefault affects global state.
// If this becomes problematic we'll need to provide our own entity // If this becomes problematic we'll need to provide our own entity
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "base/callback.h"
#include "base/macros.h" #include "base/macros.h"
class SearchTermsData; class SearchTermsData;
...@@ -19,16 +20,12 @@ class TemplateURL; ...@@ -19,16 +20,12 @@ class TemplateURL;
// from OpenSearch description documents. // from OpenSearch description documents.
class TemplateURLParser { class TemplateURLParser {
public: public:
class ParameterFilter { // A ParameterFilter is called for every URL paramter encountered during
public: // Parse(). It passes the parameter key as the first argument and the value
// Invoked for each parameter of the template URL while parsing. If this // as the second. The callback should return true if the parameter should be
// methods returns false, the parameter is not included. // kept, and false if it should be discarded.
virtual bool KeepParameter(const std::string& key, using ParameterFilter =
const std::string& value) = 0; base::RepeatingCallback<bool(const std::string&, const std::string&)>;
protected:
virtual ~ParameterFilter() {}
};
// Decodes the chunk of data representing a TemplateURL, creates the // Decodes the chunk of data representing a TemplateURL, creates the
// TemplateURL, and returns it. Returns null if the data does not describe a // TemplateURL, and returns it. Returns null if the data does not describe a
...@@ -42,7 +39,7 @@ class TemplateURLParser { ...@@ -42,7 +39,7 @@ class TemplateURLParser {
const SearchTermsData& search_terms_data, const SearchTermsData& search_terms_data,
const char* data, const char* data,
size_t length, size_t length,
ParameterFilter* parameter_filter); const ParameterFilter& parameter_filter);
private: private:
// No one should create one of these. // No one should create one of these.
......
...@@ -11,28 +11,21 @@ ...@@ -11,28 +11,21 @@
#include "libxml/parser.h" #include "libxml/parser.h"
#include "base/at_exit.h" #include "base/at_exit.h"
#include "base/bind.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/i18n/icu_util.h" #include "base/i18n/icu_util.h"
#include "components/search_engines/search_terms_data.h" #include "components/search_engines/search_terms_data.h"
#include "components/search_engines/template_url.h" #include "components/search_engines/template_url.h"
#include "components/search_engines/template_url_parser.h" #include "components/search_engines/template_url_parser.h"
#include "testing/libfuzzer/libfuzzer_exports.h"
class PseudoRandomFilter : public TemplateURLParser::ParameterFilter { bool PseudoRandomFilter(std::mt19937* generator,
public: std::uniform_int_distribution<uint16_t>* pool,
explicit PseudoRandomFilter(uint32_t seed) : generator_(seed), pool_(0, 1) {} const std::string&,
~PseudoRandomFilter() override = default; const std::string&) {
// Return true 254/255 times, ie: as if pool only returned uint8_t.
bool KeepParameter(const std::string&, const std::string&) override { return (*pool)(*generator) % (UINT8_MAX + 1);
// Return true 254/255 times, ie: as if pool_ only returned uint8_t. }
return pool_(generator_) % (UINT8_MAX + 1);
}
private:
std::mt19937 generator_;
// Use a uint16_t here instead of uint8_t because uniform_int_distribution
// does not support 8 bit types on Windows.
std::uniform_int_distribution<uint16_t> pool_;
};
struct FuzzerFixedParams { struct FuzzerFixedParams {
uint32_t seed_; uint32_t seed_;
...@@ -60,11 +53,21 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { ...@@ -60,11 +53,21 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size < sizeof(FuzzerFixedParams)) { if (size < sizeof(FuzzerFixedParams)) {
return 0; return 0;
} }
const FuzzerFixedParams* params = const FuzzerFixedParams* params =
reinterpret_cast<const FuzzerFixedParams*>(data); reinterpret_cast<const FuzzerFixedParams*>(data);
size -= sizeof(FuzzerFixedParams); size -= sizeof(FuzzerFixedParams);
std::mt19937 generator(params->seed_);
// Use a uint16_t here instead of uint8_t because uniform_int_distribution
// does not support 8 bit types on Windows.
std::uniform_int_distribution<uint16_t> pool(0, 1);
TemplateURLParser::ParameterFilter filter =
base::BindRepeating(&PseudoRandomFilter, base::Unretained(&generator),
base::Unretained(&pool));
const char* char_data = reinterpret_cast<const char*>(params + 1); const char* char_data = reinterpret_cast<const char*>(params + 1);
PseudoRandomFilter filter(params->seed_); TemplateURLParser::Parse(SearchTermsData(), char_data, size, filter);
TemplateURLParser::Parse(SearchTermsData(), char_data, size, &filter);
return 0; return 0;
} }
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