• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
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/common/chrome_paths.h"
13 #include "chrome/test/base/testing_profile.h"
14 #include "components/search_engines/template_url.h"
15 #include "components/search_engines/template_url_fetcher.h"
16 #include "components/search_engines/template_url_service.h"
17 #include "content/public/test/test_browser_thread_bundle.h"
18 #include "net/test/embedded_test_server/embedded_test_server.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "url/gurl.h"
21 
22 using base::ASCIIToUTF16;
23 
24 // Basic set-up for TemplateURLFetcher tests.
25 class TemplateURLFetcherTest : public testing::Test {
26  public:
27   TemplateURLFetcherTest();
28 
SetUp()29   virtual void SetUp() OVERRIDE {
30     TestingProfile* profile = test_util_.profile();
31     ASSERT_TRUE(profile->GetRequestContext());
32     template_url_fetcher_.reset(new TemplateURLFetcher(
33         test_util_.model(), profile->GetRequestContext()));
34 
35     ASSERT_TRUE(test_server_.InitializeAndWaitUntilReady());
36   }
37 
TearDown()38   virtual void TearDown() OVERRIDE {
39     ASSERT_TRUE(test_server_.ShutdownAndWaitUntilComplete());
40   }
41 
42   // Called when the callback is destroyed.
43   void DestroyedCallback();
44 
45   // TemplateURLFetcherCallbacks implementation.  (Although not derived from
46   // this class, this method handles those calls for the test.)
47   void ConfirmAddSearchProvider(
48       base::ScopedClosureRunner* callback_destruction_notifier,
49       scoped_ptr<TemplateURL> template_url);
50 
51   // Schedules the download of the url.
52   void StartDownload(const base::string16& keyword,
53                      const std::string& osdd_file_name,
54                      TemplateURLFetcher::ProviderType provider_type,
55                      bool check_that_file_exists);
56 
57   // Waits for any downloads to finish.
58   void WaitForDownloadToFinish();
59 
test_util()60   TemplateURLServiceTestUtil* test_util() { return &test_util_; }
template_url_fetcher()61   TemplateURLFetcher* template_url_fetcher() {
62     return template_url_fetcher_.get();
63   }
last_callback_template_url() const64   const TemplateURL* last_callback_template_url() const {
65     return last_callback_template_url_.get();
66   }
callbacks_destroyed() const67   int callbacks_destroyed() const { return callbacks_destroyed_; }
add_provider_called() const68   int add_provider_called() const { return add_provider_called_; }
69 
70  private:
71   content::TestBrowserThreadBundle thread_bundle_;  // To set up BrowserThreads.
72   TemplateURLServiceTestUtil test_util_;
73   scoped_ptr<TemplateURLFetcher> template_url_fetcher_;
74   net::test_server::EmbeddedTestServer test_server_;
75 
76   // The last TemplateURL to come from a callback.
77   scoped_ptr<TemplateURL> last_callback_template_url_;
78 
79   // How many TemplateURLFetcherTestCallbacks have been destructed.
80   int callbacks_destroyed_;
81 
82   // How many times ConfirmAddSearchProvider has been called.
83   int add_provider_called_;
84 
85   // Is the code in WaitForDownloadToFinish in a message loop waiting for a
86   // callback to finish?
87   bool waiting_for_download_;
88 
89  private:
90   DISALLOW_COPY_AND_ASSIGN(TemplateURLFetcherTest);
91 };
92 
TemplateURLFetcherTest()93 TemplateURLFetcherTest::TemplateURLFetcherTest()
94     : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
95       callbacks_destroyed_(0),
96       add_provider_called_(0),
97       waiting_for_download_(false) {
98   base::FilePath src_dir;
99   CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
100   test_server_.ServeFilesFromDirectory(
101       src_dir.AppendASCII("chrome/test/data"));
102 }
103 
DestroyedCallback()104 void TemplateURLFetcherTest::DestroyedCallback() {
105   callbacks_destroyed_++;
106   if (waiting_for_download_)
107     base::MessageLoop::current()->Quit();
108 }
109 
ConfirmAddSearchProvider(base::ScopedClosureRunner * callback_destruction_notifier,scoped_ptr<TemplateURL> template_url)110 void TemplateURLFetcherTest::ConfirmAddSearchProvider(
111     base::ScopedClosureRunner* callback_destruction_notifier,
112     scoped_ptr<TemplateURL> template_url) {
113   last_callback_template_url_ = template_url.Pass();
114   add_provider_called_++;
115 }
116 
StartDownload(const base::string16 & keyword,const std::string & osdd_file_name,TemplateURLFetcher::ProviderType provider_type,bool check_that_file_exists)117 void TemplateURLFetcherTest::StartDownload(
118     const base::string16& keyword,
119     const std::string& osdd_file_name,
120     TemplateURLFetcher::ProviderType provider_type,
121     bool check_that_file_exists) {
122 
123   if (check_that_file_exists) {
124     base::FilePath osdd_full_path;
125     ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &osdd_full_path));
126     osdd_full_path = osdd_full_path.AppendASCII(osdd_file_name);
127     ASSERT_TRUE(base::PathExists(osdd_full_path));
128     ASSERT_FALSE(base::DirectoryExists(osdd_full_path));
129   }
130 
131   // Start the fetch.
132   GURL osdd_url = test_server_.GetURL("/" + osdd_file_name);
133   GURL favicon_url;
134   base::ScopedClosureRunner* callback_destruction_notifier =
135       new base::ScopedClosureRunner(
136           base::Bind(&TemplateURLFetcherTest::DestroyedCallback,
137                      base::Unretained(this)));
138 
139   template_url_fetcher_->ScheduleDownload(
140       keyword, osdd_url, favicon_url,
141       TemplateURLFetcher::URLFetcherCustomizeCallback(),
142       base::Bind(&TemplateURLFetcherTest::ConfirmAddSearchProvider,
143                  base::Unretained(this),
144                  base::Owned(callback_destruction_notifier)),
145       provider_type);
146 }
147 
WaitForDownloadToFinish()148 void TemplateURLFetcherTest::WaitForDownloadToFinish() {
149   ASSERT_FALSE(waiting_for_download_);
150   waiting_for_download_ = true;
151   base::MessageLoop::current()->Run();
152   waiting_for_download_ = false;
153 }
154 
TEST_F(TemplateURLFetcherTest,BasicAutodetectedTest)155 TEST_F(TemplateURLFetcherTest, BasicAutodetectedTest) {
156   base::string16 keyword(ASCIIToUTF16("test"));
157 
158   test_util()->ChangeModelToLoadState();
159   ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword));
160 
161   std::string osdd_file_name("simple_open_search.xml");
162   StartDownload(keyword, osdd_file_name,
163                 TemplateURLFetcher::AUTODETECTED_PROVIDER, true);
164   ASSERT_EQ(0, add_provider_called());
165   ASSERT_EQ(0, callbacks_destroyed());
166 
167   WaitForDownloadToFinish();
168   ASSERT_EQ(0, add_provider_called());
169   ASSERT_EQ(1, callbacks_destroyed());
170 
171   const TemplateURL* t_url = test_util()->model()->GetTemplateURLForKeyword(
172       keyword);
173   ASSERT_TRUE(t_url);
174   EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
175             t_url->url_ref().DisplayURL(
176                 test_util()->model()->search_terms_data()));
177   EXPECT_TRUE(t_url->safe_for_autoreplace());
178 }
179 
TEST_F(TemplateURLFetcherTest,DuplicatesThrownAway)180 TEST_F(TemplateURLFetcherTest, DuplicatesThrownAway) {
181   base::string16 keyword(ASCIIToUTF16("test"));
182 
183   test_util()->ChangeModelToLoadState();
184   ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword));
185 
186   std::string osdd_file_name("simple_open_search.xml");
187   StartDownload(keyword, osdd_file_name,
188                 TemplateURLFetcher::AUTODETECTED_PROVIDER, true);
189   ASSERT_EQ(0, add_provider_called());
190   ASSERT_EQ(0, callbacks_destroyed());
191 
192   struct {
193     std::string description;
194     std::string osdd_file_name;
195     base::string16 keyword;
196     TemplateURLFetcher::ProviderType provider_type;
197   } test_cases[] = {
198       { "Duplicate osdd url with autodetected provider.", osdd_file_name,
199         keyword + ASCIIToUTF16("1"),
200         TemplateURLFetcher::AUTODETECTED_PROVIDER },
201       { "Duplicate keyword with autodetected provider.", osdd_file_name + "1",
202         keyword, TemplateURLFetcher::AUTODETECTED_PROVIDER },
203       { "Duplicate osdd url with explicit provider.", osdd_file_name,
204         base::string16(), TemplateURLFetcher::EXPLICIT_PROVIDER },
205   };
206 
207   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
208     StartDownload(test_cases[i].keyword, test_cases[i].osdd_file_name,
209                   test_cases[i].provider_type, false);
210     ASSERT_EQ(1, template_url_fetcher()->requests_count())
211         << test_cases[i].description;
212     ASSERT_EQ(i + 1, static_cast<size_t>(callbacks_destroyed()));
213   }
214 
215   WaitForDownloadToFinish();
216   ASSERT_EQ(1 + ARRAYSIZE_UNSAFE(test_cases),
217             static_cast<size_t>(callbacks_destroyed()));
218   ASSERT_EQ(0, add_provider_called());
219 }
220 
TEST_F(TemplateURLFetcherTest,BasicExplicitTest)221 TEST_F(TemplateURLFetcherTest, BasicExplicitTest) {
222   base::string16 keyword(ASCIIToUTF16("test"));
223 
224   test_util()->ChangeModelToLoadState();
225   ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword));
226 
227   std::string osdd_file_name("simple_open_search.xml");
228   StartDownload(keyword, osdd_file_name,
229                 TemplateURLFetcher::EXPLICIT_PROVIDER, true);
230   ASSERT_EQ(0, add_provider_called());
231   ASSERT_EQ(0, callbacks_destroyed());
232 
233   WaitForDownloadToFinish();
234   ASSERT_EQ(1, add_provider_called());
235   ASSERT_EQ(1, callbacks_destroyed());
236 
237   ASSERT_TRUE(last_callback_template_url());
238   EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
239             last_callback_template_url()->url_ref().DisplayURL(
240                 test_util()->model()->search_terms_data()));
241   EXPECT_EQ(ASCIIToUTF16("example.com"),
242             last_callback_template_url()->keyword());
243   EXPECT_FALSE(last_callback_template_url()->safe_for_autoreplace());
244 }
245 
TEST_F(TemplateURLFetcherTest,AutodetectedBeforeLoadTest)246 TEST_F(TemplateURLFetcherTest, AutodetectedBeforeLoadTest) {
247   base::string16 keyword(ASCIIToUTF16("test"));
248   ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword));
249 
250   std::string osdd_file_name("simple_open_search.xml");
251   StartDownload(keyword, osdd_file_name,
252                 TemplateURLFetcher::AUTODETECTED_PROVIDER, true);
253   ASSERT_EQ(0, add_provider_called());
254   ASSERT_EQ(1, callbacks_destroyed());
255 }
256 
TEST_F(TemplateURLFetcherTest,ExplicitBeforeLoadTest)257 TEST_F(TemplateURLFetcherTest, ExplicitBeforeLoadTest) {
258   base::string16 keyword(ASCIIToUTF16("test"));
259   ASSERT_FALSE(test_util()->model()->GetTemplateURLForKeyword(keyword));
260 
261   std::string osdd_file_name("simple_open_search.xml");
262   StartDownload(keyword, osdd_file_name,
263                 TemplateURLFetcher::EXPLICIT_PROVIDER, true);
264   ASSERT_EQ(0, add_provider_called());
265   ASSERT_EQ(0, callbacks_destroyed());
266 
267   WaitForDownloadToFinish();
268   ASSERT_EQ(1, add_provider_called());
269   ASSERT_EQ(1, callbacks_destroyed());
270 
271   ASSERT_TRUE(last_callback_template_url());
272   EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
273             last_callback_template_url()->url_ref().DisplayURL(
274                 test_util()->model()->search_terms_data()));
275   EXPECT_EQ(ASCIIToUTF16("example.com"),
276             last_callback_template_url()->keyword());
277   EXPECT_FALSE(last_callback_template_url()->safe_for_autoreplace());
278 }
279 
TEST_F(TemplateURLFetcherTest,DuplicateKeywordsTest)280 TEST_F(TemplateURLFetcherTest, DuplicateKeywordsTest) {
281   base::string16 keyword(ASCIIToUTF16("test"));
282   TemplateURLData data;
283   data.short_name = keyword;
284   data.SetKeyword(keyword);
285   data.SetURL("http://example.com/");
286   test_util()->model()->Add(new TemplateURL(data));
287   test_util()->ChangeModelToLoadState();
288 
289   ASSERT_TRUE(test_util()->model()->GetTemplateURLForKeyword(keyword));
290 
291   // This should bail because the keyword already exists.
292   std::string osdd_file_name("simple_open_search.xml");
293   StartDownload(keyword, osdd_file_name,
294                 TemplateURLFetcher::AUTODETECTED_PROVIDER, true);
295   ASSERT_EQ(0, add_provider_called());
296   ASSERT_EQ(1, callbacks_destroyed());
297   ASSERT_FALSE(last_callback_template_url());
298 }
299 
TEST_F(TemplateURLFetcherTest,DuplicateDownloadTest)300 TEST_F(TemplateURLFetcherTest, DuplicateDownloadTest) {
301   base::string16 keyword(ASCIIToUTF16("test"));
302   std::string osdd_file_name("simple_open_search.xml");
303   StartDownload(keyword, osdd_file_name,
304                 TemplateURLFetcher::EXPLICIT_PROVIDER, true);
305   ASSERT_EQ(0, add_provider_called());
306   ASSERT_EQ(0, callbacks_destroyed());
307 
308   // This should bail because the keyword already has a pending download.
309   StartDownload(keyword, osdd_file_name,
310                 TemplateURLFetcher::EXPLICIT_PROVIDER, true);
311   ASSERT_EQ(0, add_provider_called());
312   ASSERT_EQ(1, callbacks_destroyed());
313 
314   WaitForDownloadToFinish();
315   ASSERT_EQ(1, add_provider_called());
316   ASSERT_EQ(2, callbacks_destroyed());
317   ASSERT_TRUE(last_callback_template_url());
318 }
319