blob: 18ff0f79bd67cdbad97b131dfc93352497fc763f [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/callback_helpers.h"
#include "base/files/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/search_engines/template_url_service_test_util.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/testing_profile.h"
#include "components/search_engines/template_url.h"
#include "components/search_engines/template_url_fetcher.h"
#include "components/search_engines/template_url_service.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using base::ASCIIToUTF16;
// Basic set-up for TemplateURLFetcher tests.
class TemplateURLFetcherTest : public testing::Test {
public:
TemplateURLFetcherTest();
void SetUp() override {
TestingProfile* profile = test_util_.profile();
ASSERT_TRUE(profile->GetRequestContext());
template_url_fetcher_.reset(new TemplateURLFetcher(
test_util_.model(), profile->GetRequestContext()));
ASSERT_TRUE(test_server_.InitializeAndWaitUntilReady());
}
void TearDown() override {
ASSERT_TRUE(test_server_.ShutdownAndWaitUntilComplete());
}
// Called when the callback is destroyed.
void DestroyedCallback();
// TemplateURLFetcherCallbacks implementation. (Although not derived from
// this class, this method handles those calls for the test.)
void ConfirmAddSearchProvider(
base::ScopedClosureRunner* callback_destruction_notifier,
scoped_ptr<TemplateURL> template_url);
// Schedules the download of the url.
void StartDownload(const base::string16& keyword,
const std::string& osdd_file_name,
TemplateURLFetcher::ProviderType provider_type,
bool check_that_file_exists);
// Waits for any downloads to finish.
void WaitForDownloadToFinish();
TemplateURLServiceTestUtil* test_util() { return &test_util_; }
TemplateURLFetcher* template_url_fetcher() {
return template_url_fetcher_.get();
}
const TemplateURL* last_callback_template_url() const {
return last_callback_template_url_.get();
}
int callbacks_destroyed() const { return callbacks_destroyed_; }
int add_provider_called() const { return add_provider_called_; }
private:
content::TestBrowserThreadBundle thread_bundle_; // To set up BrowserThreads.
TemplateURLServiceTestUtil test_util_;
scoped_ptr<TemplateURLFetcher> template_url_fetcher_;
net::test_server::EmbeddedTestServer test_server_;
// The last TemplateURL to come from a callback.
scoped_ptr<TemplateURL> last_callback_template_url_;
// How many TemplateURLFetcherTestCallbacks have been destructed.
int callbacks_destroyed_;
// How many times ConfirmAddSearchProvider has been called.
int add_provider_called_;
// Is the code in WaitForDownloadToFinish in a message loop waiting for a
// callback to finish?
bool waiting_for_download_;
private:
DISALLOW_COPY_AND_ASSIGN(TemplateURLFetcherTest);
};
TemplateURLFetcherTest::TemplateURLFetcherTest()
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
callbacks_destroyed_(0),
add_provider_called_(0),
waiting_for_download_(false) {
base::FilePath src_dir;
CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
test_server_.ServeFilesFromDirectory(
src_dir.AppendASCII("chrome/test/data"));
}
void TemplateURLFetcherTest::DestroyedCallback() {
callbacks_destroyed_++;
if (waiting_for_download_)
base::MessageLoop::current()->Quit();
}
void TemplateURLFetcherTest::ConfirmAddSearchProvider(
base::ScopedClosureRunner* callback_destruction_notifier,
scoped_ptr<TemplateURL> template_url) {
last_callback_template_url_ = template_url.Pass();
add_provider_called_++;
}
void TemplateURLFetcherTest::StartDownload(
const base::string16& keyword,
const std::string& osdd_file_name,
TemplateURLFetcher::ProviderType provider_type,
bool check_that_file_exists) {
if (check_that_file_exists) {
base::FilePath osdd_full_path;
ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &osdd_full_path));
osdd_full_path = osdd_full_path.AppendASCII(osdd_file_name);
ASSERT_TRUE(base::PathExists(osdd_full_path));
ASSERT_FALSE(base::DirectoryExists(osdd_full_path));
}
// Start the fetch.
GURL osdd_url = test_server_.GetURL("/" + osdd_file_name);
GURL favicon_url;
base::ScopedClosureRunner* callback_destruction_notifier =
new base::ScopedClosureRunner(
base::Bind(&TemplateURLFetcherTest::DestroyedCallback,
base::Unretained(this)));
template_url_fetcher_->ScheduleDownload(
keyword, osdd_url, favicon_url,
TemplateURLFetcher::URLFetcherCustomizeCallback(),
base::Bind(&TemplateURLFetcherTest::ConfirmAddSearchProvider,
base::Unretained(this),
base::Owned(callback_destruction_notifier)),
provider_type);
}
void TemplateURLFetcherTest::WaitForDownloadToFinish() {
ASSERT_FALSE(waiting_for_download_);
waiting_for_download_ = true;
base::MessageLoop::current()->Run();
waiting_for_download_ = false;
}
TEST_F(TemplateURLFetcherTest, BasicAutodetectedTest) {
base::string16 keyword(ASCIIToUTF16("test"));
test_util()->ChangeModelToLoadState();
ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword));
std::string osdd_file_name("simple_open_search.xml");
StartDownload(keyword, osdd_file_name,
TemplateURLFetcher::AUTODETECTED_PROVIDER, true);
ASSERT_EQ(0, add_provider_called());
ASSERT_EQ(0, callbacks_destroyed());
WaitForDownloadToFinish();
ASSERT_EQ(0, add_provider_called());
ASSERT_EQ(1, callbacks_destroyed());
const TemplateURL* t_url = test_util()->model()->GetTemplateURLForKeyword(
keyword);
ASSERT_TRUE(t_url);
EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
t_url->url_ref().DisplayURL(
test_util()->model()->search_terms_data()));
EXPECT_TRUE(t_url->safe_for_autoreplace());
}
TEST_F(TemplateURLFetcherTest, DuplicatesThrownAway) {
base::string16 keyword(ASCIIToUTF16("test"));
test_util()->ChangeModelToLoadState();
ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword));
std::string osdd_file_name("simple_open_search.xml");
StartDownload(keyword, osdd_file_name,
TemplateURLFetcher::AUTODETECTED_PROVIDER, true);
ASSERT_EQ(0, add_provider_called());
ASSERT_EQ(0, callbacks_destroyed());
struct {
std::string description;
std::string osdd_file_name;
base::string16 keyword;
TemplateURLFetcher::ProviderType provider_type;
} test_cases[] = {
{ "Duplicate osdd url with autodetected provider.", osdd_file_name,
keyword + ASCIIToUTF16("1"),
TemplateURLFetcher::AUTODETECTED_PROVIDER },
{ "Duplicate keyword with autodetected provider.", osdd_file_name + "1",
keyword, TemplateURLFetcher::AUTODETECTED_PROVIDER },
{ "Duplicate osdd url with explicit provider.", osdd_file_name,
base::string16(), TemplateURLFetcher::EXPLICIT_PROVIDER },
};
for (size_t i = 0; i < arraysize(test_cases); ++i) {
StartDownload(test_cases[i].keyword, test_cases[i].osdd_file_name,
test_cases[i].provider_type, false);
ASSERT_EQ(1, template_url_fetcher()->requests_count())
<< test_cases[i].description;
ASSERT_EQ(i + 1, static_cast<size_t>(callbacks_destroyed()));
}
WaitForDownloadToFinish();
ASSERT_EQ(1 + arraysize(test_cases),
static_cast<size_t>(callbacks_destroyed()));
ASSERT_EQ(0, add_provider_called());
}
TEST_F(TemplateURLFetcherTest, BasicExplicitTest) {
base::string16 keyword(ASCIIToUTF16("test"));
test_util()->ChangeModelToLoadState();
ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword));
std::string osdd_file_name("simple_open_search.xml");
StartDownload(keyword, osdd_file_name,
TemplateURLFetcher::EXPLICIT_PROVIDER, true);
ASSERT_EQ(0, add_provider_called());
ASSERT_EQ(0, callbacks_destroyed());
WaitForDownloadToFinish();
ASSERT_EQ(1, add_provider_called());
ASSERT_EQ(1, callbacks_destroyed());
ASSERT_TRUE(last_callback_template_url());
EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
last_callback_template_url()->url_ref().DisplayURL(
test_util()->model()->search_terms_data()));
EXPECT_EQ(ASCIIToUTF16("example.com"),
last_callback_template_url()->keyword());
EXPECT_FALSE(last_callback_template_url()->safe_for_autoreplace());
}
TEST_F(TemplateURLFetcherTest, AutodetectedBeforeLoadTest) {
base::string16 keyword(ASCIIToUTF16("test"));
ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword));
std::string osdd_file_name("simple_open_search.xml");
StartDownload(keyword, osdd_file_name,
TemplateURLFetcher::AUTODETECTED_PROVIDER, true);
ASSERT_EQ(0, add_provider_called());
ASSERT_EQ(1, callbacks_destroyed());
}
TEST_F(TemplateURLFetcherTest, ExplicitBeforeLoadTest) {
base::string16 keyword(ASCIIToUTF16("test"));
ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword));
std::string osdd_file_name("simple_open_search.xml");
StartDownload(keyword, osdd_file_name,
TemplateURLFetcher::EXPLICIT_PROVIDER, true);
ASSERT_EQ(0, add_provider_called());
ASSERT_EQ(0, callbacks_destroyed());
WaitForDownloadToFinish();
ASSERT_EQ(1, add_provider_called());
ASSERT_EQ(1, callbacks_destroyed());
ASSERT_TRUE(last_callback_template_url());
EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
last_callback_template_url()->url_ref().DisplayURL(
test_util()->model()->search_terms_data()));
EXPECT_EQ(ASCIIToUTF16("example.com"),
last_callback_template_url()->keyword());
EXPECT_FALSE(last_callback_template_url()->safe_for_autoreplace());
}
TEST_F(TemplateURLFetcherTest, DuplicateKeywordsTest) {
base::string16 keyword(ASCIIToUTF16("test"));
TemplateURLData data;
data.short_name = keyword;
data.SetKeyword(keyword);
data.SetURL("http://example.com/");
test_util()->model()->Add(new TemplateURL(data));
test_util()->ChangeModelToLoadState();
ASSERT_TRUE(test_util()->model()->GetTemplateURLForKeyword(keyword));
// This should bail because the keyword already exists.
std::string osdd_file_name("simple_open_search.xml");
StartDownload(keyword, osdd_file_name,
TemplateURLFetcher::AUTODETECTED_PROVIDER, true);
ASSERT_EQ(0, add_provider_called());
ASSERT_EQ(1, callbacks_destroyed());
ASSERT_FALSE(last_callback_template_url());
}
TEST_F(TemplateURLFetcherTest, DuplicateDownloadTest) {
base::string16 keyword(ASCIIToUTF16("test"));
std::string osdd_file_name("simple_open_search.xml");
StartDownload(keyword, osdd_file_name,
TemplateURLFetcher::EXPLICIT_PROVIDER, true);
ASSERT_EQ(0, add_provider_called());
ASSERT_EQ(0, callbacks_destroyed());
// This should bail because the keyword already has a pending download.
StartDownload(keyword, osdd_file_name,
TemplateURLFetcher::EXPLICIT_PROVIDER, true);
ASSERT_EQ(0, add_provider_called());
ASSERT_EQ(1, callbacks_destroyed());
WaitForDownloadToFinish();
ASSERT_EQ(1, add_provider_called());
ASSERT_EQ(2, callbacks_destroyed());
ASSERT_TRUE(last_callback_template_url());
}