Home | History | Annotate | Download | only in search_engines
      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/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 "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 class TemplateURLFetcherTest;
     25 
     26 // Handles callbacks from TemplateURLFetcher.
     27 class TemplateURLFetcherTestCallbacks : public TemplateURLFetcherCallbacks {
     28  public:
     29   explicit TemplateURLFetcherTestCallbacks(TemplateURLFetcherTest* test)
     30       : test_(test) {
     31   }
     32   virtual ~TemplateURLFetcherTestCallbacks();
     33 
     34   // TemplateURLFetcherCallbacks implementation.
     35   virtual void ConfirmAddSearchProvider(TemplateURL* template_url,
     36                                         Profile* profile) OVERRIDE;
     37 
     38  private:
     39   TemplateURLFetcherTest* test_;
     40 
     41   DISALLOW_COPY_AND_ASSIGN(TemplateURLFetcherTestCallbacks);
     42 };
     43 
     44 // Basic set-up for TemplateURLFetcher tests.
     45 class TemplateURLFetcherTest : public testing::Test {
     46  public:
     47   TemplateURLFetcherTest();
     48 
     49   virtual void SetUp() OVERRIDE {
     50     test_util_.SetUp();
     51     TestingProfile* profile = test_util_.profile();
     52     ASSERT_TRUE(profile);
     53     ASSERT_TRUE(TemplateURLFetcherFactory::GetForProfile(profile));
     54 
     55     ASSERT_TRUE(profile->GetRequestContext());
     56     ASSERT_TRUE(test_server_.InitializeAndWaitUntilReady());
     57   }
     58 
     59   virtual void TearDown() OVERRIDE {
     60     ASSERT_TRUE(test_server_.ShutdownAndWaitUntilComplete());
     61     test_util_.TearDown();
     62   }
     63 
     64   // Called by ~TemplateURLFetcherTestCallbacks.
     65   void DestroyedCallback(TemplateURLFetcherTestCallbacks* callbacks);
     66 
     67   // TemplateURLFetcherCallbacks implementation.  (Although not derived from
     68   // this class, this method handles those calls for the test.)
     69   void ConfirmAddSearchProvider(TemplateURL* template_url, Profile* profile);
     70 
     71  protected:
     72   // Schedules the download of the url.
     73   void StartDownload(const base::string16& keyword,
     74                      const std::string& osdd_file_name,
     75                      TemplateURLFetcher::ProviderType provider_type,
     76                      bool check_that_file_exists);
     77 
     78   // Waits for any downloads to finish.
     79   void WaitForDownloadToFinish();
     80 
     81   TemplateURLServiceTestUtil test_util_;
     82   net::test_server::EmbeddedTestServer test_server_;
     83 
     84   // The last TemplateURL to come from a callback.
     85   scoped_ptr<TemplateURL> last_callback_template_url_;
     86 
     87   // How many TemplateURLFetcherTestCallbacks have been destructed.
     88   int callbacks_destroyed_;
     89 
     90   // How many times ConfirmAddSearchProvider has been called.
     91   int add_provider_called_;
     92 
     93   // Is the code in WaitForDownloadToFinish in a message loop waiting for a
     94   // callback to finish?
     95   bool waiting_for_download_;
     96 
     97  private:
     98   DISALLOW_COPY_AND_ASSIGN(TemplateURLFetcherTest);
     99 };
    100 
    101 TemplateURLFetcherTestCallbacks::~TemplateURLFetcherTestCallbacks() {
    102   test_->DestroyedCallback(this);
    103 }
    104 
    105 void TemplateURLFetcherTestCallbacks::ConfirmAddSearchProvider(
    106     TemplateURL* template_url,
    107     Profile* profile) {
    108   test_->ConfirmAddSearchProvider(template_url, profile);
    109 }
    110 
    111 TemplateURLFetcherTest::TemplateURLFetcherTest()
    112     : callbacks_destroyed_(0),
    113       add_provider_called_(0),
    114       waiting_for_download_(false) {
    115   base::FilePath src_dir;
    116   CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
    117   test_server_.ServeFilesFromDirectory(
    118       src_dir.AppendASCII("chrome/test/data"));
    119 }
    120 
    121 void TemplateURLFetcherTest::DestroyedCallback(
    122     TemplateURLFetcherTestCallbacks* callbacks) {
    123   callbacks_destroyed_++;
    124   if (waiting_for_download_)
    125     base::MessageLoop::current()->Quit();
    126 }
    127 
    128 void TemplateURLFetcherTest::ConfirmAddSearchProvider(
    129     TemplateURL* template_url,
    130     Profile* profile) {
    131   last_callback_template_url_.reset(template_url);
    132   add_provider_called_++;
    133 }
    134 
    135 void TemplateURLFetcherTest::StartDownload(
    136     const base::string16& keyword,
    137     const std::string& osdd_file_name,
    138     TemplateURLFetcher::ProviderType provider_type,
    139     bool check_that_file_exists) {
    140 
    141   if (check_that_file_exists) {
    142     base::FilePath osdd_full_path;
    143     ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &osdd_full_path));
    144     osdd_full_path = osdd_full_path.AppendASCII(osdd_file_name);
    145     ASSERT_TRUE(base::PathExists(osdd_full_path));
    146     ASSERT_FALSE(base::DirectoryExists(osdd_full_path));
    147   }
    148 
    149   // Start the fetch.
    150   GURL osdd_url = test_server_.GetURL("/" + osdd_file_name);
    151   GURL favicon_url;
    152   TemplateURLFetcherFactory::GetForProfile(
    153       test_util_.profile())->ScheduleDownload(
    154           keyword, osdd_url, favicon_url, NULL,
    155           new TemplateURLFetcherTestCallbacks(this), provider_type);
    156 }
    157 
    158 void TemplateURLFetcherTest::WaitForDownloadToFinish() {
    159   ASSERT_FALSE(waiting_for_download_);
    160   waiting_for_download_ = true;
    161   base::MessageLoop::current()->Run();
    162   waiting_for_download_ = false;
    163 }
    164 
    165 TEST_F(TemplateURLFetcherTest, BasicAutodetectedTest) {
    166   base::string16 keyword(ASCIIToUTF16("test"));
    167 
    168   test_util_.ChangeModelToLoadState();
    169   ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword));
    170 
    171   std::string osdd_file_name("simple_open_search.xml");
    172   StartDownload(keyword, osdd_file_name,
    173                 TemplateURLFetcher::AUTODETECTED_PROVIDER, true);
    174   ASSERT_EQ(0, add_provider_called_);
    175   ASSERT_EQ(0, callbacks_destroyed_);
    176 
    177   WaitForDownloadToFinish();
    178   ASSERT_EQ(0, add_provider_called_);
    179   ASSERT_EQ(1, callbacks_destroyed_);
    180 
    181   const TemplateURL* t_url = test_util_.model()->GetTemplateURLForKeyword(
    182       keyword);
    183   ASSERT_TRUE(t_url);
    184   EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
    185             t_url->url_ref().DisplayURL(
    186                 test_util_.model()->search_terms_data()));
    187   EXPECT_TRUE(t_url->safe_for_autoreplace());
    188 }
    189 
    190 TEST_F(TemplateURLFetcherTest, DuplicatesThrownAway) {
    191   base::string16 keyword(ASCIIToUTF16("test"));
    192 
    193   test_util_.ChangeModelToLoadState();
    194   ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword));
    195 
    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_);
    201 
    202   struct {
    203     std::string description;
    204     std::string osdd_file_name;
    205     base::string16 keyword;
    206     TemplateURLFetcher::ProviderType provider_type;
    207   } test_cases[] = {
    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 },
    215   };
    216 
    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);
    220     ASSERT_EQ(
    221         1,
    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_));
    226   }
    227 
    228   WaitForDownloadToFinish();
    229   ASSERT_EQ(1 + ARRAYSIZE_UNSAFE(test_cases),
    230             static_cast<size_t>(callbacks_destroyed_));
    231   ASSERT_EQ(0, add_provider_called_);
    232 }
    233 
    234 TEST_F(TemplateURLFetcherTest, BasicExplicitTest) {
    235   base::string16 keyword(ASCIIToUTF16("test"));
    236 
    237   test_util_.ChangeModelToLoadState();
    238   ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword));
    239 
    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_);
    245 
    246   WaitForDownloadToFinish();
    247   ASSERT_EQ(1, add_provider_called_);
    248   ASSERT_EQ(1, callbacks_destroyed_);
    249 
    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                 test_util_.model()->search_terms_data()));
    254   EXPECT_EQ(ASCIIToUTF16("example.com"),
    255             last_callback_template_url_->keyword());
    256   EXPECT_FALSE(last_callback_template_url_->safe_for_autoreplace());
    257 }
    258 
    259 TEST_F(TemplateURLFetcherTest, AutodetectedBeforeLoadTest) {
    260   base::string16 keyword(ASCIIToUTF16("test"));
    261   ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword));
    262 
    263   std::string osdd_file_name("simple_open_search.xml");
    264   StartDownload(keyword, osdd_file_name,
    265                 TemplateURLFetcher::AUTODETECTED_PROVIDER, true);
    266   ASSERT_EQ(0, add_provider_called_);
    267   ASSERT_EQ(1, callbacks_destroyed_);
    268 }
    269 
    270 TEST_F(TemplateURLFetcherTest, ExplicitBeforeLoadTest) {
    271   base::string16 keyword(ASCIIToUTF16("test"));
    272   ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword));
    273 
    274   std::string osdd_file_name("simple_open_search.xml");
    275   StartDownload(keyword, osdd_file_name,
    276                 TemplateURLFetcher::EXPLICIT_PROVIDER, true);
    277   ASSERT_EQ(0, add_provider_called_);
    278   ASSERT_EQ(0, callbacks_destroyed_);
    279 
    280   WaitForDownloadToFinish();
    281   ASSERT_EQ(1, add_provider_called_);
    282   ASSERT_EQ(1, callbacks_destroyed_);
    283 
    284   ASSERT_TRUE(last_callback_template_url_.get());
    285   EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
    286             last_callback_template_url_->url_ref().DisplayURL(
    287                 test_util_.model()->search_terms_data()));
    288   EXPECT_EQ(ASCIIToUTF16("example.com"),
    289             last_callback_template_url_->keyword());
    290   EXPECT_FALSE(last_callback_template_url_->safe_for_autoreplace());
    291 }
    292 
    293 TEST_F(TemplateURLFetcherTest, DuplicateKeywordsTest) {
    294   base::string16 keyword(ASCIIToUTF16("test"));
    295   TemplateURLData data;
    296   data.short_name = keyword;
    297   data.SetKeyword(keyword);
    298   data.SetURL("http://example.com/");
    299   test_util_.model()->Add(new TemplateURL(data));
    300   test_util_.ChangeModelToLoadState();
    301 
    302   ASSERT_TRUE(test_util_.model()->GetTemplateURLForKeyword(keyword));
    303 
    304   // This should bail because the keyword already exists.
    305   std::string osdd_file_name("simple_open_search.xml");
    306   StartDownload(keyword, osdd_file_name,
    307                 TemplateURLFetcher::AUTODETECTED_PROVIDER, true);
    308   ASSERT_EQ(0, add_provider_called_);
    309   ASSERT_EQ(1, callbacks_destroyed_);
    310   ASSERT_FALSE(last_callback_template_url_.get());
    311 }
    312 
    313 TEST_F(TemplateURLFetcherTest, DuplicateDownloadTest) {
    314   base::string16 keyword(ASCIIToUTF16("test"));
    315   std::string osdd_file_name("simple_open_search.xml");
    316   StartDownload(keyword, osdd_file_name,
    317                 TemplateURLFetcher::EXPLICIT_PROVIDER, true);
    318   ASSERT_EQ(0, add_provider_called_);
    319   ASSERT_EQ(0, callbacks_destroyed_);
    320 
    321   // This should bail because the keyword already has a pending download.
    322   StartDownload(keyword, osdd_file_name,
    323                 TemplateURLFetcher::EXPLICIT_PROVIDER, true);
    324   ASSERT_EQ(0, add_provider_called_);
    325   ASSERT_EQ(1, callbacks_destroyed_);
    326 
    327   WaitForDownloadToFinish();
    328   ASSERT_EQ(1, add_provider_called_);
    329   ASSERT_EQ(2, callbacks_destroyed_);
    330   ASSERT_TRUE(last_callback_template_url_.get());
    331 }
    332