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
3 // found in the LICENSE file.
7 #include "base/callback_helpers.h"
8 #include "base/files/file_util.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/path_service.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/search_engines/template_url_service_test_util.h"
14 #include "chrome/test/base/testing_profile.h"
15 #include "components/search_engines/template_url.h"
16 #include "components/search_engines/template_url_fetcher.h"
17 #include "components/search_engines/template_url_service.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "net/test/embedded_test_server/embedded_test_server.h"
20 #include "testing/gtest/include/gtest/gtest.h"
23 using base::ASCIIToUTF16
;
25 // Basic set-up for TemplateURLFetcher tests.
26 class TemplateURLFetcherTest
: public testing::Test
{
28 TemplateURLFetcherTest();
30 void SetUp() override
{
31 TestingProfile
* profile
= test_util_
.profile();
32 ASSERT_TRUE(profile
->GetRequestContext());
33 template_url_fetcher_
.reset(new TemplateURLFetcher(
34 test_util_
.model(), profile
->GetRequestContext()));
36 ASSERT_TRUE(test_server_
.InitializeAndWaitUntilReady());
39 void TearDown() override
{
40 ASSERT_TRUE(test_server_
.ShutdownAndWaitUntilComplete());
43 // Called when the callback is destroyed.
44 void DestroyedCallback();
46 // TemplateURLFetcherCallbacks implementation. (Although not derived from
47 // this class, this method handles those calls for the test.)
48 void ConfirmAddSearchProvider(
49 base::ScopedClosureRunner
* callback_destruction_notifier
,
50 scoped_ptr
<TemplateURL
> template_url
);
52 // Schedules the download of the url.
53 void StartDownload(const base::string16
& keyword
,
54 const std::string
& osdd_file_name
,
55 TemplateURLFetcher::ProviderType provider_type
,
56 bool check_that_file_exists
);
58 // Waits for any downloads to finish.
59 void WaitForDownloadToFinish();
61 TemplateURLServiceTestUtil
* test_util() { return &test_util_
; }
62 TemplateURLFetcher
* template_url_fetcher() {
63 return template_url_fetcher_
.get();
65 const TemplateURL
* last_callback_template_url() const {
66 return last_callback_template_url_
.get();
68 int callbacks_destroyed() const { return callbacks_destroyed_
; }
69 int add_provider_called() const { return add_provider_called_
; }
72 content::TestBrowserThreadBundle thread_bundle_
; // To set up BrowserThreads.
73 TemplateURLServiceTestUtil test_util_
;
74 scoped_ptr
<TemplateURLFetcher
> template_url_fetcher_
;
75 net::test_server::EmbeddedTestServer test_server_
;
77 // The last TemplateURL to come from a callback.
78 scoped_ptr
<TemplateURL
> last_callback_template_url_
;
80 // How many TemplateURLFetcherTestCallbacks have been destructed.
81 int callbacks_destroyed_
;
83 // How many times ConfirmAddSearchProvider has been called.
84 int add_provider_called_
;
86 // Is the code in WaitForDownloadToFinish in a message loop waiting for a
87 // callback to finish?
88 bool waiting_for_download_
;
91 DISALLOW_COPY_AND_ASSIGN(TemplateURLFetcherTest
);
94 bool GetTestDataDir(base::FilePath
* dir
) {
95 if (!PathService::Get(base::DIR_SOURCE_ROOT
, dir
))
97 *dir
= dir
->AppendASCII("components")
100 .AppendASCII("search_engines");
104 TemplateURLFetcherTest::TemplateURLFetcherTest()
105 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
),
106 callbacks_destroyed_(0),
107 add_provider_called_(0),
108 waiting_for_download_(false) {
109 base::FilePath test_data_dir
;
110 CHECK(GetTestDataDir(&test_data_dir
));
111 test_server_
.ServeFilesFromDirectory(test_data_dir
);
114 void TemplateURLFetcherTest::DestroyedCallback() {
115 callbacks_destroyed_
++;
116 if (waiting_for_download_
)
117 base::MessageLoop::current()->Quit();
120 void TemplateURLFetcherTest::ConfirmAddSearchProvider(
121 base::ScopedClosureRunner
* callback_destruction_notifier
,
122 scoped_ptr
<TemplateURL
> template_url
) {
123 last_callback_template_url_
= template_url
.Pass();
124 add_provider_called_
++;
127 void TemplateURLFetcherTest::StartDownload(
128 const base::string16
& keyword
,
129 const std::string
& osdd_file_name
,
130 TemplateURLFetcher::ProviderType provider_type
,
131 bool check_that_file_exists
) {
132 if (check_that_file_exists
) {
133 base::FilePath osdd_full_path
;
134 ASSERT_TRUE(GetTestDataDir(&osdd_full_path
));
135 osdd_full_path
= osdd_full_path
.AppendASCII(osdd_file_name
);
136 ASSERT_TRUE(base::PathExists(osdd_full_path
));
137 ASSERT_FALSE(base::DirectoryExists(osdd_full_path
));
141 GURL osdd_url
= test_server_
.GetURL("/" + osdd_file_name
);
143 base::ScopedClosureRunner
* callback_destruction_notifier
=
144 new base::ScopedClosureRunner(
145 base::Bind(&TemplateURLFetcherTest::DestroyedCallback
,
146 base::Unretained(this)));
148 template_url_fetcher_
->ScheduleDownload(
149 keyword
, osdd_url
, favicon_url
,
150 TemplateURLFetcher::URLFetcherCustomizeCallback(),
151 base::Bind(&TemplateURLFetcherTest::ConfirmAddSearchProvider
,
152 base::Unretained(this),
153 base::Owned(callback_destruction_notifier
)),
157 void TemplateURLFetcherTest::WaitForDownloadToFinish() {
158 ASSERT_FALSE(waiting_for_download_
);
159 waiting_for_download_
= true;
160 base::MessageLoop::current()->Run();
161 waiting_for_download_
= false;
164 TEST_F(TemplateURLFetcherTest
, BasicAutodetectedTest
) {
165 base::string16
keyword(ASCIIToUTF16("test"));
167 test_util()->ChangeModelToLoadState();
168 ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword
));
170 std::string
osdd_file_name("simple_open_search.xml");
171 StartDownload(keyword
, osdd_file_name
,
172 TemplateURLFetcher::AUTODETECTED_PROVIDER
, true);
173 ASSERT_EQ(0, add_provider_called());
174 ASSERT_EQ(0, callbacks_destroyed());
176 WaitForDownloadToFinish();
177 ASSERT_EQ(0, add_provider_called());
178 ASSERT_EQ(1, callbacks_destroyed());
180 const TemplateURL
* t_url
= test_util()->model()->GetTemplateURLForKeyword(
183 EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
184 t_url
->url_ref().DisplayURL(
185 test_util()->model()->search_terms_data()));
186 EXPECT_EQ(ASCIIToUTF16("Simple Search"), t_url
->short_name());
187 EXPECT_TRUE(t_url
->safe_for_autoreplace());
190 TEST_F(TemplateURLFetcherTest
, DuplicatesThrownAway
) {
191 base::string16
keyword(ASCIIToUTF16("test"));
193 test_util()->ChangeModelToLoadState();
194 ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword
));
196 std::string
osdd_file_name("simple_open_search.xml");
197 StartDownload(keyword
, osdd_file_name
,
198 TemplateURLFetcher::AUTODETECTED_PROVIDER
, true);
199 ASSERT_EQ(0, add_provider_called());
200 ASSERT_EQ(0, callbacks_destroyed());
203 std::string description
;
204 std::string osdd_file_name
;
205 base::string16 keyword
;
206 TemplateURLFetcher::ProviderType provider_type
;
208 { "Duplicate osdd url with autodetected provider.", osdd_file_name
,
209 keyword
+ ASCIIToUTF16("1"),
210 TemplateURLFetcher::AUTODETECTED_PROVIDER
},
211 { "Duplicate keyword with autodetected provider.", osdd_file_name
+ "1",
212 keyword
, TemplateURLFetcher::AUTODETECTED_PROVIDER
},
213 { "Duplicate osdd url with explicit provider.", osdd_file_name
,
214 base::string16(), TemplateURLFetcher::EXPLICIT_PROVIDER
},
217 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
218 StartDownload(test_cases
[i
].keyword
, test_cases
[i
].osdd_file_name
,
219 test_cases
[i
].provider_type
, false);
220 ASSERT_EQ(1, template_url_fetcher()->requests_count())
221 << test_cases
[i
].description
;
222 ASSERT_EQ(i
+ 1, static_cast<size_t>(callbacks_destroyed()));
225 WaitForDownloadToFinish();
226 ASSERT_EQ(1 + arraysize(test_cases
),
227 static_cast<size_t>(callbacks_destroyed()));
228 ASSERT_EQ(0, add_provider_called());
231 TEST_F(TemplateURLFetcherTest
, BasicExplicitTest
) {
232 base::string16
keyword(ASCIIToUTF16("test"));
234 test_util()->ChangeModelToLoadState();
235 ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword
));
237 std::string
osdd_file_name("simple_open_search.xml");
238 StartDownload(keyword
, osdd_file_name
,
239 TemplateURLFetcher::EXPLICIT_PROVIDER
, true);
240 ASSERT_EQ(0, add_provider_called());
241 ASSERT_EQ(0, callbacks_destroyed());
243 WaitForDownloadToFinish();
244 ASSERT_EQ(1, add_provider_called());
245 ASSERT_EQ(1, callbacks_destroyed());
247 ASSERT_TRUE(last_callback_template_url());
248 EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
249 last_callback_template_url()->url_ref().DisplayURL(
250 test_util()->model()->search_terms_data()));
251 EXPECT_EQ(ASCIIToUTF16("example.com"),
252 last_callback_template_url()->keyword());
253 EXPECT_FALSE(last_callback_template_url()->safe_for_autoreplace());
256 TEST_F(TemplateURLFetcherTest
, AutodetectedBeforeLoadTest
) {
257 base::string16
keyword(ASCIIToUTF16("test"));
258 ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword
));
260 std::string
osdd_file_name("simple_open_search.xml");
261 StartDownload(keyword
, osdd_file_name
,
262 TemplateURLFetcher::AUTODETECTED_PROVIDER
, true);
263 ASSERT_EQ(0, add_provider_called());
264 ASSERT_EQ(1, callbacks_destroyed());
267 TEST_F(TemplateURLFetcherTest
, ExplicitBeforeLoadTest
) {
268 base::string16
keyword(ASCIIToUTF16("test"));
269 ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword
));
271 std::string
osdd_file_name("simple_open_search.xml");
272 StartDownload(keyword
, osdd_file_name
,
273 TemplateURLFetcher::EXPLICIT_PROVIDER
, true);
274 ASSERT_EQ(0, add_provider_called());
275 ASSERT_EQ(0, callbacks_destroyed());
277 WaitForDownloadToFinish();
278 ASSERT_EQ(1, add_provider_called());
279 ASSERT_EQ(1, callbacks_destroyed());
281 ASSERT_TRUE(last_callback_template_url());
282 EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
283 last_callback_template_url()->url_ref().DisplayURL(
284 test_util()->model()->search_terms_data()));
285 EXPECT_EQ(ASCIIToUTF16("example.com"),
286 last_callback_template_url()->keyword());
287 EXPECT_FALSE(last_callback_template_url()->safe_for_autoreplace());
290 TEST_F(TemplateURLFetcherTest
, DuplicateKeywordsTest
) {
291 base::string16
keyword(ASCIIToUTF16("test"));
292 TemplateURLData data
;
293 data
.SetShortName(keyword
);
294 data
.SetKeyword(keyword
);
295 data
.SetURL("http://example.com/");
296 test_util()->model()->Add(new TemplateURL(data
));
297 test_util()->ChangeModelToLoadState();
299 ASSERT_TRUE(test_util()->model()->GetTemplateURLForKeyword(keyword
));
301 // This should bail because the keyword already exists.
302 std::string
osdd_file_name("simple_open_search.xml");
303 StartDownload(keyword
, osdd_file_name
,
304 TemplateURLFetcher::AUTODETECTED_PROVIDER
, true);
305 ASSERT_EQ(0, add_provider_called());
306 ASSERT_EQ(1, callbacks_destroyed());
307 ASSERT_FALSE(last_callback_template_url());
310 TEST_F(TemplateURLFetcherTest
, DuplicateDownloadTest
) {
311 base::string16
keyword(ASCIIToUTF16("test"));
312 std::string
osdd_file_name("simple_open_search.xml");
313 StartDownload(keyword
, osdd_file_name
,
314 TemplateURLFetcher::EXPLICIT_PROVIDER
, true);
315 ASSERT_EQ(0, add_provider_called());
316 ASSERT_EQ(0, callbacks_destroyed());
318 // This should bail because the keyword already has a pending download.
319 StartDownload(keyword
, osdd_file_name
,
320 TemplateURLFetcher::EXPLICIT_PROVIDER
, true);
321 ASSERT_EQ(0, add_provider_called());
322 ASSERT_EQ(1, callbacks_destroyed());
324 WaitForDownloadToFinish();
325 ASSERT_EQ(1, add_provider_called());
326 ASSERT_EQ(2, callbacks_destroyed());
327 ASSERT_TRUE(last_callback_template_url());
330 TEST_F(TemplateURLFetcherTest
, UnicodeTest
) {
331 base::string16
keyword(ASCIIToUTF16("test"));
333 test_util()->ChangeModelToLoadState();
334 ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword
));
336 std::string
osdd_file_name("unicode_open_search.xml");
337 StartDownload(keyword
, osdd_file_name
,
338 TemplateURLFetcher::AUTODETECTED_PROVIDER
, true);
339 WaitForDownloadToFinish();
340 const TemplateURL
* t_url
=
341 test_util()->model()->GetTemplateURLForKeyword(keyword
);
342 EXPECT_EQ(base::UTF8ToUTF16("\xd1\x82\xd0\xb5\xd1\x81\xd1\x82"),
343 t_url
->short_name());