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.
5 #include "base/callback_helpers.h"
6 #include "base/files/file_util.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/path_service.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/search_engines/template_url_service_test_util.h"
12 #include "chrome/test/base/testing_profile.h"
13 #include "components/search_engines/template_url.h"
14 #include "components/search_engines/template_url_fetcher.h"
15 #include "components/search_engines/template_url_service.h"
16 #include "content/public/test/test_browser_thread_bundle.h"
17 #include "net/test/embedded_test_server/embedded_test_server.h"
18 #include "testing/gtest/include/gtest/gtest.h"
21 using base::ASCIIToUTF16
;
23 // Basic set-up for TemplateURLFetcher tests.
24 class TemplateURLFetcherTest
: public testing::Test
{
26 TemplateURLFetcherTest();
28 void SetUp() override
{
29 TestingProfile
* profile
= test_util_
.profile();
30 ASSERT_TRUE(profile
->GetRequestContext());
31 template_url_fetcher_
.reset(new TemplateURLFetcher(
32 test_util_
.model(), profile
->GetRequestContext()));
34 ASSERT_TRUE(test_server_
.InitializeAndWaitUntilReady());
37 void TearDown() override
{
38 ASSERT_TRUE(test_server_
.ShutdownAndWaitUntilComplete());
41 // Called when the callback is destroyed.
42 void DestroyedCallback();
44 // TemplateURLFetcherCallbacks implementation. (Although not derived from
45 // this class, this method handles those calls for the test.)
46 void ConfirmAddSearchProvider(
47 base::ScopedClosureRunner
* callback_destruction_notifier
,
48 scoped_ptr
<TemplateURL
> template_url
);
50 // Schedules the download of the url.
51 void StartDownload(const base::string16
& keyword
,
52 const std::string
& osdd_file_name
,
53 TemplateURLFetcher::ProviderType provider_type
,
54 bool check_that_file_exists
);
56 // Waits for any downloads to finish.
57 void WaitForDownloadToFinish();
59 TemplateURLServiceTestUtil
* test_util() { return &test_util_
; }
60 TemplateURLFetcher
* template_url_fetcher() {
61 return template_url_fetcher_
.get();
63 const TemplateURL
* last_callback_template_url() const {
64 return last_callback_template_url_
.get();
66 int callbacks_destroyed() const { return callbacks_destroyed_
; }
67 int add_provider_called() const { return add_provider_called_
; }
70 content::TestBrowserThreadBundle thread_bundle_
; // To set up BrowserThreads.
71 TemplateURLServiceTestUtil test_util_
;
72 scoped_ptr
<TemplateURLFetcher
> template_url_fetcher_
;
73 net::test_server::EmbeddedTestServer test_server_
;
75 // The last TemplateURL to come from a callback.
76 scoped_ptr
<TemplateURL
> last_callback_template_url_
;
78 // How many TemplateURLFetcherTestCallbacks have been destructed.
79 int callbacks_destroyed_
;
81 // How many times ConfirmAddSearchProvider has been called.
82 int add_provider_called_
;
84 // Is the code in WaitForDownloadToFinish in a message loop waiting for a
85 // callback to finish?
86 bool waiting_for_download_
;
89 DISALLOW_COPY_AND_ASSIGN(TemplateURLFetcherTest
);
92 bool GetTestDataDir(base::FilePath
* dir
) {
93 if (!PathService::Get(base::DIR_SOURCE_ROOT
, dir
))
95 *dir
= dir
->AppendASCII("components")
98 .AppendASCII("search_engines");
102 TemplateURLFetcherTest::TemplateURLFetcherTest()
103 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
),
104 callbacks_destroyed_(0),
105 add_provider_called_(0),
106 waiting_for_download_(false) {
107 base::FilePath test_data_dir
;
108 CHECK(GetTestDataDir(&test_data_dir
));
109 test_server_
.ServeFilesFromDirectory(test_data_dir
);
112 void TemplateURLFetcherTest::DestroyedCallback() {
113 callbacks_destroyed_
++;
114 if (waiting_for_download_
)
115 base::MessageLoop::current()->Quit();
118 void TemplateURLFetcherTest::ConfirmAddSearchProvider(
119 base::ScopedClosureRunner
* callback_destruction_notifier
,
120 scoped_ptr
<TemplateURL
> template_url
) {
121 last_callback_template_url_
= template_url
.Pass();
122 add_provider_called_
++;
125 void TemplateURLFetcherTest::StartDownload(
126 const base::string16
& keyword
,
127 const std::string
& osdd_file_name
,
128 TemplateURLFetcher::ProviderType provider_type
,
129 bool check_that_file_exists
) {
130 if (check_that_file_exists
) {
131 base::FilePath osdd_full_path
;
132 ASSERT_TRUE(GetTestDataDir(&osdd_full_path
));
133 osdd_full_path
= osdd_full_path
.AppendASCII(osdd_file_name
);
134 ASSERT_TRUE(base::PathExists(osdd_full_path
));
135 ASSERT_FALSE(base::DirectoryExists(osdd_full_path
));
139 GURL osdd_url
= test_server_
.GetURL("/" + osdd_file_name
);
141 base::ScopedClosureRunner
* callback_destruction_notifier
=
142 new base::ScopedClosureRunner(
143 base::Bind(&TemplateURLFetcherTest::DestroyedCallback
,
144 base::Unretained(this)));
146 template_url_fetcher_
->ScheduleDownload(
147 keyword
, osdd_url
, favicon_url
,
148 TemplateURLFetcher::URLFetcherCustomizeCallback(),
149 base::Bind(&TemplateURLFetcherTest::ConfirmAddSearchProvider
,
150 base::Unretained(this),
151 base::Owned(callback_destruction_notifier
)),
155 void TemplateURLFetcherTest::WaitForDownloadToFinish() {
156 ASSERT_FALSE(waiting_for_download_
);
157 waiting_for_download_
= true;
158 base::MessageLoop::current()->Run();
159 waiting_for_download_
= false;
162 TEST_F(TemplateURLFetcherTest
, BasicAutodetectedTest
) {
163 base::string16
keyword(ASCIIToUTF16("test"));
165 test_util()->ChangeModelToLoadState();
166 ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword
));
168 std::string
osdd_file_name("simple_open_search.xml");
169 StartDownload(keyword
, osdd_file_name
,
170 TemplateURLFetcher::AUTODETECTED_PROVIDER
, true);
171 ASSERT_EQ(0, add_provider_called());
172 ASSERT_EQ(0, callbacks_destroyed());
174 WaitForDownloadToFinish();
175 ASSERT_EQ(0, add_provider_called());
176 ASSERT_EQ(1, callbacks_destroyed());
178 const TemplateURL
* t_url
= test_util()->model()->GetTemplateURLForKeyword(
181 EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
182 t_url
->url_ref().DisplayURL(
183 test_util()->model()->search_terms_data()));
184 EXPECT_TRUE(t_url
->safe_for_autoreplace());
187 TEST_F(TemplateURLFetcherTest
, DuplicatesThrownAway
) {
188 base::string16
keyword(ASCIIToUTF16("test"));
190 test_util()->ChangeModelToLoadState();
191 ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword
));
193 std::string
osdd_file_name("simple_open_search.xml");
194 StartDownload(keyword
, osdd_file_name
,
195 TemplateURLFetcher::AUTODETECTED_PROVIDER
, true);
196 ASSERT_EQ(0, add_provider_called());
197 ASSERT_EQ(0, callbacks_destroyed());
200 std::string description
;
201 std::string osdd_file_name
;
202 base::string16 keyword
;
203 TemplateURLFetcher::ProviderType provider_type
;
205 { "Duplicate osdd url with autodetected provider.", osdd_file_name
,
206 keyword
+ ASCIIToUTF16("1"),
207 TemplateURLFetcher::AUTODETECTED_PROVIDER
},
208 { "Duplicate keyword with autodetected provider.", osdd_file_name
+ "1",
209 keyword
, TemplateURLFetcher::AUTODETECTED_PROVIDER
},
210 { "Duplicate osdd url with explicit provider.", osdd_file_name
,
211 base::string16(), TemplateURLFetcher::EXPLICIT_PROVIDER
},
214 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
215 StartDownload(test_cases
[i
].keyword
, test_cases
[i
].osdd_file_name
,
216 test_cases
[i
].provider_type
, false);
217 ASSERT_EQ(1, template_url_fetcher()->requests_count())
218 << test_cases
[i
].description
;
219 ASSERT_EQ(i
+ 1, static_cast<size_t>(callbacks_destroyed()));
222 WaitForDownloadToFinish();
223 ASSERT_EQ(1 + arraysize(test_cases
),
224 static_cast<size_t>(callbacks_destroyed()));
225 ASSERT_EQ(0, add_provider_called());
228 TEST_F(TemplateURLFetcherTest
, BasicExplicitTest
) {
229 base::string16
keyword(ASCIIToUTF16("test"));
231 test_util()->ChangeModelToLoadState();
232 ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword
));
234 std::string
osdd_file_name("simple_open_search.xml");
235 StartDownload(keyword
, osdd_file_name
,
236 TemplateURLFetcher::EXPLICIT_PROVIDER
, true);
237 ASSERT_EQ(0, add_provider_called());
238 ASSERT_EQ(0, callbacks_destroyed());
240 WaitForDownloadToFinish();
241 ASSERT_EQ(1, add_provider_called());
242 ASSERT_EQ(1, callbacks_destroyed());
244 ASSERT_TRUE(last_callback_template_url());
245 EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
246 last_callback_template_url()->url_ref().DisplayURL(
247 test_util()->model()->search_terms_data()));
248 EXPECT_EQ(ASCIIToUTF16("example.com"),
249 last_callback_template_url()->keyword());
250 EXPECT_FALSE(last_callback_template_url()->safe_for_autoreplace());
253 TEST_F(TemplateURLFetcherTest
, AutodetectedBeforeLoadTest
) {
254 base::string16
keyword(ASCIIToUTF16("test"));
255 ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword
));
257 std::string
osdd_file_name("simple_open_search.xml");
258 StartDownload(keyword
, osdd_file_name
,
259 TemplateURLFetcher::AUTODETECTED_PROVIDER
, true);
260 ASSERT_EQ(0, add_provider_called());
261 ASSERT_EQ(1, callbacks_destroyed());
264 TEST_F(TemplateURLFetcherTest
, ExplicitBeforeLoadTest
) {
265 base::string16
keyword(ASCIIToUTF16("test"));
266 ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword
));
268 std::string
osdd_file_name("simple_open_search.xml");
269 StartDownload(keyword
, osdd_file_name
,
270 TemplateURLFetcher::EXPLICIT_PROVIDER
, true);
271 ASSERT_EQ(0, add_provider_called());
272 ASSERT_EQ(0, callbacks_destroyed());
274 WaitForDownloadToFinish();
275 ASSERT_EQ(1, add_provider_called());
276 ASSERT_EQ(1, callbacks_destroyed());
278 ASSERT_TRUE(last_callback_template_url());
279 EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
280 last_callback_template_url()->url_ref().DisplayURL(
281 test_util()->model()->search_terms_data()));
282 EXPECT_EQ(ASCIIToUTF16("example.com"),
283 last_callback_template_url()->keyword());
284 EXPECT_FALSE(last_callback_template_url()->safe_for_autoreplace());
287 TEST_F(TemplateURLFetcherTest
, DuplicateKeywordsTest
) {
288 base::string16
keyword(ASCIIToUTF16("test"));
289 TemplateURLData data
;
290 data
.SetShortName(keyword
);
291 data
.SetKeyword(keyword
);
292 data
.SetURL("http://example.com/");
293 test_util()->model()->Add(new TemplateURL(data
));
294 test_util()->ChangeModelToLoadState();
296 ASSERT_TRUE(test_util()->model()->GetTemplateURLForKeyword(keyword
));
298 // This should bail because the keyword already exists.
299 std::string
osdd_file_name("simple_open_search.xml");
300 StartDownload(keyword
, osdd_file_name
,
301 TemplateURLFetcher::AUTODETECTED_PROVIDER
, true);
302 ASSERT_EQ(0, add_provider_called());
303 ASSERT_EQ(1, callbacks_destroyed());
304 ASSERT_FALSE(last_callback_template_url());
307 TEST_F(TemplateURLFetcherTest
, DuplicateDownloadTest
) {
308 base::string16
keyword(ASCIIToUTF16("test"));
309 std::string
osdd_file_name("simple_open_search.xml");
310 StartDownload(keyword
, osdd_file_name
,
311 TemplateURLFetcher::EXPLICIT_PROVIDER
, true);
312 ASSERT_EQ(0, add_provider_called());
313 ASSERT_EQ(0, callbacks_destroyed());
315 // This should bail because the keyword already has a pending download.
316 StartDownload(keyword
, osdd_file_name
,
317 TemplateURLFetcher::EXPLICIT_PROVIDER
, true);
318 ASSERT_EQ(0, add_provider_called());
319 ASSERT_EQ(1, callbacks_destroyed());
321 WaitForDownloadToFinish();
322 ASSERT_EQ(1, add_provider_called());
323 ASSERT_EQ(2, callbacks_destroyed());
324 ASSERT_TRUE(last_callback_template_url());