Commit a49d62c7 authored by Robert Sesek's avatar Robert Sesek Committed by Commit Bot

Use the data_decoder service in TemplateURLParser.

This requires making the TemplateURLParser be asynchronous rather than
directly returning the result. That has a ripple effect of changing the
lifetimes of some of the parameters to Parse(), such as the
SearchTermsData.

The Firefox importer also uses the TemplateURLParser (although it may
be entirely broken, per https://crbug.com/868768). The importer assumes
that all operations are synchronous, so this adds an internal helper
class to manage the now-asynchronous state for TemplateURL parsing.

Bug: 699342
Change-Id: I311d9e29dbbca34a4f5696b251a0fbaaadcc506b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1879973
Commit-Queue: Robert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarIlya Sherman <isherman@chromium.org>
Reviewed-by: default avatarMartin Barbella <mbarbella@chromium.org>
Reviewed-by: default avatarNico Weber <thakis@chromium.org>
Reviewed-by: default avatarKevin Bailey <krb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712773}
parent 2aa1c80a
...@@ -5580,6 +5580,7 @@ static_library("test_support") { ...@@ -5580,6 +5580,7 @@ static_library("test_support") {
"//content/test:test_support", "//content/test:test_support",
"//google_apis:test_support", "//google_apis:test_support",
"//net:test_support", "//net:test_support",
"//services/data_decoder/public/cpp:test_support",
"//services/preferences/public/cpp/tracked:test_support", "//services/preferences/public/cpp/tracked:test_support",
"//skia", "//skia",
"//testing/gmock", "//testing/gmock",
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#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 "components/search_engines/template_url_prepopulate_data.h" #include "components/search_engines/template_url_prepopulate_data.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include <iterator> #include <iterator>
...@@ -92,53 +93,95 @@ std::unique_ptr<TemplateURL> CreateTemplateURL(const base::string16& url, ...@@ -92,53 +93,95 @@ std::unique_ptr<TemplateURL> CreateTemplateURL(const base::string16& url,
return std::make_unique<TemplateURL>(data); return std::make_unique<TemplateURL>(data);
} }
// Parses the OpenSearch XML files in |xml_files| and populates |search_engines| } // namespace
// with the resulting TemplateURLs.
void ParseSearchEnginesFromFirefoxXMLData(
const std::vector<std::string>& xml_data,
TemplateURLService::OwnedTemplateURLVector* search_engines) {
DCHECK(search_engines);
std::map<std::string, std::unique_ptr<TemplateURL>> search_engine_for_url; // When the Bridge receives the search engines XML data via
// The first XML file represents the default search engine in Firefox 3, so we // SetFirefoxSearchEnginesXMLData(), this class is responsible for managing the
// need to keep it on top of the list. // asynchronous TemplateURL parsing operations. The Bridge generally operates
auto default_turl = search_engine_for_url.end(); // synchronously, so this class manages the state and notifies the bridge when
for (auto xml_iter = xml_data.begin(); xml_iter != xml_data.end(); // parsing is done.
++xml_iter) { class InProcessImporterBridge::SearchEnginesParser {
std::unique_ptr<TemplateURL> template_url = TemplateURLParser::Parse( public:
UIThreadSearchTermsData(), xml_iter->data(), xml_iter->length(), // Starts parsing the |search_engines_xml_data| and will notify |bridge|
base::BindRepeating(&FirefoxURLParameterFilter)); // upon completion.
if (template_url) { SearchEnginesParser(const std::vector<std::string>& search_engines_xml_data,
auto iter = search_engine_for_url.find(template_url->url()); InProcessImporterBridge* bridge)
if (iter == search_engine_for_url.end()) { : bridge_(bridge), data_decoder_(new data_decoder::DataDecoder()) {
iter = search_engine_for_url DCHECK(!search_engines_xml_data.empty());
.insert(std::make_pair(template_url->url(), StartParse(search_engines_xml_data);
std::move(template_url))) }
.first;
} else { // Returns true if all the data have been parsed, false if the operation
// We have already found a search engine with the same URL. We give // is still ongoing.
// priority to the latest one found, as GetSearchEnginesXMLFiles() bool is_done() const { return is_done_; }
// returns a vector with first Firefox default search engines and then
// the user's ones. We want to give priority to the user ones. // If InProcessImporterBridge::NotifyEnded() is called before is_done()
iter->second = std::move(template_url); // returns true, NotifyEnded() sets this flag so that it can be called back
} // to complete the import.
if (default_turl == search_engine_for_url.end()) void set_notify_ended_on_completion() { notify_ended_on_completion_ = true; }
default_turl = iter;
private:
void StartParse(const std::vector<std::string>& search_engines_xml_data) {
const auto& last_item = search_engines_xml_data.end() - 1;
TemplateURLParser::ParameterFilter param_filter =
base::BindRepeating(&FirefoxURLParameterFilter);
for (auto it = search_engines_xml_data.begin();
it != search_engines_xml_data.end(); ++it) {
// Because all TemplateURLParser are handled by the same data_decoder_
// instance, the results will be returned FIFO.
// The SearchEnginesParser is owned by the InProcessImporterBridge,
// which is not deleted until NotifyEnded() is called, so using Unretained
// is safe.
TemplateURLParser::ParseWithDataDecoder(
data_decoder_.get(), &search_terms_data_, *it, param_filter,
base::BindOnce(&SearchEnginesParser::OnURLParsed,
base::Unretained(this), it == last_item));
} }
} }
// Put the results in the |search_engines| vector. void OnURLParsed(bool is_last_item, std::unique_ptr<TemplateURL> url) {
for (auto t_iter = search_engine_for_url.begin(); if (url)
t_iter != search_engine_for_url.end(); ++t_iter) { parsed_urls_.push_back(std::move(url));
if (t_iter == default_turl)
search_engines->insert(search_engines->begin(), if (is_last_item)
std::move(default_turl->second)); FinishParsing();
else
search_engines->push_back(std::move(t_iter->second));
} }
}
} // namespace void FinishParsing() {
is_done_ = true;
// Shut down the DataDecoder.
data_decoder_.reset();
bridge_->WriteSearchEngines(std::move(parsed_urls_));
if (notify_ended_on_completion_)
bridge_->NotifyEnded();
}
// Storage for the URLs. These are stored in the same order as the original
// |search_engines_xml_data|.
TemplateURLService::OwnedTemplateURLVector parsed_urls_;
InProcessImporterBridge* bridge_; // Weak, owns this.
// Set to true if the last search engine has been parsed.
bool is_done_ = false;
// Set to true if the ImporterBridge has been NotifyEnded() already but was
// waiting on this class to finish the import.
bool notify_ended_on_completion_ = false;
// Parameter for TemplateURLParser.
UIThreadSearchTermsData search_terms_data_;
// The DataDecoder instance that is shared amongst all the TemplateURLs being
// parsed.
std::unique_ptr<data_decoder::DataDecoder> data_decoder_;
DISALLOW_COPY_AND_ASSIGN(SearchEnginesParser);
};
InProcessImporterBridge::InProcessImporterBridge( InProcessImporterBridge::InProcessImporterBridge(
ProfileWriter* writer, ProfileWriter* writer,
...@@ -186,10 +229,10 @@ void InProcessImporterBridge::SetKeywords( ...@@ -186,10 +229,10 @@ void InProcessImporterBridge::SetKeywords(
void InProcessImporterBridge::SetFirefoxSearchEnginesXMLData( void InProcessImporterBridge::SetFirefoxSearchEnginesXMLData(
const std::vector<std::string>& search_engine_data) { const std::vector<std::string>& search_engine_data) {
TemplateURLService::OwnedTemplateURLVector search_engines; if (!search_engine_data.empty()) {
ParseSearchEnginesFromFirefoxXMLData(search_engine_data, &search_engines); // SearchEnginesParser will call back the Bridge back when it is done.
search_engines_.reset(new SearchEnginesParser(search_engine_data, this));
writer_->AddKeywords(std::move(search_engines), true); }
} }
void InProcessImporterBridge::SetPasswordForm( void InProcessImporterBridge::SetPasswordForm(
...@@ -228,6 +271,13 @@ void InProcessImporterBridge::NotifyItemEnded(importer::ImportItem item) { ...@@ -228,6 +271,13 @@ void InProcessImporterBridge::NotifyItemEnded(importer::ImportItem item) {
} }
void InProcessImporterBridge::NotifyEnded() { void InProcessImporterBridge::NotifyEnded() {
// If there are search engines to parse but parsing them is not yet complete,
// arrange to be called back when they are done.
if (search_engines_ && !search_engines_->is_done()) {
search_engines_->set_notify_ended_on_completion();
return;
}
host_->NotifyImportEnded(); host_->NotifyImportEnded();
} }
...@@ -236,3 +286,35 @@ base::string16 InProcessImporterBridge::GetLocalizedString(int message_id) { ...@@ -236,3 +286,35 @@ base::string16 InProcessImporterBridge::GetLocalizedString(int message_id) {
} }
InProcessImporterBridge::~InProcessImporterBridge() {} InProcessImporterBridge::~InProcessImporterBridge() {}
void InProcessImporterBridge::WriteSearchEngines(
TemplateURL::OwnedTemplateURLVector template_urls) {
std::map<std::string, std::unique_ptr<TemplateURL>> search_engine_for_url;
for (auto& template_url : template_urls) {
std::string key = template_url->url();
// Give priority to the latest template URL that is found, as
// GetSearchEnginesXMLFiles() returns a vector with first Firefox default
// search engines and then the user's ones. The user ones should take
// precedence.
search_engine_for_url[key] = std::move(template_url);
}
// The first URL represents the default search engine in Firefox 3, so we
// need to keep it on top of the list.
auto default_turl = search_engine_for_url.end();
if (!template_urls.empty())
default_turl = search_engine_for_url.find(template_urls[0]->url());
// Put the results in the |search_engines| vector.
TemplateURLService::OwnedTemplateURLVector search_engines;
for (auto it = search_engine_for_url.begin();
it != search_engine_for_url.end(); ++it) {
if (it == default_turl) {
search_engines.insert(search_engines.begin(),
std::move(default_turl->second));
} else {
search_engines.push_back(std::move(it->second));
}
}
writer_->AddKeywords(std::move(search_engines), true);
}
...@@ -60,10 +60,19 @@ class InProcessImporterBridge : public ImporterBridge { ...@@ -60,10 +60,19 @@ class InProcessImporterBridge : public ImporterBridge {
// End ImporterBridge implementation. // End ImporterBridge implementation.
private: private:
class SearchEnginesParser;
friend class SearchEnginesParser;
~InProcessImporterBridge() override; ~InProcessImporterBridge() override;
// Called by the SearchEnginesParser when all the search engines have been
// parsed. The |template_urls| vector is in the same sort order that was
// passed to SetFirefoxSearchEnginesXMLData().
void WriteSearchEngines(TemplateURL::OwnedTemplateURLVector template_urls);
ProfileWriter* const writer_; // weak ProfileWriter* const writer_; // weak
const base::WeakPtr<ExternalProcessImporterHost> host_; const base::WeakPtr<ExternalProcessImporterHost> host_;
std::unique_ptr<SearchEnginesParser> search_engines_;
DISALLOW_COPY_AND_ASSIGN(InProcessImporterBridge); DISALLOW_COPY_AND_ASSIGN(InProcessImporterBridge);
}; };
......
...@@ -10,9 +10,11 @@ ...@@ -10,9 +10,11 @@
#include "base/path_service.h" #include "base/path_service.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/test/task_environment.h"
#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_paths.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 "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16; using base::ASCIIToUTF16;
...@@ -39,15 +41,25 @@ class TemplateURLParserTest : public testing::Test { ...@@ -39,15 +41,25 @@ class TemplateURLParserTest : public testing::Test {
void ParseFile(const std::string& file_name, void ParseFile(const std::string& file_name,
const TemplateURLParser::ParameterFilter& filter); const TemplateURLParser::ParameterFilter& filter);
void ParseString(const std::string& data,
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_;
private: private:
void OnTemplateURLParsed(base::OnceClosure quit_closure,
std::unique_ptr<TemplateURL> template_url) {
template_url_ = std::move(template_url);
std::move(quit_closure).Run();
}
base::FilePath osdd_dir_; base::FilePath osdd_dir_;
base::test::TaskEnvironment task_environment_;
data_decoder::test::InProcessDataDecoder data_decoder_;
}; };
TemplateURLParserTest::TemplateURLParserTest() { TemplateURLParserTest::TemplateURLParserTest() {}
}
TemplateURLParserTest::~TemplateURLParserTest() { TemplateURLParserTest::~TemplateURLParserTest() {
} }
...@@ -66,8 +78,19 @@ void TemplateURLParserTest::ParseFile( ...@@ -66,8 +78,19 @@ void TemplateURLParserTest::ParseFile(
std::string contents; std::string contents;
ASSERT_TRUE(base::ReadFileToString(full_path, &contents)); ASSERT_TRUE(base::ReadFileToString(full_path, &contents));
template_url_ = TemplateURLParser::Parse(SearchTermsData(), contents.data(), ParseString(contents, filter);
contents.length(), filter); }
void TemplateURLParserTest::ParseString(
const std::string& data,
const TemplateURLParser::ParameterFilter& filter) {
base::RunLoop run_loop;
SearchTermsData search_terms_data;
TemplateURLParser::Parse(
&search_terms_data, data, filter,
base::BindOnce(&TemplateURLParserTest::OnTemplateURLParsed,
base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
} }
// Actual tests --------------------------------------------------------------- // Actual tests ---------------------------------------------------------------
...@@ -249,6 +272,5 @@ TEST_F(TemplateURLParserTest, InvalidInput) { ...@@ -249,6 +272,5 @@ TEST_F(TemplateURLParserTest, InvalidInput) {
</Url> </Url>
</OpenSearchDescription> </OpenSearchDescription>
)"; )";
TemplateURLParser::Parse(SearchTermsData(), char_data, base::size(char_data), ParseString(char_data, filter);
filter);
} }
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "components/search_engines/template_url.h" #include "components/search_engines/template_url.h"
#include "components/search_engines/template_url_data.h" #include "components/search_engines/template_url_data.h"
#include "components/search_engines/template_url_service_observer.h" #include "components/search_engines/template_url_service_observer.h"
#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
class KeywordWebDataService; class KeywordWebDataService;
class TemplateURLService; class TemplateURLService;
...@@ -83,6 +84,7 @@ class TemplateURLServiceTestUtil : public TemplateURLServiceObserver { ...@@ -83,6 +84,7 @@ class TemplateURLServiceTestUtil : public TemplateURLServiceObserver {
base::string16 search_term_; base::string16 search_term_;
scoped_refptr<KeywordWebDataService> web_data_service_; scoped_refptr<KeywordWebDataService> web_data_service_;
std::unique_ptr<TemplateURLService> model_; std::unique_ptr<TemplateURLService> model_;
data_decoder::test::InProcessDataDecoder data_decoder_;
DISALLOW_COPY_AND_ASSIGN(TemplateURLServiceTestUtil); DISALLOW_COPY_AND_ASSIGN(TemplateURLServiceTestUtil);
}; };
......
...@@ -48,6 +48,7 @@ static_library("utility") { ...@@ -48,6 +48,7 @@ static_library("utility") {
"//media", "//media",
"//net:net_with_v8", "//net:net_with_v8",
"//printing/buildflags", "//printing/buildflags",
"//services/data_decoder:lib",
"//services/network:network_service", "//services/network:network_service",
"//services/service_manager/public/cpp", "//services/service_manager/public/cpp",
"//skia", "//skia",
...@@ -100,7 +101,6 @@ static_library("utility") { ...@@ -100,7 +101,6 @@ static_library("utility") {
"//chrome/common:mojo_bindings", "//chrome/common:mojo_bindings",
"//chrome/common/importer:interfaces", "//chrome/common/importer:interfaces",
"//components/autofill/core/common", "//components/autofill/core/common",
"//services/data_decoder:lib",
"//services/proxy_resolver:lib", "//services/proxy_resolver:lib",
] ]
} }
......
...@@ -70,9 +70,9 @@ static_library("search_engines") { ...@@ -70,9 +70,9 @@ static_library("search_engines") {
"//components/variations", "//components/variations",
"//google_apis", "//google_apis",
"//net", "//net",
"//services/data_decoder/public/cpp",
"//services/network/public/cpp", "//services/network/public/cpp",
"//sql", "//sql",
"//third_party/libxml", # https://crbug.com/699342
"//third_party/metrics_proto", "//third_party/metrics_proto",
"//ui/base", "//ui/base",
"//ui/gfx", "//ui/gfx",
......
...@@ -15,8 +15,8 @@ include_rules = [ ...@@ -15,8 +15,8 @@ include_rules = [
"+components/variations", "+components/variations",
"+components/webdata", "+components/webdata",
"+google_apis", "+google_apis",
"+libxml",
"+net", "+net",
"+services/data_decoder/public",
"+services/network/public/cpp", "+services/network/public/cpp",
"+services/network/test", "+services/network/test",
"+sql", "+sql",
......
...@@ -80,6 +80,7 @@ class TemplateURLFetcher::RequestDelegate { ...@@ -80,6 +80,7 @@ class TemplateURLFetcher::RequestDelegate {
base::string16 keyword() const { return keyword_; } base::string16 keyword() const { return keyword_; }
private: private:
void OnTemplateURLParsed(std::unique_ptr<TemplateURL> template_url);
void OnLoaded(); void OnLoaded();
void AddSearchProvider(); void AddSearchProvider();
...@@ -140,6 +141,25 @@ TemplateURLFetcher::RequestDelegate::RequestDelegate( ...@@ -140,6 +141,25 @@ TemplateURLFetcher::RequestDelegate::RequestDelegate(
50000 /* max_body_size */); 50000 /* max_body_size */);
} }
void TemplateURLFetcher::RequestDelegate::OnTemplateURLParsed(
std::unique_ptr<TemplateURL> template_url) {
template_url_ = std::move(template_url);
if (!template_url_ ||
!template_url_->url_ref().SupportsReplacement(
fetcher_->template_url_service_->search_terms_data())) {
fetcher_->RequestCompleted(this);
// WARNING: RequestCompleted deletes us.
return;
}
// Wait for the model to be loaded before adding the provider.
if (!fetcher_->template_url_service_->loaded())
return;
AddSearchProvider();
// WARNING: AddSearchProvider deletes us.
}
void TemplateURLFetcher::RequestDelegate::OnLoaded() { void TemplateURLFetcher::RequestDelegate::OnLoaded() {
template_url_subscription_.reset(); template_url_subscription_.reset();
if (!template_url_) if (!template_url_)
...@@ -158,23 +178,11 @@ void TemplateURLFetcher::RequestDelegate::OnSimpleLoaderComplete( ...@@ -158,23 +178,11 @@ void TemplateURLFetcher::RequestDelegate::OnSimpleLoaderComplete(
return; return;
} }
template_url_ = TemplateURLParser::Parse( TemplateURLParser::Parse(
fetcher_->template_url_service_->search_terms_data(), &fetcher_->template_url_service_->search_terms_data(),
response_body->data(), response_body->length(), *response_body.get(), TemplateURLParser::ParameterFilter(),
TemplateURLParser::ParameterFilter()); base::BindOnce(&RequestDelegate::OnTemplateURLParsed,
if (!template_url_ || base::Unretained(this)));
!template_url_->url_ref().SupportsReplacement(
fetcher_->template_url_service_->search_terms_data())) {
fetcher_->RequestCompleted(this);
// WARNING: RequestCompleted deletes us.
return;
}
// Wait for the model to be loaded before adding the provider.
if (!fetcher_->template_url_service_->loaded())
return;
AddSearchProvider();
// WARNING: AddSearchProvider deletes us.
} }
void TemplateURLFetcher::RequestDelegate::AddSearchProvider() { void TemplateURLFetcher::RequestDelegate::AddSearchProvider() {
......
...@@ -16,6 +16,10 @@ ...@@ -16,6 +16,10 @@
class SearchTermsData; class SearchTermsData;
class TemplateURL; class TemplateURL;
namespace data_decoder {
class DataDecoder;
}
// TemplateURLParser, as the name implies, handling reading of TemplateURLs // TemplateURLParser, as the name implies, handling reading of TemplateURLs
// from OpenSearch description documents. // from OpenSearch description documents.
class TemplateURLParser { class TemplateURLParser {
...@@ -27,19 +31,30 @@ class TemplateURLParser { ...@@ -27,19 +31,30 @@ class TemplateURLParser {
using ParameterFilter = using ParameterFilter =
base::RepeatingCallback<bool(const std::string&, const std::string&)>; base::RepeatingCallback<bool(const std::string&, const std::string&)>;
using ParseCallback = base::OnceCallback<void(std::unique_ptr<TemplateURL>)>;
// 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 calls the |completion_callback| with the result. A null
// valid TemplateURL, the URLs referenced do not point to valid http/https // value is provided if the data does not describe a valid TemplateURL, the
// resources, or for some other reason we do not support the described // URLs referenced do not point to valid http/https resources, or for some
// TemplateURL. |parameter_filter| can be used if you want to filter some // other reason we do not support the described TemplateURL.
// parameters out of the URL. For example, when importing from another // |parameter_filter| can be used if you want to filter some parameters out
// browser, we remove any parameter identifying that browser. If set to null, // of the URL. For example, when importing from another browser, we remove
// the URL is not modified. // any parameter identifying that browser. If set to null, the URL is not
static std::unique_ptr<TemplateURL> Parse( // modified.
const SearchTermsData& search_terms_data, static void Parse(const SearchTermsData* search_terms_data,
const char* data, const std::string& data,
size_t length, const ParameterFilter& parameter_filter,
const ParameterFilter& parameter_filter); ParseCallback completion_callback);
// The same as Parse(), but it allows the caller to manage the lifetime of
// the DataDecoder service. The |data_decoder| must be kept alive until the
// |completion_callback| is called.
static void ParseWithDataDecoder(data_decoder::DataDecoder* data_decoder,
const SearchTermsData* search_terms_data,
const std::string& data,
const ParameterFilter& parameter_filter,
ParseCallback completion_callback);
private: private:
// No one should create one of these. // No one should create one of these.
......
...@@ -31,11 +31,13 @@ source_set("cpp") { ...@@ -31,11 +31,13 @@ source_set("cpp") {
public = [ public = [
"data_decoder.h", "data_decoder.h",
"json_sanitizer.h", "json_sanitizer.h",
"safe_xml_parser.h",
] ]
sources = [ sources = [
"data_decoder.cc", "data_decoder.cc",
"json_sanitizer.cc", "json_sanitizer.cc",
"safe_xml_parser.cc",
] ]
configs += [ "//build/config/compiler:wexit_time_destructors" ] configs += [ "//build/config/compiler:wexit_time_destructors" ]
...@@ -68,12 +70,10 @@ source_set("cpp") { ...@@ -68,12 +70,10 @@ source_set("cpp") {
public += [ public += [
"decode_image.h", "decode_image.h",
"safe_bundled_exchanges_parser.h", "safe_bundled_exchanges_parser.h",
"safe_xml_parser.h",
] ]
sources += [ sources += [
"decode_image.cc", "decode_image.cc",
"safe_bundled_exchanges_parser.cc", "safe_bundled_exchanges_parser.cc",
"safe_xml_parser.cc",
] ]
} }
......
...@@ -67,6 +67,8 @@ fuzzer_test("template_url_parser_fuzzer") { ...@@ -67,6 +67,8 @@ fuzzer_test("template_url_parser_fuzzer") {
"//base", "//base",
"//base:i18n", "//base:i18n",
"//components/search_engines:search_engines", "//components/search_engines:search_engines",
"//services/data_decoder/public/cpp",
"//services/data_decoder/public/cpp:test_support",
"//third_party/libxml:libxml", "//third_party/libxml:libxml",
] ]
dict = "//third_party/libxml/fuzz/xml.dict" dict = "//third_party/libxml/fuzz/xml.dict"
......
...@@ -14,9 +14,12 @@ ...@@ -14,9 +14,12 @@
#include "base/bind.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 "base/run_loop.h"
#include "base/task/single_thread_task_executor.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 "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#include "testing/libfuzzer/libfuzzer_exports.h" #include "testing/libfuzzer/libfuzzer_exports.h"
bool PseudoRandomFilter(std::mt19937* generator, bool PseudoRandomFilter(std::mt19937* generator,
...@@ -45,7 +48,11 @@ void ignore(void* ctx, const char* msg, ...) { ...@@ -45,7 +48,11 @@ void ignore(void* ctx, const char* msg, ...) {
class Env { class Env {
public: public:
Env() { xmlSetGenericErrorFunc(NULL, &ignore); } Env() { xmlSetGenericErrorFunc(nullptr, &ignore); }
private:
base::SingleThreadTaskExecutor executor_;
data_decoder::test::InProcessDataDecoder data_decoder_;
}; };
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
...@@ -63,11 +70,22 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { ...@@ -63,11 +70,22 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
// does not support 8 bit types on Windows. // does not support 8 bit types on Windows.
std::uniform_int_distribution<uint16_t> pool(0, 1); std::uniform_int_distribution<uint16_t> pool(0, 1);
base::RunLoop run_loop;
SearchTermsData search_terms_data;
std::string string_data(reinterpret_cast<const char*>(params + 1), size);
TemplateURLParser::ParameterFilter filter = TemplateURLParser::ParameterFilter filter =
base::BindRepeating(&PseudoRandomFilter, base::Unretained(&generator), base::BindRepeating(&PseudoRandomFilter, base::Unretained(&generator),
base::Unretained(&pool)); base::Unretained(&pool));
TemplateURLParser::Parse(&search_terms_data, string_data, filter,
base::BindOnce(
[](base::OnceClosure quit_closure,
std::unique_ptr<TemplateURL> ignored) {
std::move(quit_closure).Run();
},
run_loop.QuitClosure()));
run_loop.Run();
const char* char_data = reinterpret_cast<const char*>(params + 1);
TemplateURLParser::Parse(SearchTermsData(), char_data, size, filter);
return 0; return 0;
} }
...@@ -141,7 +141,6 @@ static_library("libxml") { ...@@ -141,7 +141,6 @@ static_library("libxml") {
":xml_reader", ":xml_reader",
":xml_writer", ":xml_writer",
":libxml_utils", ":libxml_utils",
"//components/search_engines",
"//testing/libfuzzer/*", "//testing/libfuzzer/*",
"//third_party/blink/renderer/*", "//third_party/blink/renderer/*",
"//third_party/fontconfig", "//third_party/fontconfig",
......
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