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 <map> 6 7 #include "base/file_util.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/stl_util-inl.h" 10 #include "base/string_number_conversions.h" 11 #include "base/string_split.h" 12 #include "base/string_util.h" 13 #include "base/stringprintf.h" 14 #include "base/threading/thread.h" 15 #include "base/version.h" 16 #include "chrome/browser/extensions/extension_error_reporter.h" 17 #include "chrome/browser/extensions/extension_updater.h" 18 #include "chrome/browser/extensions/extension_service.h" 19 #include "chrome/browser/extensions/test_extension_prefs.h" 20 #include "chrome/browser/prefs/pref_service.h" 21 #include "chrome/common/extensions/extension.h" 22 #include "chrome/common/extensions/extension_constants.h" 23 #include "chrome/common/pref_names.h" 24 #include "chrome/common/net/test_url_fetcher_factory.h" 25 #include "chrome/test/testing_profile.h" 26 #include "content/browser/browser_thread.h" 27 #include "net/base/escape.h" 28 #include "net/base/load_flags.h" 29 #include "net/url_request/url_request_status.h" 30 #include "testing/gtest/include/gtest/gtest.h" 31 #include "libxml/globals.h" 32 33 using base::Time; 34 using base::TimeDelta; 35 36 namespace { 37 38 const char kEmptyUpdateUrlData[] = ""; 39 40 int expected_load_flags = 41 net::LOAD_DO_NOT_SEND_COOKIES | 42 net::LOAD_DO_NOT_SAVE_COOKIES | 43 net::LOAD_DISABLE_CACHE; 44 45 const ManifestFetchData::PingData kNeverPingedData( 46 ManifestFetchData::kNeverPinged, ManifestFetchData::kNeverPinged); 47 48 } // namespace 49 50 // Base class for further specialized test classes. 51 class MockService : public ExtensionServiceInterface { 52 public: 53 MockService() 54 : pending_extension_manager_(ALLOW_THIS_IN_INITIALIZER_LIST(*this)) {} 55 virtual ~MockService() {} 56 57 virtual const ExtensionList* extensions() const { 58 ADD_FAILURE(); 59 return NULL; 60 } 61 62 virtual const ExtensionList* disabled_extensions() const { 63 ADD_FAILURE(); 64 return NULL; 65 } 66 67 virtual void UpdateExtension(const std::string& id, 68 const FilePath& path, 69 const GURL& download_url) { 70 FAIL(); 71 } 72 73 virtual const Extension* GetExtensionById(const std::string& id, 74 bool include_disabled) const { 75 ADD_FAILURE(); 76 return NULL; 77 } 78 79 virtual bool UninstallExtension(const std::string& extension_id, 80 bool external_uninstall, 81 std::string* error) { 82 ADD_FAILURE(); 83 return false; 84 } 85 86 virtual bool IsExtensionEnabled(const std::string& extension_id) const { 87 ADD_FAILURE(); 88 return false; 89 } 90 91 virtual bool IsExternalExtensionUninstalled( 92 const std::string& extension_id) const { 93 ADD_FAILURE(); 94 return false; 95 } 96 97 virtual void EnableExtension(const std::string& extension_id) { 98 FAIL(); 99 } 100 101 virtual void DisableExtension(const std::string& extension_id) { 102 FAIL(); 103 } 104 105 106 virtual void UpdateExtensionBlacklist( 107 const std::vector<std::string>& blacklist) { 108 FAIL(); 109 } 110 111 virtual void CheckAdminBlacklist() { 112 FAIL(); 113 } 114 115 virtual bool IsIncognitoEnabled(const std::string& id) const { 116 ADD_FAILURE(); 117 return false; 118 } 119 120 virtual void SetIsIncognitoEnabled(const std::string& id, 121 bool enabled) { 122 FAIL(); 123 } 124 125 virtual void CheckForUpdatesSoon() { 126 FAIL(); 127 } 128 129 virtual PendingExtensionManager* pending_extension_manager() { 130 ADD_FAILURE() << "Subclass should override this if it will " 131 << "be accessed by a test."; 132 return &pending_extension_manager_; 133 } 134 135 virtual void ProcessSyncData( 136 const ExtensionSyncData& extension_sync_data, 137 PendingExtensionInfo::ShouldAllowInstallPredicate 138 should_allow_install) { 139 FAIL(); 140 } 141 142 Profile* profile() { return &profile_; } 143 144 ExtensionPrefs* extension_prefs() { return prefs_.prefs(); } 145 146 PrefService* pref_service() { return prefs_.pref_service(); } 147 148 // Creates test extensions and inserts them into list. The name and 149 // version are all based on their index. If |update_url| is non-null, it 150 // will be used as the update_url for each extension. 151 // The |id| is used to distinguish extension names and make sure that 152 // no two extensions share the same name. 153 void CreateTestExtensions(int id, int count, ExtensionList *list, 154 const std::string* update_url, 155 Extension::Location location) { 156 for (int i = 1; i <= count; i++) { 157 DictionaryValue manifest; 158 manifest.SetString(extension_manifest_keys::kVersion, 159 base::StringPrintf("%d.0.0.0", i)); 160 manifest.SetString(extension_manifest_keys::kName, 161 base::StringPrintf("Extension %d.%d", id, i)); 162 if (update_url) 163 manifest.SetString(extension_manifest_keys::kUpdateURL, *update_url); 164 scoped_refptr<Extension> e = 165 prefs_.AddExtensionWithManifest(manifest, location); 166 ASSERT_TRUE(e != NULL); 167 list->push_back(e); 168 } 169 } 170 171 protected: 172 PendingExtensionManager pending_extension_manager_; 173 TestExtensionPrefs prefs_; 174 TestingProfile profile_; 175 176 private: 177 DISALLOW_COPY_AND_ASSIGN(MockService); 178 }; 179 180 181 std::string GenerateId(std::string input) { 182 std::string result; 183 EXPECT_TRUE(Extension::GenerateId(input, &result)); 184 return result; 185 } 186 187 bool ShouldInstallExtensionsOnly(const Extension& extension) { 188 return extension.GetType() == Extension::TYPE_EXTENSION; 189 } 190 191 bool ShouldInstallThemesOnly(const Extension& extension) { 192 return extension.is_theme(); 193 } 194 195 bool ShouldAlwaysInstall(const Extension& extension) { 196 return true; 197 } 198 199 // Loads some pending extension records into a pending extension manager. 200 void SetupPendingExtensionManagerForTest( 201 int count, 202 const GURL& update_url, 203 PendingExtensionManager* pending_extension_manager) { 204 for (int i = 1; i <= count; i++) { 205 PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install = 206 (i % 2 == 0) ? &ShouldInstallThemesOnly : &ShouldInstallExtensionsOnly; 207 const bool kIsFromSync = true; 208 const bool kInstallSilently = true; 209 const Extension::State kInitialState = Extension::ENABLED; 210 const bool kInitialIncognitoEnabled = false; 211 std::string id = GenerateId(base::StringPrintf("extension%i", i)); 212 213 pending_extension_manager->AddForTesting( 214 id, 215 PendingExtensionInfo(update_url, 216 should_allow_install, 217 kIsFromSync, 218 kInstallSilently, 219 kInitialState, 220 kInitialIncognitoEnabled, 221 Extension::INTERNAL)); 222 } 223 } 224 225 class ServiceForManifestTests : public MockService { 226 public: 227 ServiceForManifestTests() {} 228 229 virtual ~ServiceForManifestTests() {} 230 231 virtual const Extension* GetExtensionById(const std::string& id, 232 bool include_disabled) const { 233 for (ExtensionList::const_iterator iter = extensions_.begin(); 234 iter != extensions_.end(); ++iter) { 235 if ((*iter)->id() == id) { 236 return *iter; 237 } 238 } 239 return NULL; 240 } 241 242 virtual const ExtensionList* extensions() const { return &extensions_; } 243 244 virtual PendingExtensionManager* pending_extension_manager() { 245 return &pending_extension_manager_; 246 } 247 248 void set_extensions(ExtensionList extensions) { 249 extensions_ = extensions; 250 } 251 252 private: 253 ExtensionList extensions_; 254 }; 255 256 class ServiceForDownloadTests : public MockService { 257 public: 258 virtual void UpdateExtension(const std::string& id, 259 const FilePath& extension_path, 260 const GURL& download_url) { 261 extension_id_ = id; 262 install_path_ = extension_path; 263 download_url_ = download_url; 264 } 265 266 virtual PendingExtensionManager* pending_extension_manager() { 267 return &pending_extension_manager_; 268 } 269 270 virtual const Extension* GetExtensionById(const std::string& id, bool) const { 271 last_inquired_extension_id_ = id; 272 return NULL; 273 } 274 275 const std::string& extension_id() const { return extension_id_; } 276 const FilePath& install_path() const { return install_path_; } 277 const GURL& download_url() const { return download_url_; } 278 const std::string& last_inquired_extension_id() const { 279 return last_inquired_extension_id_; 280 } 281 282 private: 283 std::string extension_id_; 284 FilePath install_path_; 285 GURL download_url_; 286 287 // The last extension ID that GetExtensionById was called with. 288 // Mutable because the method that sets it (GetExtensionById) is const 289 // in the actual extension service, but must record the last extension 290 // ID in this test class. 291 mutable std::string last_inquired_extension_id_; 292 }; 293 294 class ServiceForBlacklistTests : public MockService { 295 public: 296 ServiceForBlacklistTests() 297 : MockService(), 298 processed_blacklist_(false) { 299 } 300 virtual void UpdateExtensionBlacklist( 301 const std::vector<std::string>& blacklist) { 302 processed_blacklist_ = true; 303 return; 304 } 305 bool processed_blacklist() { return processed_blacklist_; } 306 const std::string& extension_id() { return extension_id_; } 307 308 private: 309 bool processed_blacklist_; 310 std::string extension_id_; 311 FilePath install_path_; 312 }; 313 314 static const int kUpdateFrequencySecs = 15; 315 316 // Takes a string with KEY=VALUE parameters separated by '&' in |params| and 317 // puts the key/value pairs into |result|. For keys with no value, the empty 318 // string is used. So for "a=1&b=foo&c", result would map "a" to "1", "b" to 319 // "foo", and "c" to "". 320 static void ExtractParameters(const std::string& params, 321 std::map<std::string, std::string>* result) { 322 std::vector<std::string> pairs; 323 base::SplitString(params, '&', &pairs); 324 for (size_t i = 0; i < pairs.size(); i++) { 325 std::vector<std::string> key_val; 326 base::SplitString(pairs[i], '=', &key_val); 327 if (!key_val.empty()) { 328 std::string key = key_val[0]; 329 EXPECT_TRUE(result->find(key) == result->end()); 330 (*result)[key] = (key_val.size() == 2) ? key_val[1] : ""; 331 } else { 332 NOTREACHED(); 333 } 334 } 335 } 336 337 // All of our tests that need to use private APIs of ExtensionUpdater live 338 // inside this class (which is a friend to ExtensionUpdater). 339 class ExtensionUpdaterTest : public testing::Test { 340 public: 341 static void SimulateTimerFired(ExtensionUpdater* updater) { 342 EXPECT_TRUE(updater->timer_.IsRunning()); 343 updater->timer_.Stop(); 344 updater->TimerFired(); 345 } 346 347 static void SimulateCheckSoon(const ExtensionUpdater& updater, 348 MessageLoop* message_loop) { 349 EXPECT_TRUE(updater.will_check_soon_); 350 message_loop->RunAllPending(); 351 } 352 353 // Adds a Result with the given data to results. 354 static void AddParseResult( 355 const std::string& id, 356 const std::string& version, 357 const std::string& url, 358 UpdateManifest::Results* results) { 359 UpdateManifest::Result result; 360 result.extension_id = id; 361 result.version = version; 362 result.crx_url = GURL(url); 363 results->list.push_back(result); 364 } 365 366 static void TestExtensionUpdateCheckRequests(bool pending) { 367 MessageLoop message_loop; 368 BrowserThread ui_thread(BrowserThread::UI, &message_loop); 369 BrowserThread file_thread(BrowserThread::FILE, &message_loop); 370 BrowserThread io_thread(BrowserThread::IO); 371 io_thread.Start(); 372 373 // Create an extension with an update_url. 374 ServiceForManifestTests service; 375 std::string update_url("http://foo.com/bar"); 376 ExtensionList extensions; 377 PendingExtensionManager* pending_extension_manager = 378 service.pending_extension_manager(); 379 if (pending) { 380 SetupPendingExtensionManagerForTest(1, GURL(update_url), 381 pending_extension_manager); 382 } else { 383 service.CreateTestExtensions(1, 1, &extensions, &update_url, 384 Extension::INTERNAL); 385 service.set_extensions(extensions); 386 } 387 388 // Set up and start the updater. 389 TestURLFetcherFactory factory; 390 URLFetcher::set_factory(&factory); 391 ExtensionUpdater updater( 392 &service, service.extension_prefs(), service.pref_service(), 393 service.profile(), 60*60*24); 394 updater.Start(); 395 // Disable blacklist checks (tested elsewhere) so that we only see the 396 // update HTTP request. 397 updater.set_blacklist_checks_enabled(false); 398 399 // Tell the update that it's time to do update checks. 400 SimulateTimerFired(&updater); 401 402 // Get the url our mock fetcher was asked to fetch. 403 TestURLFetcher* fetcher = 404 factory.GetFetcherByID(ExtensionUpdater::kManifestFetcherId); 405 const GURL& url = fetcher->original_url(); 406 EXPECT_FALSE(url.is_empty()); 407 EXPECT_TRUE(url.is_valid()); 408 EXPECT_TRUE(url.SchemeIs("http")); 409 EXPECT_EQ("foo.com", url.host()); 410 EXPECT_EQ("/bar", url.path()); 411 412 // Validate the extension request parameters in the query. It should 413 // look something like "?x=id%3D<id>%26v%3D<version>%26uc". 414 EXPECT_TRUE(url.has_query()); 415 std::vector<std::string> parts; 416 base::SplitString(url.query(), '=', &parts); 417 EXPECT_EQ(2u, parts.size()); 418 EXPECT_EQ("x", parts[0]); 419 std::string decoded = UnescapeURLComponent(parts[1], 420 UnescapeRule::URL_SPECIAL_CHARS); 421 std::map<std::string, std::string> params; 422 ExtractParameters(decoded, ¶ms); 423 if (pending) { 424 EXPECT_EQ(pending_extension_manager->begin()->first, params["id"]); 425 EXPECT_EQ("0.0.0.0", params["v"]); 426 } else { 427 EXPECT_EQ(extensions[0]->id(), params["id"]); 428 EXPECT_EQ(extensions[0]->VersionString(), params["v"]); 429 } 430 EXPECT_EQ("", params["uc"]); 431 } 432 433 static void TestBlacklistUpdateCheckRequests() { 434 ServiceForManifestTests service; 435 436 // Setup and start the updater. 437 MessageLoop message_loop; 438 BrowserThread ui_thread(BrowserThread::UI, &message_loop); 439 BrowserThread io_thread(BrowserThread::IO); 440 io_thread.Start(); 441 442 TestURLFetcherFactory factory; 443 URLFetcher::set_factory(&factory); 444 ExtensionUpdater updater( 445 &service, service.extension_prefs(), service.pref_service(), 446 service.profile(), 60*60*24); 447 updater.Start(); 448 449 // Tell the updater that it's time to do update checks. 450 SimulateTimerFired(&updater); 451 452 // Get the url our mock fetcher was asked to fetch. 453 TestURLFetcher* fetcher = 454 factory.GetFetcherByID(ExtensionUpdater::kManifestFetcherId); 455 ASSERT_FALSE(fetcher == NULL); 456 const GURL& url = fetcher->original_url(); 457 458 EXPECT_FALSE(url.is_empty()); 459 EXPECT_TRUE(url.is_valid()); 460 EXPECT_TRUE(url.SchemeIs("https")); 461 EXPECT_EQ("clients2.google.com", url.host()); 462 EXPECT_EQ("/service/update2/crx", url.path()); 463 464 // Validate the extension request parameters in the query. It should 465 // look something like "?x=id%3D<id>%26v%3D<version>%26uc". 466 EXPECT_TRUE(url.has_query()); 467 std::vector<std::string> parts; 468 base::SplitString(url.query(), '=', &parts); 469 EXPECT_EQ(2u, parts.size()); 470 EXPECT_EQ("x", parts[0]); 471 std::string decoded = UnescapeURLComponent(parts[1], 472 UnescapeRule::URL_SPECIAL_CHARS); 473 std::map<std::string, std::string> params; 474 ExtractParameters(decoded, ¶ms); 475 EXPECT_EQ("com.google.crx.blacklist", params["id"]); 476 EXPECT_EQ("0", params["v"]); 477 EXPECT_EQ("", params["uc"]); 478 EXPECT_TRUE(ContainsKey(params, "ping")); 479 } 480 481 static void TestUpdateUrlDataEmpty() { 482 const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 483 const std::string version = "1.0"; 484 485 // Make sure that an empty update URL data string does not cause a ap= 486 // option to appear in the x= parameter. 487 ManifestFetchData fetch_data(GURL("http://localhost/foo")); 488 fetch_data.AddExtension(id, version, 489 kNeverPingedData, ""); 490 EXPECT_EQ("http://localhost/foo\?x=id%3Daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 491 "%26v%3D1.0%26uc", 492 fetch_data.full_url().spec()); 493 } 494 495 static void TestUpdateUrlDataSimple() { 496 const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 497 const std::string version = "1.0"; 498 499 // Make sure that an update URL data string causes an appropriate ap= 500 // option to appear in the x= parameter. 501 ManifestFetchData fetch_data(GURL("http://localhost/foo")); 502 fetch_data.AddExtension(id, version, 503 kNeverPingedData, "bar"); 504 EXPECT_EQ("http://localhost/foo\?x=id%3Daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 505 "%26v%3D1.0%26uc%26ap%3Dbar", 506 fetch_data.full_url().spec()); 507 } 508 509 static void TestUpdateUrlDataCompound() { 510 const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 511 const std::string version = "1.0"; 512 513 // Make sure that an update URL data string causes an appropriate ap= 514 // option to appear in the x= parameter. 515 ManifestFetchData fetch_data(GURL("http://localhost/foo")); 516 fetch_data.AddExtension(id, version, 517 kNeverPingedData, "a=1&b=2&c"); 518 EXPECT_EQ("http://localhost/foo\?x=id%3Daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 519 "%26v%3D1.0%26uc%26ap%3Da%253D1%2526b%253D2%2526c", 520 fetch_data.full_url().spec()); 521 } 522 523 static void TestUpdateUrlDataFromGallery(const std::string& gallery_url) { 524 MockService service; 525 ManifestFetchesBuilder builder(&service, service.extension_prefs()); 526 ExtensionList extensions; 527 std::string url(gallery_url); 528 529 service.CreateTestExtensions(1, 1, &extensions, &url, Extension::INTERNAL); 530 builder.AddExtension(*extensions[0]); 531 std::vector<ManifestFetchData*> fetches = builder.GetFetches(); 532 EXPECT_EQ(1u, fetches.size()); 533 scoped_ptr<ManifestFetchData> fetch(fetches[0]); 534 fetches.clear(); 535 536 // Make sure that extensions that update from the gallery ignore any 537 // update URL data. 538 const std::string& update_url = fetch->full_url().spec(); 539 std::string::size_type x = update_url.find("x="); 540 EXPECT_NE(std::string::npos, x); 541 std::string::size_type ap = update_url.find("ap%3D", x); 542 EXPECT_EQ(std::string::npos, ap); 543 } 544 545 static void TestDetermineUpdates() { 546 MessageLoop message_loop; 547 BrowserThread ui_thread(BrowserThread::UI, &message_loop); 548 BrowserThread file_thread(BrowserThread::FILE, &message_loop); 549 550 // Create a set of test extensions 551 ServiceForManifestTests service; 552 ExtensionList tmp; 553 service.CreateTestExtensions(1, 3, &tmp, NULL, Extension::INTERNAL); 554 service.set_extensions(tmp); 555 556 ExtensionUpdater updater( 557 &service, service.extension_prefs(), service.pref_service(), 558 service.profile(), kUpdateFrequencySecs); 559 updater.Start(); 560 561 // Check passing an empty list of parse results to DetermineUpdates 562 ManifestFetchData fetch_data(GURL("http://localhost/foo")); 563 UpdateManifest::Results updates; 564 std::vector<int> updateable = updater.DetermineUpdates(fetch_data, 565 updates); 566 EXPECT_TRUE(updateable.empty()); 567 568 // Create two updates - expect that DetermineUpdates will return the first 569 // one (v1.0 installed, v1.1 available) but not the second one (both 570 // installed and available at v2.0). 571 scoped_ptr<Version> one(Version::GetVersionFromString("1.0")); 572 EXPECT_TRUE(tmp[0]->version()->Equals(*one)); 573 fetch_data.AddExtension(tmp[0]->id(), tmp[0]->VersionString(), 574 kNeverPingedData, 575 kEmptyUpdateUrlData); 576 AddParseResult(tmp[0]->id(), 577 "1.1", "http://localhost/e1_1.1.crx", &updates); 578 fetch_data.AddExtension(tmp[1]->id(), tmp[1]->VersionString(), 579 kNeverPingedData, 580 kEmptyUpdateUrlData); 581 AddParseResult(tmp[1]->id(), 582 tmp[1]->VersionString(), "http://localhost/e2_2.0.crx", &updates); 583 updateable = updater.DetermineUpdates(fetch_data, updates); 584 EXPECT_EQ(1u, updateable.size()); 585 EXPECT_EQ(0, updateable[0]); 586 } 587 588 static void TestDetermineUpdatesPending() { 589 // Create a set of test extensions 590 ServiceForManifestTests service; 591 PendingExtensionManager* pending_extension_manager = 592 service.pending_extension_manager(); 593 SetupPendingExtensionManagerForTest(3, GURL(), pending_extension_manager); 594 595 MessageLoop message_loop; 596 BrowserThread ui_thread(BrowserThread::UI, &message_loop); 597 ExtensionUpdater updater( 598 &service, service.extension_prefs(), service.pref_service(), 599 service.profile(), kUpdateFrequencySecs); 600 updater.Start(); 601 602 ManifestFetchData fetch_data(GURL("http://localhost/foo")); 603 UpdateManifest::Results updates; 604 PendingExtensionManager::const_iterator it; 605 for (it = pending_extension_manager->begin(); 606 it != pending_extension_manager->end(); ++it) { 607 fetch_data.AddExtension(it->first, "1.0.0.0", 608 kNeverPingedData, 609 kEmptyUpdateUrlData); 610 AddParseResult(it->first, 611 "1.1", "http://localhost/e1_1.1.crx", &updates); 612 } 613 std::vector<int> updateable = 614 updater.DetermineUpdates(fetch_data, updates); 615 // All the apps should be updateable. 616 EXPECT_EQ(3u, updateable.size()); 617 for (std::vector<int>::size_type i = 0; i < updateable.size(); ++i) { 618 EXPECT_EQ(static_cast<int>(i), updateable[i]); 619 } 620 } 621 622 static void TestMultipleManifestDownloading() { 623 MessageLoop ui_loop; 624 BrowserThread ui_thread(BrowserThread::UI, &ui_loop); 625 BrowserThread file_thread(BrowserThread::FILE); 626 file_thread.Start(); 627 BrowserThread io_thread(BrowserThread::IO); 628 io_thread.Start(); 629 630 TestURLFetcherFactory factory; 631 TestURLFetcher* fetcher = NULL; 632 URLFetcher::set_factory(&factory); 633 scoped_ptr<ServiceForDownloadTests> service(new ServiceForDownloadTests); 634 ExtensionUpdater updater(service.get(), service->extension_prefs(), 635 service->pref_service(), 636 service->profile(), 637 kUpdateFrequencySecs); 638 updater.Start(); 639 640 GURL url1("http://localhost/manifest1"); 641 GURL url2("http://localhost/manifest2"); 642 643 // Request 2 update checks - the first should begin immediately and the 644 // second one should be queued up. 645 ManifestFetchData* fetch1 = new ManifestFetchData(url1); 646 ManifestFetchData* fetch2 = new ManifestFetchData(url2); 647 ManifestFetchData::PingData zeroDays(0, 0); 648 fetch1->AddExtension("1111", "1.0", zeroDays, kEmptyUpdateUrlData); 649 fetch2->AddExtension("12345", "2.0", kNeverPingedData, 650 kEmptyUpdateUrlData); 651 updater.StartUpdateCheck(fetch1); 652 updater.StartUpdateCheck(fetch2); 653 654 std::string invalid_xml = "invalid xml"; 655 fetcher = factory.GetFetcherByID(ExtensionUpdater::kManifestFetcherId); 656 EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL); 657 EXPECT_TRUE(fetcher->load_flags() == expected_load_flags); 658 fetcher->delegate()->OnURLFetchComplete( 659 fetcher, url1, net::URLRequestStatus(), 200, ResponseCookies(), 660 invalid_xml); 661 662 // Now that the first request is complete, make sure the second one has 663 // been started. 664 const std::string kValidXml = 665 "<?xml version='1.0' encoding='UTF-8'?>" 666 "<gupdate xmlns='http://www.google.com/update2/response'" 667 " protocol='2.0'>" 668 " <app appid='12345'>" 669 " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx'" 670 " version='1.2.3.4' prodversionmin='2.0.143.0' />" 671 " </app>" 672 "</gupdate>"; 673 fetcher = factory.GetFetcherByID(ExtensionUpdater::kManifestFetcherId); 674 EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL); 675 EXPECT_TRUE(fetcher->load_flags() == expected_load_flags); 676 fetcher->delegate()->OnURLFetchComplete( 677 fetcher, url2, net::URLRequestStatus(), 200, ResponseCookies(), 678 kValidXml); 679 680 // This should run the manifest parsing, then we want to make sure that our 681 // service was called with GetExtensionById with the matching id from 682 // kValidXml. 683 file_thread.Stop(); 684 io_thread.Stop(); 685 ui_loop.RunAllPending(); 686 EXPECT_EQ("12345", service->last_inquired_extension_id()); 687 xmlCleanupGlobals(); 688 689 // The FILE thread is needed for |service|'s cleanup, 690 // because of ImportantFileWriter. 691 file_thread.Start(); 692 service.reset(); 693 } 694 695 static void TestSingleExtensionDownloading(bool pending) { 696 MessageLoop ui_loop; 697 BrowserThread ui_thread(BrowserThread::UI, &ui_loop); 698 BrowserThread file_thread(BrowserThread::FILE); 699 file_thread.Start(); 700 BrowserThread io_thread(BrowserThread::IO); 701 io_thread.Start(); 702 703 TestURLFetcherFactory factory; 704 TestURLFetcher* fetcher = NULL; 705 URLFetcher::set_factory(&factory); 706 scoped_ptr<ServiceForDownloadTests> service(new ServiceForDownloadTests); 707 ExtensionUpdater updater(service.get(), service->extension_prefs(), 708 service->pref_service(), 709 service->profile(), 710 kUpdateFrequencySecs); 711 updater.Start(); 712 713 GURL test_url("http://localhost/extension.crx"); 714 715 std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 716 std::string hash = ""; 717 scoped_ptr<Version> version(Version::GetVersionFromString("0.0.1")); 718 ASSERT_TRUE(version.get()); 719 updater.FetchUpdatedExtension(id, test_url, hash, version->GetString()); 720 721 if (pending) { 722 const bool kIsFromSync = true; 723 const bool kInstallSilently = true; 724 const Extension::State kInitialState = Extension::ENABLED; 725 const bool kInitialIncognitoEnabled = false; 726 PendingExtensionManager* pending_extension_manager = 727 service->pending_extension_manager(); 728 pending_extension_manager->AddForTesting( 729 id, 730 PendingExtensionInfo(test_url, &ShouldAlwaysInstall, kIsFromSync, 731 kInstallSilently, kInitialState, 732 kInitialIncognitoEnabled, Extension::INTERNAL)); 733 } 734 735 // Call back the ExtensionUpdater with a 200 response and some test data 736 std::string extension_data("whatever"); 737 fetcher = factory.GetFetcherByID(ExtensionUpdater::kExtensionFetcherId); 738 EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL); 739 EXPECT_TRUE(fetcher->load_flags() == expected_load_flags); 740 fetcher->delegate()->OnURLFetchComplete( 741 fetcher, test_url, net::URLRequestStatus(), 200, ResponseCookies(), 742 extension_data); 743 744 file_thread.Stop(); 745 ui_loop.RunAllPending(); 746 747 // Expect that ExtensionUpdater asked the mock extensions service to install 748 // a file with the test data for the right id. 749 EXPECT_EQ(id, service->extension_id()); 750 FilePath tmpfile_path = service->install_path(); 751 EXPECT_FALSE(tmpfile_path.empty()); 752 EXPECT_EQ(test_url, service->download_url()); 753 std::string file_contents; 754 EXPECT_TRUE(file_util::ReadFileToString(tmpfile_path, &file_contents)); 755 EXPECT_TRUE(extension_data == file_contents); 756 757 // The FILE thread is needed for |service|'s cleanup, 758 // because of ImportantFileWriter. 759 file_thread.Start(); 760 service.reset(); 761 762 file_util::Delete(tmpfile_path, false); 763 URLFetcher::set_factory(NULL); 764 } 765 766 static void TestBlacklistDownloading() { 767 MessageLoop message_loop; 768 BrowserThread ui_thread(BrowserThread::UI, &message_loop); 769 BrowserThread file_thread(BrowserThread::FILE, &message_loop); 770 BrowserThread io_thread(BrowserThread::IO); 771 io_thread.Start(); 772 773 TestURLFetcherFactory factory; 774 TestURLFetcher* fetcher = NULL; 775 URLFetcher::set_factory(&factory); 776 ServiceForBlacklistTests service; 777 ExtensionUpdater updater( 778 &service, service.extension_prefs(), service.pref_service(), 779 service.profile(), kUpdateFrequencySecs); 780 updater.Start(); 781 GURL test_url("http://localhost/extension.crx"); 782 783 std::string id = "com.google.crx.blacklist"; 784 785 std::string hash = 786 "2CE109E9D0FAF820B2434E166297934E6177B65AB9951DBC3E204CAD4689B39C"; 787 788 std::string version = "0.0.1"; 789 updater.FetchUpdatedExtension(id, test_url, hash, version); 790 791 // Call back the ExtensionUpdater with a 200 response and some test data 792 std::string extension_data("aaabbb"); 793 fetcher = factory.GetFetcherByID(ExtensionUpdater::kExtensionFetcherId); 794 EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL); 795 EXPECT_TRUE(fetcher->load_flags() == expected_load_flags); 796 fetcher->delegate()->OnURLFetchComplete( 797 fetcher, test_url, net::URLRequestStatus(), 200, ResponseCookies(), 798 extension_data); 799 800 message_loop.RunAllPending(); 801 802 // The updater should have called extension service to process the 803 // blacklist. 804 EXPECT_TRUE(service.processed_blacklist()); 805 806 EXPECT_EQ(version, service.pref_service()-> 807 GetString(prefs::kExtensionBlacklistUpdateVersion)); 808 809 URLFetcher::set_factory(NULL); 810 } 811 812 static void TestMultipleExtensionDownloading() { 813 MessageLoopForUI message_loop; 814 BrowserThread ui_thread(BrowserThread::UI, &message_loop); 815 BrowserThread file_thread(BrowserThread::FILE, &message_loop); 816 BrowserThread io_thread(BrowserThread::IO); 817 io_thread.Start(); 818 819 TestURLFetcherFactory factory; 820 TestURLFetcher* fetcher = NULL; 821 URLFetcher::set_factory(&factory); 822 ServiceForDownloadTests service; 823 ExtensionUpdater updater( 824 &service, service.extension_prefs(), service.pref_service(), 825 service.profile(), kUpdateFrequencySecs); 826 updater.Start(); 827 828 GURL url1("http://localhost/extension1.crx"); 829 GURL url2("http://localhost/extension2.crx"); 830 831 std::string id1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 832 std::string id2 = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; 833 834 std::string hash1 = ""; 835 std::string hash2 = ""; 836 837 std::string version1 = "0.1"; 838 std::string version2 = "0.1"; 839 // Start two fetches 840 updater.FetchUpdatedExtension(id1, url1, hash1, version1); 841 updater.FetchUpdatedExtension(id2, url2, hash2, version2); 842 843 // Make the first fetch complete. 844 std::string extension_data1("whatever"); 845 fetcher = factory.GetFetcherByID(ExtensionUpdater::kExtensionFetcherId); 846 EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL); 847 EXPECT_TRUE(fetcher->load_flags() == expected_load_flags); 848 fetcher->delegate()->OnURLFetchComplete( 849 fetcher, url1, net::URLRequestStatus(), 200, ResponseCookies(), 850 extension_data1); 851 message_loop.RunAllPending(); 852 853 // Expect that the service was asked to do an install with the right data. 854 FilePath tmpfile_path = service.install_path(); 855 EXPECT_FALSE(tmpfile_path.empty()); 856 EXPECT_EQ(id1, service.extension_id()); 857 EXPECT_EQ(url1, service.download_url()); 858 message_loop.RunAllPending(); 859 file_util::Delete(tmpfile_path, false); 860 861 // Make sure the second fetch finished and asked the service to do an 862 // update. 863 std::string extension_data2("whatever2"); 864 fetcher = factory.GetFetcherByID(ExtensionUpdater::kExtensionFetcherId); 865 EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL); 866 EXPECT_TRUE(fetcher->load_flags() == expected_load_flags); 867 fetcher->delegate()->OnURLFetchComplete( 868 fetcher, url2, net::URLRequestStatus(), 200, ResponseCookies(), 869 extension_data2); 870 message_loop.RunAllPending(); 871 EXPECT_EQ(id2, service.extension_id()); 872 EXPECT_EQ(url2, service.download_url()); 873 EXPECT_FALSE(service.install_path().empty()); 874 875 // Make sure the correct crx contents were passed for the update call. 876 std::string file_contents; 877 EXPECT_TRUE(file_util::ReadFileToString(service.install_path(), 878 &file_contents)); 879 EXPECT_TRUE(extension_data2 == file_contents); 880 file_util::Delete(service.install_path(), false); 881 } 882 883 // Test requests to both a Google server and a non-google server. This allows 884 // us to test various combinations of installed (ie roll call) and active 885 // (ie app launch) ping scenarios. The invariant is that each type of ping 886 // value should be present at most once per day, and can be calculated based 887 // on the delta between now and the last ping time (or in the case of active 888 // pings, that delta plus whether the app has been active). 889 static void TestGalleryRequests(int rollcall_ping_days, 890 int active_ping_days, 891 bool active_bit) { 892 MessageLoop message_loop; 893 BrowserThread ui_thread(BrowserThread::UI, &message_loop); 894 BrowserThread file_thread(BrowserThread::FILE, &message_loop); 895 896 TestURLFetcherFactory factory; 897 URLFetcher::set_factory(&factory); 898 899 // Set up 2 mock extensions, one with a google.com update url and one 900 // without. 901 ServiceForManifestTests service; 902 ExtensionList tmp; 903 GURL url1("http://clients2.google.com/service/update2/crx"); 904 GURL url2("http://www.somewebsite.com"); 905 service.CreateTestExtensions(1, 1, &tmp, &url1.possibly_invalid_spec(), 906 Extension::INTERNAL); 907 service.CreateTestExtensions(2, 1, &tmp, &url2.possibly_invalid_spec(), 908 Extension::INTERNAL); 909 EXPECT_EQ(2u, tmp.size()); 910 service.set_extensions(tmp); 911 912 ExtensionPrefs* prefs = service.extension_prefs(); 913 const std::string& id = tmp[0]->id(); 914 Time now = Time::Now(); 915 if (rollcall_ping_days == 0) { 916 prefs->SetLastPingDay(id, now - TimeDelta::FromSeconds(15)); 917 } else if (rollcall_ping_days > 0) { 918 Time last_ping_day = now - 919 TimeDelta::FromDays(rollcall_ping_days) - 920 TimeDelta::FromSeconds(15); 921 prefs->SetLastPingDay(id, last_ping_day); 922 } 923 924 // Store a value for the last day we sent an active ping. 925 if (active_ping_days == 0) { 926 prefs->SetLastActivePingDay(id, now - TimeDelta::FromSeconds(15)); 927 } else if (active_ping_days > 0) { 928 Time last_active_ping_day = now - 929 TimeDelta::FromDays(active_ping_days) - 930 TimeDelta::FromSeconds(15); 931 prefs->SetLastActivePingDay(id, last_active_ping_day); 932 } 933 if (active_bit) 934 prefs->SetActiveBit(id, true); 935 936 ExtensionUpdater updater( 937 &service, service.extension_prefs(), service.pref_service(), 938 service.profile(), kUpdateFrequencySecs); 939 updater.Start(); 940 updater.set_blacklist_checks_enabled(false); 941 942 // Make the updater do manifest fetching, and note the urls it tries to 943 // fetch. 944 std::vector<GURL> fetched_urls; 945 updater.CheckNow(); 946 TestURLFetcher* fetcher = 947 factory.GetFetcherByID(ExtensionUpdater::kManifestFetcherId); 948 EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL); 949 fetched_urls.push_back(fetcher->original_url()); 950 fetcher->delegate()->OnURLFetchComplete( 951 fetcher, fetched_urls[0], net::URLRequestStatus(), 500, 952 ResponseCookies(), ""); 953 fetcher = 954 factory.GetFetcherByID(ExtensionUpdater::kManifestFetcherId); 955 fetched_urls.push_back(fetcher->original_url()); 956 957 // The urls could have been fetched in either order, so use the host to 958 // tell them apart and note the query each used. 959 std::string url1_query; 960 std::string url2_query; 961 if (fetched_urls[0].host() == url1.host()) { 962 url1_query = fetched_urls[0].query(); 963 url2_query = fetched_urls[1].query(); 964 } else if (fetched_urls[0].host() == url2.host()) { 965 url1_query = fetched_urls[1].query(); 966 url2_query = fetched_urls[0].query(); 967 } else { 968 NOTREACHED(); 969 } 970 971 // First make sure the non-google query had no ping parameter. 972 std::string search_string = "ping%3D"; 973 EXPECT_TRUE(url2_query.find(search_string) == std::string::npos); 974 975 // Now make sure the google query had the correct ping parameter. 976 bool ping_expected = false; 977 bool did_rollcall = false; 978 if (rollcall_ping_days != 0) { 979 search_string += "r%253D" + base::IntToString(rollcall_ping_days); 980 did_rollcall = true; 981 ping_expected = true; 982 } 983 if (active_bit && active_ping_days != 0) { 984 if (did_rollcall) 985 search_string += "%2526"; 986 search_string += "a%253D" + base::IntToString(active_ping_days); 987 ping_expected = true; 988 } 989 bool ping_found = url1_query.find(search_string) != std::string::npos; 990 EXPECT_EQ(ping_expected, ping_found) << "query was: " << url1_query 991 << " was looking for " << search_string; 992 } 993 994 // This makes sure that the extension updater properly stores the results 995 // of a <daystart> tag from a manifest fetch in one of two cases: 1) This is 996 // the first time we fetched the extension, or 2) We sent a ping value of 997 // >= 1 day for the extension. 998 static void TestHandleManifestResults() { 999 ServiceForManifestTests service; 1000 MessageLoop message_loop; 1001 BrowserThread ui_thread(BrowserThread::UI, &message_loop); 1002 ExtensionUpdater updater( 1003 &service, service.extension_prefs(), service.pref_service(), 1004 service.profile(), kUpdateFrequencySecs); 1005 updater.Start(); 1006 1007 GURL update_url("http://www.google.com/manifest"); 1008 ExtensionList tmp; 1009 service.CreateTestExtensions(1, 1, &tmp, &update_url.spec(), 1010 Extension::INTERNAL); 1011 service.set_extensions(tmp); 1012 1013 ManifestFetchData fetch_data(update_url); 1014 const Extension* extension = tmp[0]; 1015 fetch_data.AddExtension(extension->id(), extension->VersionString(), 1016 kNeverPingedData, 1017 kEmptyUpdateUrlData); 1018 UpdateManifest::Results results; 1019 results.daystart_elapsed_seconds = 750; 1020 1021 updater.HandleManifestResults(fetch_data, &results); 1022 Time last_ping_day = 1023 service.extension_prefs()->LastPingDay(extension->id()); 1024 EXPECT_FALSE(last_ping_day.is_null()); 1025 int64 seconds_diff = (Time::Now() - last_ping_day).InSeconds(); 1026 EXPECT_LT(seconds_diff - results.daystart_elapsed_seconds, 5); 1027 } 1028 }; 1029 1030 // Because we test some private methods of ExtensionUpdater, it's easer for the 1031 // actual test code to live in ExtenionUpdaterTest methods instead of TEST_F 1032 // subclasses where friendship with ExtenionUpdater is not inherited. 1033 1034 TEST(ExtensionUpdaterTest, TestExtensionUpdateCheckRequests) { 1035 ExtensionUpdaterTest::TestExtensionUpdateCheckRequests(false); 1036 } 1037 1038 TEST(ExtensionUpdaterTest, TestExtensionUpdateCheckRequestsPending) { 1039 ExtensionUpdaterTest::TestExtensionUpdateCheckRequests(true); 1040 } 1041 1042 // This test is disabled on Mac, see http://crbug.com/26035. 1043 TEST(ExtensionUpdaterTest, TestBlacklistUpdateCheckRequests) { 1044 ExtensionUpdaterTest::TestBlacklistUpdateCheckRequests(); 1045 } 1046 1047 TEST(ExtensionUpdaterTest, TestUpdateUrlData) { 1048 MessageLoop message_loop; 1049 BrowserThread file_thread(BrowserThread::FILE, &message_loop); 1050 1051 ExtensionUpdaterTest::TestUpdateUrlDataEmpty(); 1052 ExtensionUpdaterTest::TestUpdateUrlDataSimple(); 1053 ExtensionUpdaterTest::TestUpdateUrlDataCompound(); 1054 ExtensionUpdaterTest::TestUpdateUrlDataFromGallery( 1055 Extension::GalleryUpdateUrl(false).spec()); 1056 ExtensionUpdaterTest::TestUpdateUrlDataFromGallery( 1057 Extension::GalleryUpdateUrl(true).spec()); 1058 } 1059 1060 TEST(ExtensionUpdaterTest, TestDetermineUpdates) { 1061 ExtensionUpdaterTest::TestDetermineUpdates(); 1062 } 1063 1064 TEST(ExtensionUpdaterTest, TestDetermineUpdatesPending) { 1065 ExtensionUpdaterTest::TestDetermineUpdatesPending(); 1066 } 1067 1068 TEST(ExtensionUpdaterTest, TestMultipleManifestDownloading) { 1069 ExtensionUpdaterTest::TestMultipleManifestDownloading(); 1070 } 1071 1072 TEST(ExtensionUpdaterTest, TestSingleExtensionDownloading) { 1073 ExtensionUpdaterTest::TestSingleExtensionDownloading(false); 1074 } 1075 1076 TEST(ExtensionUpdaterTest, TestSingleExtensionDownloadingPending) { 1077 ExtensionUpdaterTest::TestSingleExtensionDownloading(true); 1078 } 1079 1080 // This test is disabled on Mac, see http://crbug.com/26035. 1081 TEST(ExtensionUpdaterTest, TestBlacklistDownloading) { 1082 ExtensionUpdaterTest::TestBlacklistDownloading(); 1083 } 1084 1085 TEST(ExtensionUpdaterTest, TestMultipleExtensionDownloading) { 1086 ExtensionUpdaterTest::TestMultipleExtensionDownloading(); 1087 } 1088 1089 TEST(ExtensionUpdaterTest, TestGalleryRequests) { 1090 // We want to test a variety of combinations of expected ping conditions for 1091 // rollcall and active pings. 1092 int ping_cases[] = { ManifestFetchData::kNeverPinged, 0, 1, 5 }; 1093 1094 for (size_t i = 0; i < arraysize(ping_cases); i++) { 1095 for (size_t j = 0; j < arraysize(ping_cases); j++) { 1096 for (size_t k = 0; k < 2; k++) { 1097 int rollcall_ping_days = ping_cases[i]; 1098 int active_ping_days = ping_cases[j]; 1099 // Skip cases where rollcall_ping_days == -1, but active_ping_days > 0, 1100 // because rollcall_ping_days == -1 means the app was just installed and 1101 // this is the first update check after installation. 1102 if (rollcall_ping_days == ManifestFetchData::kNeverPinged && 1103 active_ping_days > 0) 1104 continue; 1105 1106 bool active_bit = k > 0; 1107 ExtensionUpdaterTest::TestGalleryRequests( 1108 rollcall_ping_days, active_ping_days, active_bit); 1109 ASSERT_FALSE(HasFailure()) << 1110 " rollcall_ping_days=" << ping_cases[i] << 1111 " active_ping_days=" << ping_cases[j] << 1112 " active_bit=" << active_bit; 1113 } 1114 } 1115 } 1116 } 1117 1118 TEST(ExtensionUpdaterTest, TestHandleManifestResults) { 1119 ExtensionUpdaterTest::TestHandleManifestResults(); 1120 } 1121 1122 TEST(ExtensionUpdaterTest, TestManifestFetchesBuilderAddExtension) { 1123 MessageLoop message_loop; 1124 BrowserThread file_thread(BrowserThread::FILE, &message_loop); 1125 1126 MockService service; 1127 ManifestFetchesBuilder builder(&service, service.extension_prefs()); 1128 1129 // Non-internal non-external extensions should be rejected. 1130 { 1131 ExtensionList extensions; 1132 service.CreateTestExtensions(1, 1, &extensions, NULL, Extension::INVALID); 1133 ASSERT_FALSE(extensions.empty()); 1134 builder.AddExtension(*extensions[0]); 1135 EXPECT_TRUE(builder.GetFetches().empty()); 1136 } 1137 1138 // Extensions with invalid update URLs should be rejected. 1139 builder.AddPendingExtension( 1140 GenerateId("foo"), PendingExtensionInfo(GURL("http:google.com:foo"), 1141 &ShouldInstallExtensionsOnly, 1142 false, false, true, false, 1143 Extension::INTERNAL)); 1144 EXPECT_TRUE(builder.GetFetches().empty()); 1145 1146 // Extensions with empty IDs should be rejected. 1147 builder.AddPendingExtension( 1148 "", PendingExtensionInfo(GURL(), &ShouldInstallExtensionsOnly, 1149 false, false, true, false, 1150 Extension::INTERNAL)); 1151 EXPECT_TRUE(builder.GetFetches().empty()); 1152 1153 // TODO(akalin): Test that extensions with empty update URLs 1154 // converted from user scripts are rejected. 1155 1156 // Extensions with empty update URLs should have a default one 1157 // filled in. 1158 builder.AddPendingExtension( 1159 GenerateId("foo"), PendingExtensionInfo(GURL(), 1160 &ShouldInstallExtensionsOnly, 1161 false, false, true, false, 1162 Extension::INTERNAL)); 1163 std::vector<ManifestFetchData*> fetches = builder.GetFetches(); 1164 ASSERT_EQ(1u, fetches.size()); 1165 scoped_ptr<ManifestFetchData> fetch(fetches[0]); 1166 fetches.clear(); 1167 EXPECT_FALSE(fetch->base_url().is_empty()); 1168 EXPECT_FALSE(fetch->full_url().is_empty()); 1169 } 1170 1171 TEST(ExtensionUpdaterTest, TestStartUpdateCheckMemory) { 1172 MessageLoop message_loop; 1173 BrowserThread ui_thread(BrowserThread::UI, &message_loop); 1174 BrowserThread file_thread(BrowserThread::FILE, &message_loop); 1175 1176 ServiceForManifestTests service; 1177 TestURLFetcherFactory factory; 1178 URLFetcher::set_factory(&factory); 1179 ExtensionUpdater updater( 1180 &service, service.extension_prefs(), service.pref_service(), 1181 service.profile(), kUpdateFrequencySecs); 1182 updater.Start(); 1183 updater.StartUpdateCheck(new ManifestFetchData(GURL())); 1184 // This should delete the newly-created ManifestFetchData. 1185 updater.StartUpdateCheck(new ManifestFetchData(GURL())); 1186 // This should add into |manifests_pending_|. 1187 updater.StartUpdateCheck(new ManifestFetchData( 1188 GURL("http://www.google.com"))); 1189 // This should clear out |manifests_pending_|. 1190 updater.Stop(); 1191 } 1192 1193 TEST(ExtensionUpdaterTest, TestCheckSoon) { 1194 MessageLoop message_loop; 1195 BrowserThread ui_thread(BrowserThread::UI, &message_loop); 1196 BrowserThread file_thread(BrowserThread::FILE, &message_loop); 1197 1198 ServiceForManifestTests service; 1199 TestURLFetcherFactory factory; 1200 URLFetcher::set_factory(&factory); 1201 ExtensionUpdater updater( 1202 &service, service.extension_prefs(), service.pref_service(), 1203 service.profile(), kUpdateFrequencySecs); 1204 EXPECT_FALSE(updater.WillCheckSoon()); 1205 updater.Start(); 1206 EXPECT_FALSE(updater.WillCheckSoon()); 1207 updater.CheckSoon(); 1208 EXPECT_TRUE(updater.WillCheckSoon()); 1209 updater.CheckSoon(); 1210 EXPECT_TRUE(updater.WillCheckSoon()); 1211 ExtensionUpdaterTest::SimulateCheckSoon(updater, &message_loop); 1212 EXPECT_FALSE(updater.WillCheckSoon()); 1213 updater.CheckSoon(); 1214 EXPECT_TRUE(updater.WillCheckSoon()); 1215 updater.Stop(); 1216 EXPECT_FALSE(updater.WillCheckSoon()); 1217 } 1218 1219 // TODO(asargent) - (http://crbug.com/12780) add tests for: 1220 // -prodversionmin (shouldn't update if browser version too old) 1221 // -manifests & updates arriving out of order / interleaved 1222 // -malformed update url (empty, file://, has query, has a # fragment, etc.) 1223 // -An extension gets uninstalled while updates are in progress (so it doesn't 1224 // "come back from the dead") 1225 // -An extension gets manually updated to v3 while we're downloading v2 (ie 1226 // you don't get downgraded accidentally) 1227 // -An update manifest mentions multiple updates 1228