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/file_util.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/path_service.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/search_engines/template_url.h"
11 #include "chrome/browser/search_engines/template_url_fetcher.h"
12 #include "chrome/browser/search_engines/template_url_fetcher_callbacks.h"
13 #include "chrome/browser/search_engines/template_url_fetcher_factory.h"
14 #include "chrome/browser/search_engines/template_url_service.h"
15 #include "chrome/browser/search_engines/template_url_service_test_util.h"
16 #include "chrome/common/chrome_paths.h"
17 #include "chrome/test/base/testing_profile.h"
18 #include "content/public/browser/browser_thread.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 class TemplateURLFetcherTest
;
27 // Handles callbacks from TemplateURLFetcher.
28 class TemplateURLFetcherTestCallbacks
: public TemplateURLFetcherCallbacks
{
30 explicit TemplateURLFetcherTestCallbacks(TemplateURLFetcherTest
* test
)
33 virtual ~TemplateURLFetcherTestCallbacks();
35 // TemplateURLFetcherCallbacks implementation.
36 virtual void ConfirmAddSearchProvider(TemplateURL
* template_url
,
37 Profile
* profile
) OVERRIDE
;
40 TemplateURLFetcherTest
* test_
;
42 DISALLOW_COPY_AND_ASSIGN(TemplateURLFetcherTestCallbacks
);
45 // Basic set-up for TemplateURLFetcher tests.
46 class TemplateURLFetcherTest
: public testing::Test
{
48 TemplateURLFetcherTest();
50 virtual void SetUp() OVERRIDE
{
52 TestingProfile
* profile
= test_util_
.profile();
54 ASSERT_TRUE(TemplateURLFetcherFactory::GetForProfile(profile
));
56 ASSERT_TRUE(profile
->GetRequestContext());
57 ASSERT_TRUE(test_server_
.InitializeAndWaitUntilReady());
60 virtual void TearDown() OVERRIDE
{
61 ASSERT_TRUE(test_server_
.ShutdownAndWaitUntilComplete());
62 test_util_
.TearDown();
65 // Called by ~TemplateURLFetcherTestCallbacks.
66 void DestroyedCallback(TemplateURLFetcherTestCallbacks
* callbacks
);
68 // TemplateURLFetcherCallbacks implementation. (Although not derived from
69 // this class, this method handles those calls for the test.)
70 void ConfirmAddSearchProvider(TemplateURL
* template_url
, Profile
* profile
);
73 // Schedules the download of the url.
74 void StartDownload(const base::string16
& keyword
,
75 const std::string
& osdd_file_name
,
76 TemplateURLFetcher::ProviderType provider_type
,
77 bool check_that_file_exists
);
79 // Waits for any downloads to finish.
80 void WaitForDownloadToFinish();
82 TemplateURLServiceTestUtil test_util_
;
83 net::test_server::EmbeddedTestServer test_server_
;
85 // The last TemplateURL to come from a callback.
86 scoped_ptr
<TemplateURL
> last_callback_template_url_
;
88 // How many TemplateURLFetcherTestCallbacks have been destructed.
89 int callbacks_destroyed_
;
91 // How many times ConfirmAddSearchProvider has been called.
92 int add_provider_called_
;
94 // Is the code in WaitForDownloadToFinish in a message loop waiting for a
95 // callback to finish?
96 bool waiting_for_download_
;
99 DISALLOW_COPY_AND_ASSIGN(TemplateURLFetcherTest
);
102 TemplateURLFetcherTestCallbacks::~TemplateURLFetcherTestCallbacks() {
103 test_
->DestroyedCallback(this);
106 void TemplateURLFetcherTestCallbacks::ConfirmAddSearchProvider(
107 TemplateURL
* template_url
,
109 test_
->ConfirmAddSearchProvider(template_url
, profile
);
112 TemplateURLFetcherTest::TemplateURLFetcherTest()
113 : callbacks_destroyed_(0),
114 add_provider_called_(0),
115 waiting_for_download_(false) {
116 base::FilePath src_dir
;
117 CHECK(PathService::Get(base::DIR_SOURCE_ROOT
, &src_dir
));
118 test_server_
.ServeFilesFromDirectory(
119 src_dir
.AppendASCII("chrome/test/data"));
122 void TemplateURLFetcherTest::DestroyedCallback(
123 TemplateURLFetcherTestCallbacks
* callbacks
) {
124 callbacks_destroyed_
++;
125 if (waiting_for_download_
)
126 base::MessageLoop::current()->Quit();
129 void TemplateURLFetcherTest::ConfirmAddSearchProvider(
130 TemplateURL
* template_url
,
132 last_callback_template_url_
.reset(template_url
);
133 add_provider_called_
++;
136 void TemplateURLFetcherTest::StartDownload(
137 const base::string16
& keyword
,
138 const std::string
& osdd_file_name
,
139 TemplateURLFetcher::ProviderType provider_type
,
140 bool check_that_file_exists
) {
142 if (check_that_file_exists
) {
143 base::FilePath osdd_full_path
;
144 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &osdd_full_path
));
145 osdd_full_path
= osdd_full_path
.AppendASCII(osdd_file_name
);
146 ASSERT_TRUE(base::PathExists(osdd_full_path
));
147 ASSERT_FALSE(base::DirectoryExists(osdd_full_path
));
151 GURL osdd_url
= test_server_
.GetURL("/" + osdd_file_name
);
153 TemplateURLFetcherFactory::GetForProfile(
154 test_util_
.profile())->ScheduleDownload(
155 keyword
, osdd_url
, favicon_url
, NULL
,
156 new TemplateURLFetcherTestCallbacks(this), provider_type
);
159 void TemplateURLFetcherTest::WaitForDownloadToFinish() {
160 ASSERT_FALSE(waiting_for_download_
);
161 waiting_for_download_
= true;
162 base::MessageLoop::current()->Run();
163 waiting_for_download_
= false;
166 TEST_F(TemplateURLFetcherTest
, BasicAutodetectedTest
) {
167 base::string16
keyword(ASCIIToUTF16("test"));
169 test_util_
.ChangeModelToLoadState();
170 ASSERT_FALSE(test_util_
.model()->GetTemplateURLForKeyword(keyword
));
172 std::string
osdd_file_name("simple_open_search.xml");
173 StartDownload(keyword
, osdd_file_name
,
174 TemplateURLFetcher::AUTODETECTED_PROVIDER
, true);
175 ASSERT_EQ(0, add_provider_called_
);
176 ASSERT_EQ(0, callbacks_destroyed_
);
178 WaitForDownloadToFinish();
179 ASSERT_EQ(0, add_provider_called_
);
180 ASSERT_EQ(1, callbacks_destroyed_
);
182 const TemplateURL
* t_url
= test_util_
.model()->GetTemplateURLForKeyword(
185 EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
186 t_url
->url_ref().DisplayURL());
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_UNSAFE(test_cases
); ++i
) {
218 StartDownload(test_cases
[i
].keyword
, test_cases
[i
].osdd_file_name
,
219 test_cases
[i
].provider_type
, false);
222 TemplateURLFetcherFactory::GetForProfile(
223 test_util_
.profile())->requests_count()) <<
224 test_cases
[i
].description
;
225 ASSERT_EQ(i
+ 1, static_cast<size_t>(callbacks_destroyed_
));
228 WaitForDownloadToFinish();
229 ASSERT_EQ(1 + ARRAYSIZE_UNSAFE(test_cases
),
230 static_cast<size_t>(callbacks_destroyed_
));
231 ASSERT_EQ(0, add_provider_called_
);
234 TEST_F(TemplateURLFetcherTest
, BasicExplicitTest
) {
235 base::string16
keyword(ASCIIToUTF16("test"));
237 test_util_
.ChangeModelToLoadState();
238 ASSERT_FALSE(test_util_
.model()->GetTemplateURLForKeyword(keyword
));
240 std::string
osdd_file_name("simple_open_search.xml");
241 StartDownload(keyword
, osdd_file_name
,
242 TemplateURLFetcher::EXPLICIT_PROVIDER
, true);
243 ASSERT_EQ(0, add_provider_called_
);
244 ASSERT_EQ(0, callbacks_destroyed_
);
246 WaitForDownloadToFinish();
247 ASSERT_EQ(1, add_provider_called_
);
248 ASSERT_EQ(1, callbacks_destroyed_
);
250 ASSERT_TRUE(last_callback_template_url_
.get());
251 EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
252 last_callback_template_url_
->url_ref().DisplayURL());
253 EXPECT_EQ(ASCIIToUTF16("example.com"),
254 last_callback_template_url_
->keyword());
255 EXPECT_FALSE(last_callback_template_url_
->safe_for_autoreplace());
258 TEST_F(TemplateURLFetcherTest
, AutodetectedBeforeLoadTest
) {
259 base::string16
keyword(ASCIIToUTF16("test"));
260 ASSERT_FALSE(test_util_
.model()->GetTemplateURLForKeyword(keyword
));
262 std::string
osdd_file_name("simple_open_search.xml");
263 StartDownload(keyword
, osdd_file_name
,
264 TemplateURLFetcher::AUTODETECTED_PROVIDER
, true);
265 ASSERT_EQ(0, add_provider_called_
);
266 ASSERT_EQ(1, callbacks_destroyed_
);
269 TEST_F(TemplateURLFetcherTest
, ExplicitBeforeLoadTest
) {
270 base::string16
keyword(ASCIIToUTF16("test"));
271 ASSERT_FALSE(test_util_
.model()->GetTemplateURLForKeyword(keyword
));
273 std::string
osdd_file_name("simple_open_search.xml");
274 StartDownload(keyword
, osdd_file_name
,
275 TemplateURLFetcher::EXPLICIT_PROVIDER
, true);
276 ASSERT_EQ(0, add_provider_called_
);
277 ASSERT_EQ(0, callbacks_destroyed_
);
279 WaitForDownloadToFinish();
280 ASSERT_EQ(1, add_provider_called_
);
281 ASSERT_EQ(1, callbacks_destroyed_
);
283 ASSERT_TRUE(last_callback_template_url_
.get());
284 EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
285 last_callback_template_url_
->url_ref().DisplayURL());
286 EXPECT_EQ(ASCIIToUTF16("example.com"),
287 last_callback_template_url_
->keyword());
288 EXPECT_FALSE(last_callback_template_url_
->safe_for_autoreplace());
291 TEST_F(TemplateURLFetcherTest
, DuplicateKeywordsTest
) {
292 base::string16
keyword(ASCIIToUTF16("test"));
293 TemplateURLData data
;
294 data
.short_name
= keyword
;
295 data
.SetKeyword(keyword
);
296 data
.SetURL("http://example.com/");
297 test_util_
.model()->Add(new TemplateURL(test_util_
.profile(), data
));
298 test_util_
.ChangeModelToLoadState();
300 ASSERT_TRUE(test_util_
.model()->GetTemplateURLForKeyword(keyword
));
302 // This should bail because the keyword already exists.
303 std::string
osdd_file_name("simple_open_search.xml");
304 StartDownload(keyword
, osdd_file_name
,
305 TemplateURLFetcher::AUTODETECTED_PROVIDER
, true);
306 ASSERT_EQ(0, add_provider_called_
);
307 ASSERT_EQ(1, callbacks_destroyed_
);
308 ASSERT_FALSE(last_callback_template_url_
.get());
311 TEST_F(TemplateURLFetcherTest
, DuplicateDownloadTest
) {
312 base::string16
keyword(ASCIIToUTF16("test"));
313 std::string
osdd_file_name("simple_open_search.xml");
314 StartDownload(keyword
, osdd_file_name
,
315 TemplateURLFetcher::EXPLICIT_PROVIDER
, true);
316 ASSERT_EQ(0, add_provider_called_
);
317 ASSERT_EQ(0, callbacks_destroyed_
);
319 // This should bail because the keyword already has a pending download.
320 StartDownload(keyword
, osdd_file_name
,
321 TemplateURLFetcher::EXPLICIT_PROVIDER
, true);
322 ASSERT_EQ(0, add_provider_called_
);
323 ASSERT_EQ(1, callbacks_destroyed_
);
325 WaitForDownloadToFinish();
326 ASSERT_EQ(1, add_provider_called_
);
327 ASSERT_EQ(2, callbacks_destroyed_
);
328 ASSERT_TRUE(last_callback_template_url_
.get());