1 // Copyright (c) 2011 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.h" 8 #include "base/path_service.h" 9 #include "base/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_model.h" 14 #include "chrome/browser/search_engines/template_url_model_test_util.h" 15 #include "chrome/common/chrome_paths.h" 16 #include "chrome/test/testing_profile.h" 17 #include "googleurl/src/gurl.h" 18 #include "net/test/test_server.h" 19 #include "testing/gtest/include/gtest/gtest.h" 20 21 class TemplateURLFetcherTest; 22 23 // Handles callbacks from TemplateURLFetcher. 24 class TemplateURLFetcherTestCallbacks : public TemplateURLFetcherCallbacks { 25 public: 26 explicit TemplateURLFetcherTestCallbacks(TemplateURLFetcherTest* test) 27 : test_(test) { 28 } 29 virtual ~TemplateURLFetcherTestCallbacks(); 30 31 // TemplateURLFetcherCallbacks implementation. 32 virtual void ConfirmSetDefaultSearchProvider( 33 TemplateURL* template_url, 34 TemplateURLModel* template_url_model); 35 virtual void ConfirmAddSearchProvider( 36 TemplateURL* template_url, 37 Profile* profile); 38 39 private: 40 TemplateURLFetcherTest* test_; 41 42 DISALLOW_COPY_AND_ASSIGN(TemplateURLFetcherTestCallbacks); 43 }; 44 45 // Basic set-up for TemplateURLFetcher tests. 46 class TemplateURLFetcherTest : public testing::Test { 47 public: 48 TemplateURLFetcherTest(); 49 50 virtual void SetUp() { 51 test_util_.SetUp(); 52 test_util_.StartIOThread(); 53 ASSERT_TRUE(test_util_.profile()); 54 test_util_.profile()->CreateTemplateURLFetcher(); 55 ASSERT_TRUE(test_util_.profile()->GetTemplateURLFetcher()); 56 57 test_util_.profile()->CreateRequestContext(); 58 ASSERT_TRUE(test_util_.profile()->GetRequestContext()); 59 ASSERT_TRUE(test_server_.Start()); 60 } 61 62 virtual void TearDown() { 63 test_util_.TearDown(); 64 } 65 66 // Called by ~TemplateURLFetcherTestCallbacks. 67 void DestroyedCallback(TemplateURLFetcherTestCallbacks* callbacks); 68 69 // TemplateURLFetcherCallbacks implementation. (Although not derived from 70 // this class, these methods handle those calls for the test.) 71 virtual void ConfirmSetDefaultSearchProvider( 72 TemplateURL* template_url, 73 TemplateURLModel* template_url_model); 74 virtual void ConfirmAddSearchProvider( 75 TemplateURL* template_url, 76 Profile* profile); 77 78 protected: 79 // Schedules the download of the url. 80 void StartDownload(const string16& keyword, 81 const std::string& osdd_file_name, 82 TemplateURLFetcher::ProviderType provider_type, 83 bool check_that_file_exists); 84 85 // Waits for any downloads to finish. 86 void WaitForDownloadToFinish(); 87 88 TemplateURLModelTestUtil test_util_; 89 net::TestServer test_server_; 90 91 // The last TemplateURL to come from a callback. 92 scoped_ptr<TemplateURL> last_callback_template_url_; 93 94 // How many TemplateURLFetcherTestCallbacks have been destructed. 95 int callbacks_destroyed_; 96 97 // How many times ConfirmSetDefaultSearchProvider has been called. 98 int set_default_called_; 99 100 // How many times ConfirmAddSearchProvider has been called. 101 int add_provider_called_; 102 103 // Is the code in WaitForDownloadToFinish in a message loop waiting for a 104 // callback to finish? 105 bool waiting_for_download_; 106 107 private: 108 DISALLOW_COPY_AND_ASSIGN(TemplateURLFetcherTest); 109 }; 110 111 TemplateURLFetcherTestCallbacks::~TemplateURLFetcherTestCallbacks() { 112 test_->DestroyedCallback(this); 113 } 114 115 void TemplateURLFetcherTestCallbacks::ConfirmSetDefaultSearchProvider( 116 TemplateURL* template_url, 117 TemplateURLModel* template_url_model) { 118 test_->ConfirmSetDefaultSearchProvider(template_url, template_url_model); 119 } 120 121 void TemplateURLFetcherTestCallbacks::ConfirmAddSearchProvider( 122 TemplateURL* template_url, 123 Profile* profile) { 124 test_->ConfirmAddSearchProvider(template_url, profile); 125 } 126 127 TemplateURLFetcherTest::TemplateURLFetcherTest() 128 : test_server_(net::TestServer::TYPE_HTTP, 129 FilePath(FILE_PATH_LITERAL("chrome/test/data"))), 130 callbacks_destroyed_(0), 131 set_default_called_(0), 132 add_provider_called_(0), 133 waiting_for_download_(false) { 134 } 135 136 void TemplateURLFetcherTest::DestroyedCallback( 137 TemplateURLFetcherTestCallbacks* callbacks) { 138 callbacks_destroyed_++; 139 if (waiting_for_download_) 140 MessageLoop::current()->Quit(); 141 } 142 143 void TemplateURLFetcherTest::ConfirmSetDefaultSearchProvider( 144 TemplateURL* template_url, 145 TemplateURLModel* template_url_model) { 146 last_callback_template_url_.reset(template_url); 147 set_default_called_++; 148 } 149 150 void TemplateURLFetcherTest::ConfirmAddSearchProvider( 151 TemplateURL* template_url, 152 Profile* profile) { 153 last_callback_template_url_.reset(template_url); 154 add_provider_called_++; 155 } 156 157 void TemplateURLFetcherTest::StartDownload( 158 const string16& keyword, 159 const std::string& osdd_file_name, 160 TemplateURLFetcher::ProviderType provider_type, 161 bool check_that_file_exists) { 162 163 if (check_that_file_exists) { 164 FilePath osdd_full_path; 165 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &osdd_full_path)); 166 osdd_full_path = osdd_full_path.AppendASCII(osdd_file_name); 167 ASSERT_TRUE(file_util::PathExists(osdd_full_path)); 168 ASSERT_FALSE(file_util::DirectoryExists(osdd_full_path)); 169 } 170 171 // Start the fetch. 172 GURL osdd_url = test_server_.GetURL("files/" + osdd_file_name); 173 GURL favicon_url; 174 test_util_.profile()->GetTemplateURLFetcher()->ScheduleDownload( 175 keyword, osdd_url, favicon_url, new TemplateURLFetcherTestCallbacks(this), 176 provider_type); 177 } 178 179 void TemplateURLFetcherTest::WaitForDownloadToFinish() { 180 ASSERT_FALSE(waiting_for_download_); 181 waiting_for_download_ = true; 182 MessageLoop::current()->Run(); 183 waiting_for_download_ = false; 184 } 185 186 TEST_F(TemplateURLFetcherTest, BasicAutodetectedTest) { 187 string16 keyword(ASCIIToUTF16("test")); 188 189 test_util_.ChangeModelToLoadState(); 190 ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword)); 191 192 std::string osdd_file_name("simple_open_search.xml"); 193 StartDownload(keyword, osdd_file_name, 194 TemplateURLFetcher::AUTODETECTED_PROVIDER, true); 195 ASSERT_EQ(0, set_default_called_); 196 ASSERT_EQ(0, add_provider_called_); 197 ASSERT_EQ(0, callbacks_destroyed_); 198 199 WaitForDownloadToFinish(); 200 ASSERT_EQ(0, set_default_called_); 201 ASSERT_EQ(0, add_provider_called_); 202 ASSERT_EQ(1, callbacks_destroyed_); 203 204 const TemplateURL* t_url = test_util_.model()->GetTemplateURLForKeyword( 205 keyword); 206 ASSERT_TRUE(t_url); 207 EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"), 208 t_url->url()->DisplayURL()); 209 EXPECT_TRUE(t_url->safe_for_autoreplace()); 210 } 211 212 TEST_F(TemplateURLFetcherTest, DuplicatesThrownAway) { 213 string16 keyword(ASCIIToUTF16("test")); 214 215 test_util_.ChangeModelToLoadState(); 216 ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword)); 217 218 std::string osdd_file_name("simple_open_search.xml"); 219 StartDownload(keyword, osdd_file_name, 220 TemplateURLFetcher::AUTODETECTED_PROVIDER, true); 221 ASSERT_EQ(0, set_default_called_); 222 ASSERT_EQ(0, add_provider_called_); 223 ASSERT_EQ(0, callbacks_destroyed_); 224 225 struct { 226 std::string description; 227 std::string osdd_file_name; 228 string16 keyword; 229 TemplateURLFetcher::ProviderType provider_type; 230 } test_cases[] = { 231 { "Duplicate keyword and osdd url with autodetected provider.", 232 osdd_file_name, keyword, TemplateURLFetcher::AUTODETECTED_PROVIDER }, 233 { "Duplicate keyword and osdd url with explicit provider.", 234 osdd_file_name, keyword, TemplateURLFetcher::EXPLICIT_PROVIDER }, 235 { "Duplicate osdd url with explicit provider.", 236 osdd_file_name, keyword + ASCIIToUTF16("1"), 237 TemplateURLFetcher::EXPLICIT_PROVIDER }, 238 { "Duplicate keyword with explicit provider.", 239 osdd_file_name + "1", keyword, TemplateURLFetcher::EXPLICIT_PROVIDER } 240 }; 241 242 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { 243 StartDownload(test_cases[i].keyword, test_cases[i].osdd_file_name, 244 test_cases[i].provider_type, false); 245 ASSERT_EQ( 246 1, 247 test_util_.profile()->GetTemplateURLFetcher()->requests_count()) << 248 test_cases[i].description; 249 ASSERT_EQ(i + 1, static_cast<size_t>(callbacks_destroyed_)); 250 } 251 252 WaitForDownloadToFinish(); 253 ASSERT_EQ(1 + ARRAYSIZE_UNSAFE(test_cases), 254 static_cast<size_t>(callbacks_destroyed_)); 255 ASSERT_EQ(0, set_default_called_); 256 ASSERT_EQ(0, add_provider_called_); 257 } 258 259 TEST_F(TemplateURLFetcherTest, BasicExplicitTest) { 260 string16 keyword(ASCIIToUTF16("test")); 261 262 test_util_.ChangeModelToLoadState(); 263 ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword)); 264 265 std::string osdd_file_name("simple_open_search.xml"); 266 StartDownload(keyword, osdd_file_name, 267 TemplateURLFetcher::EXPLICIT_PROVIDER, true); 268 ASSERT_EQ(0, set_default_called_); 269 ASSERT_EQ(0, add_provider_called_); 270 ASSERT_EQ(0, callbacks_destroyed_); 271 272 WaitForDownloadToFinish(); 273 ASSERT_EQ(0, set_default_called_); 274 ASSERT_EQ(1, add_provider_called_); 275 ASSERT_EQ(1, callbacks_destroyed_); 276 277 ASSERT_TRUE(last_callback_template_url_.get()); 278 EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"), 279 last_callback_template_url_->url()->DisplayURL()); 280 EXPECT_FALSE(last_callback_template_url_->safe_for_autoreplace()); 281 } 282 283 TEST_F(TemplateURLFetcherTest, BasicExplicitDefaultTest) { 284 string16 keyword(ASCIIToUTF16("test")); 285 286 test_util_.ChangeModelToLoadState(); 287 ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword)); 288 289 std::string osdd_file_name("simple_open_search.xml"); 290 StartDownload(keyword, osdd_file_name, 291 TemplateURLFetcher::EXPLICIT_DEFAULT_PROVIDER, true); 292 ASSERT_EQ(0, set_default_called_); 293 ASSERT_EQ(0, add_provider_called_); 294 ASSERT_EQ(0, callbacks_destroyed_); 295 296 WaitForDownloadToFinish(); 297 ASSERT_EQ(1, set_default_called_); 298 ASSERT_EQ(0, add_provider_called_); 299 ASSERT_EQ(1, callbacks_destroyed_); 300 301 ASSERT_TRUE(last_callback_template_url_.get()); 302 EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"), 303 last_callback_template_url_->url()->DisplayURL()); 304 EXPECT_FALSE(last_callback_template_url_->safe_for_autoreplace()); 305 } 306 307 TEST_F(TemplateURLFetcherTest, AutodetectedBeforeLoadTest) { 308 string16 keyword(ASCIIToUTF16("test")); 309 ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword)); 310 311 std::string osdd_file_name("simple_open_search.xml"); 312 StartDownload(keyword, osdd_file_name, 313 TemplateURLFetcher::AUTODETECTED_PROVIDER, true); 314 ASSERT_EQ(0, set_default_called_); 315 ASSERT_EQ(0, add_provider_called_); 316 ASSERT_EQ(1, callbacks_destroyed_); 317 } 318 319 TEST_F(TemplateURLFetcherTest, ExplicitBeforeLoadTest) { 320 string16 keyword(ASCIIToUTF16("test")); 321 ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword)); 322 323 std::string osdd_file_name("simple_open_search.xml"); 324 StartDownload(keyword, osdd_file_name, 325 TemplateURLFetcher::EXPLICIT_PROVIDER, true); 326 ASSERT_EQ(0, set_default_called_); 327 ASSERT_EQ(0, add_provider_called_); 328 ASSERT_EQ(1, callbacks_destroyed_); 329 } 330 331 TEST_F(TemplateURLFetcherTest, ExplicitDefaultBeforeLoadTest) { 332 string16 keyword(ASCIIToUTF16("test")); 333 ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword)); 334 335 std::string osdd_file_name("simple_open_search.xml"); 336 StartDownload(keyword, osdd_file_name, 337 TemplateURLFetcher::EXPLICIT_DEFAULT_PROVIDER, true); 338 ASSERT_EQ(0, set_default_called_); 339 ASSERT_EQ(0, add_provider_called_); 340 ASSERT_EQ(0, callbacks_destroyed_); 341 342 WaitForDownloadToFinish(); 343 ASSERT_EQ(1, set_default_called_); 344 ASSERT_EQ(0, add_provider_called_); 345 ASSERT_EQ(1, callbacks_destroyed_); 346 347 ASSERT_TRUE(last_callback_template_url_.get()); 348 EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"), 349 last_callback_template_url_->url()->DisplayURL()); 350 EXPECT_FALSE(last_callback_template_url_->safe_for_autoreplace()); 351 } 352 353 TEST_F(TemplateURLFetcherTest, DuplicateKeywordsTest) { 354 string16 keyword(ASCIIToUTF16("test")); 355 356 TemplateURL* t_url = new TemplateURL(); 357 t_url->SetURL("http://example.com/", 0, 0); 358 t_url->set_keyword(keyword); 359 t_url->set_short_name(keyword); 360 test_util_.model()->Add(t_url); 361 test_util_.ChangeModelToLoadState(); 362 363 ASSERT_TRUE(test_util_.model()->GetTemplateURLForKeyword(keyword)); 364 365 std::string osdd_file_name("simple_open_search.xml"); 366 StartDownload(keyword, osdd_file_name, 367 TemplateURLFetcher::AUTODETECTED_PROVIDER, true); 368 ASSERT_EQ(0, set_default_called_); 369 ASSERT_EQ(0, add_provider_called_); 370 ASSERT_EQ(1, callbacks_destroyed_); 371 372 StartDownload(keyword, osdd_file_name, 373 TemplateURLFetcher::EXPLICIT_PROVIDER, true); 374 ASSERT_EQ(0, set_default_called_); 375 ASSERT_EQ(0, add_provider_called_); 376 ASSERT_EQ(2, callbacks_destroyed_); 377 378 StartDownload(keyword, osdd_file_name, 379 TemplateURLFetcher::EXPLICIT_DEFAULT_PROVIDER, true); 380 ASSERT_EQ(0, set_default_called_); 381 ASSERT_EQ(0, add_provider_called_); 382 ASSERT_EQ(2, callbacks_destroyed_); 383 384 WaitForDownloadToFinish(); 385 ASSERT_EQ(1, set_default_called_); 386 ASSERT_EQ(0, add_provider_called_); 387 ASSERT_EQ(3, callbacks_destroyed_); 388 ASSERT_TRUE(last_callback_template_url_.get()); 389 ASSERT_NE(keyword, last_callback_template_url_->keyword()); 390 } 391