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 "chrome/browser/component_updater/test/component_updater_service_unittest.h" 6 #include "base/file_util.h" 7 #include "base/path_service.h" 8 #include "base/run_loop.h" 9 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_util.h" 11 #include "base/strings/stringprintf.h" 12 #include "base/values.h" 13 #include "chrome/browser/component_updater/test/test_installer.h" 14 #include "chrome/common/chrome_paths.h" 15 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/resource_controller.h" 17 #include "content/public/browser/resource_request_info.h" 18 #include "content/public/browser/resource_throttle.h" 19 #include "libxml/globals.h" 20 #include "net/base/upload_bytes_element_reader.h" 21 #include "net/url_request/url_fetcher.h" 22 #include "net/url_request/url_request_test_util.h" 23 #include "url/gurl.h" 24 25 using content::BrowserThread; 26 27 using ::testing::_; 28 using ::testing::InSequence; 29 using ::testing::Mock; 30 31 namespace component_updater { 32 33 #define POST_INTERCEPT_SCHEME "http" 34 #define POST_INTERCEPT_HOSTNAME "localhost2" 35 #define POST_INTERCEPT_PATH "/update2" 36 37 MockComponentObserver::MockComponentObserver() { 38 } 39 40 MockComponentObserver::~MockComponentObserver() { 41 } 42 43 TestConfigurator::TestConfigurator() 44 : initial_time_(0), 45 times_(1), 46 recheck_time_(0), 47 ondemand_time_(0), 48 cus_(NULL), 49 context_(new net::TestURLRequestContextGetter( 50 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))) { 51 } 52 53 TestConfigurator::~TestConfigurator() { 54 } 55 56 int TestConfigurator::InitialDelay() { return initial_time_; } 57 58 int TestConfigurator::NextCheckDelay() { 59 // This is called when a new full cycle of checking for updates is going 60 // to happen. In test we normally only test one cycle so it is a good 61 // time to break from the test messageloop Run() method so the test can 62 // finish. 63 if (--times_ <= 0) { 64 quit_closure_.Run(); 65 return 0; 66 } 67 return 1; 68 } 69 70 int TestConfigurator::StepDelay() { 71 return 0; 72 } 73 74 int TestConfigurator::StepDelayMedium() { 75 return NextCheckDelay(); 76 } 77 78 int TestConfigurator::MinimumReCheckWait() { 79 return recheck_time_; 80 } 81 82 int TestConfigurator::OnDemandDelay() { 83 return ondemand_time_; 84 } 85 86 GURL TestConfigurator::UpdateUrl() { 87 return GURL(POST_INTERCEPT_SCHEME "://" 88 POST_INTERCEPT_HOSTNAME POST_INTERCEPT_PATH); 89 } 90 91 GURL TestConfigurator::PingUrl() { 92 return UpdateUrl(); 93 } 94 95 std::string TestConfigurator::ExtraRequestParams() { return "extra=\"foo\""; } 96 97 size_t TestConfigurator::UrlSizeLimit() { return 256; } 98 99 net::URLRequestContextGetter* TestConfigurator::RequestContext() { 100 return context_.get(); 101 } 102 103 // Don't use the utility process to run code out-of-process. 104 bool TestConfigurator::InProcess() { return true; } 105 106 ComponentPatcher* TestConfigurator::CreateComponentPatcher() { 107 return new MockComponentPatcher(); 108 } 109 110 bool TestConfigurator::DeltasEnabled() const { 111 return true; 112 } 113 114 bool TestConfigurator::UseBackgroundDownloader() const { 115 return false; 116 } 117 118 // Set how many update checks are called, the default value is just once. 119 void TestConfigurator::SetLoopCount(int times) { times_ = times; } 120 121 void TestConfigurator::SetRecheckTime(int seconds) { 122 recheck_time_ = seconds; 123 } 124 125 void TestConfigurator::SetOnDemandTime(int seconds) { 126 ondemand_time_ = seconds; 127 } 128 129 void TestConfigurator::SetComponentUpdateService(ComponentUpdateService* cus) { 130 cus_ = cus; 131 } 132 133 void TestConfigurator::SetQuitClosure(const base::Closure& quit_closure) { 134 quit_closure_ = quit_closure; 135 } 136 137 void TestConfigurator::SetInitialDelay(int seconds) { 138 initial_time_ = seconds; 139 } 140 141 InterceptorFactory::InterceptorFactory() 142 : URLRequestPostInterceptorFactory(POST_INTERCEPT_SCHEME, 143 POST_INTERCEPT_HOSTNAME) {} 144 145 InterceptorFactory::~InterceptorFactory() {} 146 147 URLRequestPostInterceptor* InterceptorFactory::CreateInterceptor() { 148 return URLRequestPostInterceptorFactory::CreateInterceptor( 149 base::FilePath::FromUTF8Unsafe(POST_INTERCEPT_PATH)); 150 } 151 152 class PartialMatch : public URLRequestPostInterceptor::RequestMatcher { 153 public: 154 explicit PartialMatch(const std::string& expected) : expected_(expected) {} 155 virtual bool Match(const std::string& actual) const OVERRIDE { 156 return actual.find(expected_) != std::string::npos; 157 } 158 159 private: 160 const std::string expected_; 161 162 DISALLOW_COPY_AND_ASSIGN(PartialMatch); 163 }; 164 165 ComponentUpdaterTest::ComponentUpdaterTest() 166 : test_config_(NULL), 167 thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) { 168 // The component updater instance under test. 169 test_config_ = new TestConfigurator; 170 component_updater_.reset(ComponentUpdateServiceFactory(test_config_)); 171 test_config_->SetComponentUpdateService(component_updater_.get()); 172 173 // The test directory is chrome/test/data/components. 174 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_); 175 test_data_dir_ = test_data_dir_.AppendASCII("components"); 176 177 net::URLFetcher::SetEnableInterceptionForTests(true); 178 } 179 180 ComponentUpdaterTest::~ComponentUpdaterTest() { 181 net::URLFetcher::SetEnableInterceptionForTests(false); 182 } 183 184 void ComponentUpdaterTest::SetUp() { 185 get_interceptor_.reset(new GetInterceptor); 186 interceptor_factory_.reset(new InterceptorFactory); 187 post_interceptor_ = interceptor_factory_->CreateInterceptor(); 188 EXPECT_TRUE(post_interceptor_); 189 } 190 191 void ComponentUpdaterTest::TearDown() { 192 interceptor_factory_.reset(); 193 get_interceptor_.reset(); 194 xmlCleanupGlobals(); 195 } 196 197 ComponentUpdateService* ComponentUpdaterTest::component_updater() { 198 return component_updater_.get(); 199 } 200 201 // Makes the full path to a component updater test file. 202 const base::FilePath ComponentUpdaterTest::test_file(const char* file) { 203 return test_data_dir_.AppendASCII(file); 204 } 205 206 TestConfigurator* ComponentUpdaterTest::test_configurator() { 207 return test_config_; 208 } 209 210 ComponentUpdateService::Status ComponentUpdaterTest::RegisterComponent( 211 CrxComponent* com, 212 TestComponents component, 213 const Version& version, 214 TestInstaller* installer) { 215 if (component == kTestComponent_abag) { 216 com->name = "test_abag"; 217 com->pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash)); 218 } else if (component == kTestComponent_jebg) { 219 com->name = "test_jebg"; 220 com->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); 221 } else { 222 com->name = "test_ihfo"; 223 com->pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash)); 224 } 225 com->version = version; 226 com->installer = installer; 227 return component_updater_->RegisterComponent(*com); 228 } 229 230 void ComponentUpdaterTest::RunThreads() { 231 base::RunLoop runloop; 232 test_configurator()->SetQuitClosure(runloop.QuitClosure()); 233 runloop.Run(); 234 235 // Since some tests need to drain currently enqueued tasks such as network 236 // intercepts on the IO thread, run the threads until they are 237 // idle. The component updater service won't loop again until the loop count 238 // is set and the service is started. 239 RunThreadsUntilIdle(); 240 } 241 242 void ComponentUpdaterTest::RunThreadsUntilIdle() { 243 base::RunLoop().RunUntilIdle(); 244 } 245 246 ComponentUpdateService::Status OnDemandTester::OnDemand( 247 ComponentUpdateService* cus, const std::string& component_id) { 248 return cus->OnDemandUpdate(component_id); 249 } 250 251 // Verify that our test fixture work and the component updater can 252 // be created and destroyed with no side effects. 253 TEST_F(ComponentUpdaterTest, VerifyFixture) { 254 EXPECT_TRUE(component_updater() != NULL); 255 } 256 257 // Verify that the component updater can be caught in a quick 258 // start-shutdown situation. Failure of this test will be a crash. 259 TEST_F(ComponentUpdaterTest, StartStop) { 260 component_updater()->Start(); 261 RunThreadsUntilIdle(); 262 component_updater()->Stop(); 263 } 264 265 // Verify that when the server has no updates, we go back to sleep and 266 // the COMPONENT_UPDATER_STARTED and COMPONENT_UPDATER_SLEEPING notifications 267 // are generated. No pings are sent. 268 TEST_F(ComponentUpdaterTest, CheckCrxSleep) { 269 MockComponentObserver observer; 270 271 EXPECT_CALL(observer, 272 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 273 .Times(1); 274 EXPECT_CALL(observer, 275 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 276 .Times(2); 277 EXPECT_CALL(observer, 278 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 279 .Times(2); 280 281 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 282 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 283 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 284 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 285 286 TestInstaller installer; 287 CrxComponent com; 288 com.observer = &observer; 289 EXPECT_EQ(ComponentUpdateService::kOk, 290 RegisterComponent(&com, 291 kTestComponent_abag, 292 Version("1.1"), 293 &installer)); 294 295 // We loop twice, but there are no updates so we expect two sleep messages. 296 test_configurator()->SetLoopCount(2); 297 component_updater()->Start(); 298 RunThreads(); 299 300 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 301 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count()); 302 303 // Expect to see the two update check requests and no other requests, 304 // including pings. 305 EXPECT_EQ(2, post_interceptor_->GetHitCount()) 306 << post_interceptor_->GetRequestsAsString(); 307 EXPECT_EQ(2, post_interceptor_->GetCount()) 308 << post_interceptor_->GetRequestsAsString(); 309 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 310 "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" 311 "<updatecheck /></app>")) 312 << post_interceptor_->GetRequestsAsString(); 313 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 314 "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" 315 "<updatecheck /></app>")) 316 << post_interceptor_->GetRequestsAsString(); 317 318 component_updater()->Stop(); 319 320 // Loop twice again but this case we simulate a server error by returning 321 // an empty file. Expect the behavior of the service to be the same as before. 322 EXPECT_CALL(observer, 323 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 324 .Times(1); 325 EXPECT_CALL(observer, 326 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 327 .Times(2); 328 EXPECT_CALL(observer, 329 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 330 .Times(2); 331 332 post_interceptor_->Reset(); 333 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 334 "updatecheck"), test_file("updatecheck_reply_empty"))); 335 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 336 "updatecheck"), test_file("updatecheck_reply_empty"))); 337 338 test_configurator()->SetLoopCount(2); 339 component_updater()->Start(); 340 RunThreads(); 341 342 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 343 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count()); 344 345 EXPECT_EQ(2, post_interceptor_->GetHitCount()) 346 << post_interceptor_->GetRequestsAsString(); 347 EXPECT_EQ(2, post_interceptor_->GetCount()) 348 << post_interceptor_->GetRequestsAsString(); 349 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 350 "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" 351 "<updatecheck /></app>")) 352 << post_interceptor_->GetRequestsAsString(); 353 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 354 "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" 355 "<updatecheck /></app>")) 356 << post_interceptor_->GetRequestsAsString(); 357 358 component_updater()->Stop(); 359 } 360 361 // Verify that we can check for updates and install one component. Besides 362 // the notifications above COMPONENT_UPDATE_FOUND and COMPONENT_UPDATE_READY 363 // should have been fired. We do two loops so the second time around there 364 // should be nothing left to do. 365 // We also check that the following network requests are issued: 366 // 1- update check 367 // 2- download crx 368 // 3- ping 369 // 4- second update check. 370 TEST_F(ComponentUpdaterTest, InstallCrx) { 371 MockComponentObserver observer1; 372 { 373 InSequence seq; 374 EXPECT_CALL(observer1, 375 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 376 .Times(1); 377 EXPECT_CALL(observer1, 378 OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0)) 379 .Times(1); 380 EXPECT_CALL(observer1, 381 OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0)) 382 .Times(1); 383 EXPECT_CALL(observer1, 384 OnEvent(ComponentObserver::COMPONENT_UPDATED, 0)) 385 .Times(1); 386 EXPECT_CALL(observer1, 387 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 388 .Times(1); 389 EXPECT_CALL(observer1, 390 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 391 .Times(1); 392 EXPECT_CALL(observer1, 393 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 394 .Times(1); 395 } 396 397 MockComponentObserver observer2; 398 { 399 InSequence seq; 400 EXPECT_CALL(observer2, 401 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 402 .Times(1); 403 EXPECT_CALL(observer2, 404 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 405 .Times(1); 406 EXPECT_CALL(observer2, 407 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 408 .Times(1); 409 EXPECT_CALL(observer2, 410 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 411 .Times(1); 412 EXPECT_CALL(observer2, 413 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 414 .Times(1); 415 } 416 417 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 418 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 419 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 420 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 421 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 422 423 get_interceptor_->SetResponse( 424 GURL(expected_crx_url), 425 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); 426 427 TestInstaller installer1; 428 CrxComponent com1; 429 com1.observer = &observer1; 430 RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1); 431 TestInstaller installer2; 432 CrxComponent com2; 433 com2.observer = &observer2; 434 RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2); 435 436 test_configurator()->SetLoopCount(2); 437 component_updater()->Start(); 438 RunThreads(); 439 440 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error()); 441 EXPECT_EQ(1, static_cast<TestInstaller*>(com1.installer)->install_count()); 442 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error()); 443 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count()); 444 445 // Expect three request in total: two update checks and one ping. 446 EXPECT_EQ(3, post_interceptor_->GetHitCount()) 447 << post_interceptor_->GetRequestsAsString(); 448 EXPECT_EQ(3, post_interceptor_->GetCount()) 449 << post_interceptor_->GetRequestsAsString(); 450 451 // Expect one component download. 452 EXPECT_EQ(1, get_interceptor_->GetHitCount()); 453 454 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 455 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" 456 "<updatecheck /></app>")) 457 << post_interceptor_->GetRequestsAsString(); 458 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 459 "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"2.2\">" 460 "<updatecheck /></app>")) 461 << post_interceptor_->GetRequestsAsString(); 462 463 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 464 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " 465 "version=\"0.9\" nextversion=\"1.0\">" 466 "<event eventtype=\"3\" eventresult=\"1\"/>")) 467 << post_interceptor_->GetRequestsAsString(); 468 469 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find( 470 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"1.0\">" 471 "<updatecheck /></app>")); 472 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find( 473 "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"2.2\">" 474 "<updatecheck /></app>")) 475 << post_interceptor_->GetRequestsAsString(); 476 477 // Test the protocol version is correct and the extra request attributes 478 // are included in the request. 479 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 480 "request protocol=\"3.0\" extra=\"foo\"")) 481 << post_interceptor_->GetRequestsAsString(); 482 483 // Tokenize the request string to look for specific attributes, which 484 // are important for backward compatibility with the version v2 of the update 485 // protocol. In this case, inspect the <request>, which is the first element 486 // after the xml declaration of the update request body. 487 // Expect to find the |os|, |arch|, |prodchannel|, and |prodversion| 488 // attributes: 489 // <?xml version="1.0" encoding="UTF-8"?> 490 // <request... os=... arch=... prodchannel=... prodversion=...> 491 // ... 492 // </request> 493 const std::string update_request(post_interceptor_->GetRequests()[0]); 494 std::vector<base::StringPiece> elements; 495 Tokenize(update_request, "<>", &elements); 496 EXPECT_NE(string::npos, elements[1].find(" os=")); 497 EXPECT_NE(string::npos, elements[1].find(" arch=")); 498 EXPECT_NE(string::npos, elements[1].find(" prodchannel=")); 499 EXPECT_NE(string::npos, elements[1].find(" prodversion=")); 500 501 component_updater()->Stop(); 502 } 503 504 // This test checks that the "prodversionmin" value is handled correctly. In 505 // particular there should not be an install because the minimum product 506 // version is much higher than of chrome. 507 TEST_F(ComponentUpdaterTest, ProdVersionCheck) { 508 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 509 "updatecheck"), test_file("updatecheck_reply_2.xml"))); 510 511 get_interceptor_->SetResponse( 512 GURL(expected_crx_url), 513 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); 514 515 TestInstaller installer; 516 CrxComponent com; 517 RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer); 518 519 test_configurator()->SetLoopCount(1); 520 component_updater()->Start(); 521 RunThreads(); 522 523 // Expect one update check and no ping. 524 EXPECT_EQ(1, post_interceptor_->GetHitCount()) 525 << post_interceptor_->GetRequestsAsString(); 526 EXPECT_EQ(1, post_interceptor_->GetCount()) 527 << post_interceptor_->GetRequestsAsString(); 528 529 // Expect no download to occur. 530 EXPECT_EQ(0, get_interceptor_->GetHitCount()); 531 532 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 533 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count()); 534 535 component_updater()->Stop(); 536 } 537 538 // Test that a update check due to an on demand call can cause installs. 539 // Here is the timeline: 540 // - First loop: we return a reply that indicates no update, so 541 // nothing happens. 542 // - We make an on demand call. 543 // - This triggers a second loop, which has a reply that triggers an install. 544 TEST_F(ComponentUpdaterTest, OnDemandUpdate) { 545 MockComponentObserver observer1; 546 { 547 InSequence seq; 548 EXPECT_CALL(observer1, 549 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 550 .Times(1); 551 EXPECT_CALL(observer1, 552 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 553 .Times(1); 554 EXPECT_CALL(observer1, 555 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 556 .Times(1); 557 EXPECT_CALL(observer1, 558 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 559 .Times(1); 560 EXPECT_CALL(observer1, 561 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 562 .Times(1); 563 EXPECT_CALL(observer1, 564 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 565 .Times(1); 566 } 567 568 MockComponentObserver observer2; 569 { 570 InSequence seq; 571 EXPECT_CALL(observer2, 572 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 573 .Times(1); 574 EXPECT_CALL(observer2, 575 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 576 .Times(1); 577 EXPECT_CALL(observer2, 578 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 579 .Times(1); 580 EXPECT_CALL(observer2, 581 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 582 .Times(1); 583 EXPECT_CALL(observer2, 584 OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0)) 585 .Times(1); 586 EXPECT_CALL(observer2, 587 OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0)) 588 .Times(1); 589 EXPECT_CALL(observer2, 590 OnEvent(ComponentObserver::COMPONENT_UPDATED, 0)) 591 .Times(1); 592 EXPECT_CALL(observer2, 593 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 594 .Times(1); 595 } 596 597 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 598 "updatecheck"), test_file("updatecheck_reply_empty"))); 599 600 get_interceptor_->SetResponse( 601 GURL(expected_crx_url), 602 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); 603 604 TestInstaller installer1; 605 CrxComponent com1; 606 com1.observer = &observer1; 607 RegisterComponent(&com1, kTestComponent_abag, Version("2.2"), &installer1); 608 TestInstaller installer2; 609 CrxComponent com2; 610 com2.observer = &observer2; 611 RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"), &installer2); 612 613 // No update normally. 614 test_configurator()->SetLoopCount(1); 615 component_updater()->Start(); 616 RunThreads(); 617 component_updater()->Stop(); 618 619 EXPECT_EQ(1, post_interceptor_->GetHitCount()) 620 << post_interceptor_->GetRequestsAsString(); 621 EXPECT_EQ(1, post_interceptor_->GetCount()) 622 << post_interceptor_->GetRequestsAsString(); 623 624 EXPECT_EQ(0, get_interceptor_->GetHitCount()); 625 626 // Update after an on-demand check is issued. 627 post_interceptor_->Reset(); 628 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 629 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 630 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 631 632 EXPECT_EQ(ComponentUpdateService::kOk, 633 OnDemandTester::OnDemand(component_updater(), 634 GetCrxComponentID(com2))); 635 test_configurator()->SetLoopCount(1); 636 component_updater()->Start(); 637 RunThreads(); 638 639 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error()); 640 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count()); 641 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error()); 642 EXPECT_EQ(1, static_cast<TestInstaller*>(com2.installer)->install_count()); 643 644 EXPECT_EQ(2, post_interceptor_->GetHitCount()) 645 << post_interceptor_->GetRequestsAsString(); 646 EXPECT_EQ(2, post_interceptor_->GetCount()) 647 << post_interceptor_->GetRequestsAsString(); 648 649 EXPECT_EQ(1, get_interceptor_->GetHitCount()); 650 651 // Expect the update check to contain an "ondemand" request for the 652 // second component (com2) and a normal request for the other component. 653 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 654 "<app appid=\"abagagagagagagagagagagagagagagag\" " 655 "version=\"2.2\"><updatecheck /></app>")) 656 << post_interceptor_->GetRequestsAsString(); 657 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 658 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " 659 "version=\"0.9\" installsource=\"ondemand\"><updatecheck /></app>")) 660 << post_interceptor_->GetRequestsAsString(); 661 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 662 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " 663 "version=\"0.9\" nextversion=\"1.0\">" 664 "<event eventtype=\"3\" eventresult=\"1\"/>")) 665 << post_interceptor_->GetRequestsAsString(); 666 667 // Also check what happens if previous check too soon. 668 test_configurator()->SetOnDemandTime(60 * 60); 669 EXPECT_EQ(ComponentUpdateService::kError, 670 OnDemandTester::OnDemand(component_updater(), 671 GetCrxComponentID(com2))); 672 // Okay, now reset to 0 for the other tests. 673 test_configurator()->SetOnDemandTime(0); 674 component_updater()->Stop(); 675 676 // Test a few error cases. NOTE: We don't have callbacks for 677 // when the updates failed yet. 678 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1)); 679 { 680 InSequence seq; 681 EXPECT_CALL(observer1, 682 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 683 .Times(1); 684 EXPECT_CALL(observer1, 685 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 686 .Times(1); 687 EXPECT_CALL(observer1, 688 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 689 .Times(1); 690 } 691 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2)); 692 { 693 InSequence seq; 694 EXPECT_CALL(observer2, 695 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 696 .Times(1); 697 EXPECT_CALL(observer2, 698 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 699 .Times(1); 700 EXPECT_CALL(observer2, 701 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 702 .Times(1); 703 } 704 705 // No update: error from no server response 706 post_interceptor_->Reset(); 707 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 708 "updatecheck"), test_file("updatecheck_reply_empty"))); 709 710 test_configurator()->SetLoopCount(1); 711 component_updater()->Start(); 712 EXPECT_EQ(ComponentUpdateService::kOk, 713 OnDemandTester::OnDemand(component_updater(), 714 GetCrxComponentID(com2))); 715 RunThreads(); 716 component_updater()->Stop(); 717 718 EXPECT_EQ(1, post_interceptor_->GetHitCount()) 719 << post_interceptor_->GetRequestsAsString(); 720 EXPECT_EQ(1, post_interceptor_->GetCount()) 721 << post_interceptor_->GetRequestsAsString(); 722 723 // No update: already updated to 1.0 so nothing new 724 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1)); 725 { 726 InSequence seq; 727 EXPECT_CALL(observer1, 728 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 729 .Times(1); 730 EXPECT_CALL(observer1, 731 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 732 .Times(1); 733 EXPECT_CALL(observer1, 734 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 735 .Times(1); 736 } 737 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2)); 738 { 739 InSequence seq; 740 EXPECT_CALL(observer2, 741 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 742 .Times(1); 743 EXPECT_CALL(observer2, 744 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 745 .Times(1); 746 EXPECT_CALL(observer2, 747 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 748 .Times(1); 749 } 750 751 post_interceptor_->Reset(); 752 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 753 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 754 755 test_configurator()->SetLoopCount(1); 756 component_updater()->Start(); 757 EXPECT_EQ(ComponentUpdateService::kOk, 758 OnDemandTester::OnDemand(component_updater(), 759 GetCrxComponentID(com2))); 760 RunThreads(); 761 762 EXPECT_EQ(1, post_interceptor_->GetHitCount()) 763 << post_interceptor_->GetRequestsAsString(); 764 EXPECT_EQ(1, post_interceptor_->GetCount()) 765 << post_interceptor_->GetRequestsAsString(); 766 767 component_updater()->Stop(); 768 } 769 770 // Verify that a previously registered component can get re-registered 771 // with a different version. 772 TEST_F(ComponentUpdaterTest, CheckReRegistration) { 773 MockComponentObserver observer1; 774 { 775 InSequence seq; 776 EXPECT_CALL(observer1, 777 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 778 .Times(1); 779 EXPECT_CALL(observer1, 780 OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0)) 781 .Times(1); 782 EXPECT_CALL(observer1, 783 OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0)) 784 .Times(1); 785 EXPECT_CALL(observer1, 786 OnEvent(ComponentObserver::COMPONENT_UPDATED, 0)) 787 .Times(1); 788 EXPECT_CALL(observer1, 789 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 790 .Times(1); 791 EXPECT_CALL(observer1, 792 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 793 .Times(1); 794 EXPECT_CALL(observer1, 795 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 796 .Times(1); 797 } 798 799 MockComponentObserver observer2; 800 { 801 InSequence seq; 802 EXPECT_CALL(observer2, 803 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 804 .Times(1); 805 EXPECT_CALL(observer2, 806 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 807 .Times(1); 808 EXPECT_CALL(observer2, 809 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 810 .Times(1); 811 EXPECT_CALL(observer2, 812 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 813 .Times(1); 814 EXPECT_CALL(observer2, 815 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 816 .Times(1); 817 } 818 819 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 820 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 821 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 822 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 823 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 824 825 get_interceptor_->SetResponse( 826 GURL(expected_crx_url), 827 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); 828 829 TestInstaller installer1; 830 CrxComponent com1; 831 com1.observer = &observer1; 832 RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1); 833 TestInstaller installer2; 834 CrxComponent com2; 835 com2.observer = &observer2; 836 RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2); 837 838 // Loop twice to issue two checks: (1) with original 0.9 version, update to 839 // 1.0, and do the second check (2) with the updated 1.0 version. 840 test_configurator()->SetLoopCount(2); 841 component_updater()->Start(); 842 RunThreads(); 843 844 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error()); 845 EXPECT_EQ(1, static_cast<TestInstaller*>(com1.installer)->install_count()); 846 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error()); 847 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count()); 848 849 EXPECT_EQ(3, post_interceptor_->GetHitCount()) 850 << post_interceptor_->GetRequestsAsString(); 851 EXPECT_EQ(1, get_interceptor_->GetHitCount()); 852 853 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 854 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" 855 "<updatecheck /></app>")) 856 << post_interceptor_->GetRequestsAsString(); 857 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 858 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " 859 "version=\"0.9\" nextversion=\"1.0\">" 860 "<event eventtype=\"3\" eventresult=\"1\"/>")) 861 << post_interceptor_->GetRequestsAsString(); 862 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find( 863 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"1.0\">" 864 "<updatecheck /></app>")) 865 << post_interceptor_->GetRequestsAsString(); 866 867 component_updater()->Stop(); 868 869 // Now re-register, pretending to be an even newer version (2.2) 870 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1)); 871 { 872 InSequence seq; 873 EXPECT_CALL(observer1, 874 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 875 .Times(1); 876 EXPECT_CALL(observer1, 877 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 878 .Times(1); 879 EXPECT_CALL(observer1, 880 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 881 .Times(1); 882 } 883 884 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2)); 885 { 886 InSequence seq; 887 EXPECT_CALL(observer2, 888 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 889 .Times(1); 890 EXPECT_CALL(observer2, 891 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 892 .Times(1); 893 EXPECT_CALL(observer2, 894 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 895 .Times(1); 896 } 897 898 post_interceptor_->Reset(); 899 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 900 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 901 902 TestInstaller installer3; 903 EXPECT_EQ(ComponentUpdateService::kReplaced, 904 RegisterComponent(&com1, 905 kTestComponent_jebg, 906 Version("2.2"), 907 &installer3)); 908 909 // Loop once just to notice the check happening with the re-register version. 910 test_configurator()->SetLoopCount(1); 911 component_updater()->Start(); 912 RunThreads(); 913 914 // We created a new installer, so the counts go back to 0. 915 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error()); 916 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count()); 917 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error()); 918 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count()); 919 920 // One update check and no additional pings are expected. 921 EXPECT_EQ(1, post_interceptor_->GetHitCount()) 922 << post_interceptor_->GetRequestsAsString(); 923 EXPECT_EQ(1, post_interceptor_->GetCount()) 924 << post_interceptor_->GetRequestsAsString(); 925 926 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 927 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"2.2\">" 928 "<updatecheck /></app>")); 929 930 component_updater()->Stop(); 931 } 932 933 // Verify that we can download and install a component and a differential 934 // update to that component. We do three loops; the final loop should do 935 // nothing. 936 // We also check that exactly 5 non-ping network requests are issued: 937 // 1- update check (response: v1 available) 938 // 2- download crx (v1) 939 // 3- update check (response: v2 available) 940 // 4- download differential crx (v1 to v2) 941 // 5- update check (response: no further update available) 942 // There should be two pings, one for each update. The second will bear a 943 // diffresult=1, while the first will not. 944 TEST_F(ComponentUpdaterTest, DifferentialUpdate) { 945 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 946 "updatecheck"), test_file("updatecheck_diff_reply_1.xml"))); 947 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 948 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 949 "updatecheck"), test_file("updatecheck_diff_reply_2.xml"))); 950 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 951 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 952 "updatecheck"), test_file("updatecheck_diff_reply_3.xml"))); 953 954 get_interceptor_->SetResponse( 955 GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), 956 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx")); 957 get_interceptor_->SetResponse( 958 GURL("http://localhost/download/" 959 "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), 960 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx")); 961 962 VersionedTestInstaller installer; 963 CrxComponent com; 964 RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer); 965 966 test_configurator()->SetLoopCount(3); 967 component_updater()->Start(); 968 RunThreads(); 969 970 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 971 EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count()); 972 973 EXPECT_EQ(5, post_interceptor_->GetHitCount()) 974 << post_interceptor_->GetRequestsAsString(); 975 EXPECT_EQ(5, post_interceptor_->GetCount()) 976 << post_interceptor_->GetRequestsAsString(); 977 EXPECT_EQ(2, get_interceptor_->GetHitCount()); 978 979 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 980 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"0.0\">" 981 "<updatecheck /></app>")) 982 << post_interceptor_->GetRequestsAsString(); 983 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 984 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " 985 "version=\"0.0\" nextversion=\"1.0\">" 986 "<event eventtype=\"3\" eventresult=\"1\" nextfp=\"1\"/>")) 987 << post_interceptor_->GetRequestsAsString(); 988 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find( 989 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">" 990 "<updatecheck /><packages><package fp=\"1\"/></packages></app>")) 991 << post_interceptor_->GetRequestsAsString(); 992 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find( 993 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " 994 "version=\"1.0\" nextversion=\"2.0\">" 995 "<event eventtype=\"3\" eventresult=\"1\" diffresult=\"1\" " 996 "previousfp=\"1\" nextfp=\"22\"/>")) 997 << post_interceptor_->GetRequestsAsString(); 998 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[4].find( 999 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">" 1000 "<updatecheck /><packages><package fp=\"22\"/></packages></app>")) 1001 << post_interceptor_->GetRequestsAsString(); 1002 component_updater()->Stop(); 1003 } 1004 1005 // Verify that component installation falls back to downloading and installing 1006 // a full update if the differential update fails (in this case, because the 1007 // installer does not know about the existing files). We do two loops; the final 1008 // loop should do nothing. 1009 // We also check that exactly 4 non-ping network requests are issued: 1010 // 1- update check (loop 1) 1011 // 2- download differential crx 1012 // 3- download full crx 1013 // 4- update check (loop 2 - no update available) 1014 // There should be one ping for the first attempted update. 1015 TEST_F(ComponentUpdaterTest, DifferentialUpdateFails) { 1016 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1017 "updatecheck"), test_file("updatecheck_diff_reply_2.xml"))); 1018 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 1019 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1020 "updatecheck"), test_file("updatecheck_diff_reply_3.xml"))); 1021 1022 get_interceptor_->SetResponse( 1023 GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), 1024 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx")); 1025 get_interceptor_->SetResponse( 1026 GURL("http://localhost/download/" 1027 "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), 1028 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx")); 1029 get_interceptor_->SetResponse( 1030 GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"), 1031 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx")); 1032 1033 TestInstaller installer; 1034 CrxComponent com; 1035 RegisterComponent(&com, kTestComponent_ihfo, Version("1.0"), &installer); 1036 1037 test_configurator()->SetLoopCount(2); 1038 component_updater()->Start(); 1039 RunThreads(); 1040 1041 // A failed differential update does not count as a failed install. 1042 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 1043 EXPECT_EQ(1, static_cast<TestInstaller*>(com.installer)->install_count()); 1044 1045 EXPECT_EQ(3, post_interceptor_->GetHitCount()) 1046 << post_interceptor_->GetRequestsAsString(); 1047 EXPECT_EQ(3, post_interceptor_->GetCount()) 1048 << post_interceptor_->GetRequestsAsString(); 1049 EXPECT_EQ(2, get_interceptor_->GetHitCount()); 1050 1051 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 1052 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">" 1053 "<updatecheck /></app>")) 1054 << post_interceptor_->GetRequestsAsString(); 1055 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 1056 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " 1057 "version=\"1.0\" nextversion=\"2.0\">" 1058 "<event eventtype=\"3\" eventresult=\"1\" diffresult=\"0\" " 1059 "differrorcat=\"2\" differrorcode=\"16\" nextfp=\"22\"/>")) 1060 << post_interceptor_->GetRequestsAsString(); 1061 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find( 1062 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">" 1063 "<updatecheck /><packages><package fp=\"22\"/></packages></app>")) 1064 << post_interceptor_->GetRequestsAsString(); 1065 1066 component_updater()->Stop(); 1067 } 1068 1069 // Verify that a failed installation causes an install failure ping. 1070 TEST_F(ComponentUpdaterTest, CheckFailedInstallPing) { 1071 // This test installer reports installation failure. 1072 class : public TestInstaller { 1073 virtual bool Install(const base::DictionaryValue& manifest, 1074 const base::FilePath& unpack_path) OVERRIDE { 1075 ++install_count_; 1076 base::DeleteFile(unpack_path, true); 1077 return false; 1078 } 1079 } installer; 1080 1081 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1082 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 1083 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 1084 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1085 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 1086 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 1087 get_interceptor_->SetResponse( 1088 GURL(expected_crx_url), 1089 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); 1090 1091 // Start with 0.9, and attempt update to 1.0. 1092 // Loop twice to issue two checks: (1) with original 0.9 version 1093 // and (2), which should retry with 0.9. 1094 CrxComponent com; 1095 RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer); 1096 1097 test_configurator()->SetLoopCount(2); 1098 component_updater()->Start(); 1099 RunThreads(); 1100 1101 EXPECT_EQ(4, post_interceptor_->GetHitCount()) 1102 << post_interceptor_->GetRequestsAsString(); 1103 EXPECT_EQ(2, get_interceptor_->GetHitCount()); 1104 1105 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 1106 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" 1107 "<updatecheck /></app>")) 1108 << post_interceptor_->GetRequestsAsString(); 1109 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 1110 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " 1111 "version=\"0.9\" nextversion=\"1.0\">" 1112 "<event eventtype=\"3\" eventresult=\"0\" " 1113 "errorcat=\"3\" errorcode=\"9\"/>")) 1114 << post_interceptor_->GetRequestsAsString(); 1115 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find( 1116 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" 1117 "<updatecheck /></app>")) 1118 << post_interceptor_->GetRequestsAsString(); 1119 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find( 1120 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " 1121 "version=\"0.9\" nextversion=\"1.0\">" 1122 "<event eventtype=\"3\" eventresult=\"0\" " 1123 "errorcat=\"3\" errorcode=\"9\"/>")) 1124 << post_interceptor_->GetRequestsAsString(); 1125 1126 // Loop once more, but expect no ping because a noupdate response is issued. 1127 // This is necessary to clear out the fire-and-forget ping from the previous 1128 // iteration. 1129 post_interceptor_->Reset(); 1130 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1131 "updatecheck"), test_file("updatecheck_reply_noupdate.xml"))); 1132 1133 test_configurator()->SetLoopCount(1); 1134 component_updater()->Start(); 1135 RunThreads(); 1136 1137 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 1138 EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count()); 1139 1140 EXPECT_EQ(1, post_interceptor_->GetHitCount()) 1141 << post_interceptor_->GetRequestsAsString(); 1142 EXPECT_EQ(1, post_interceptor_->GetCount()) 1143 << post_interceptor_->GetRequestsAsString(); 1144 1145 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 1146 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" 1147 "<updatecheck /></app>")) 1148 << post_interceptor_->GetRequestsAsString(); 1149 1150 component_updater()->Stop(); 1151 } 1152 1153 // Verify that we successfully propagate a patcher error. 1154 // ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx contains an incorrect 1155 // patching instruction that should fail. 1156 TEST_F(ComponentUpdaterTest, DifferentialUpdateFailErrorcode) { 1157 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1158 "updatecheck"), test_file("updatecheck_diff_reply_1.xml"))); 1159 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 1160 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1161 "updatecheck"), test_file("updatecheck_diff_reply_2.xml"))); 1162 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 1163 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1164 "updatecheck"), test_file("updatecheck_diff_reply_3.xml"))); 1165 1166 get_interceptor_->SetResponse( 1167 GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), 1168 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx")); 1169 // This intercept returns a different file than what is specified in the 1170 // update check response and requested in the download. The file that is 1171 // actually dowloaded contains a patching error, an therefore, an error 1172 // is injected at the time of patching. 1173 get_interceptor_->SetResponse( 1174 GURL("http://localhost/download/" 1175 "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), 1176 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx")); 1177 get_interceptor_->SetResponse( 1178 GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"), 1179 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx")); 1180 1181 VersionedTestInstaller installer; 1182 CrxComponent com; 1183 RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer); 1184 1185 test_configurator()->SetLoopCount(3); 1186 component_updater()->Start(); 1187 RunThreads(); 1188 component_updater()->Stop(); 1189 1190 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 1191 EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count()); 1192 1193 EXPECT_EQ(5, post_interceptor_->GetHitCount()) 1194 << post_interceptor_->GetRequestsAsString(); 1195 EXPECT_EQ(5, post_interceptor_->GetCount()) 1196 << post_interceptor_->GetRequestsAsString(); 1197 EXPECT_EQ(3, get_interceptor_->GetHitCount()); 1198 1199 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 1200 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"0.0\">" 1201 "<updatecheck /></app>")) 1202 << post_interceptor_->GetRequestsAsString(); 1203 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 1204 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " 1205 "version=\"0.0\" nextversion=\"1.0\">" 1206 "<event eventtype=\"3\" eventresult=\"1\" nextfp=\"1\"/>")) 1207 << post_interceptor_->GetRequestsAsString(); 1208 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find( 1209 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">" 1210 "<updatecheck /><packages><package fp=\"1\"/></packages></app>")) 1211 << post_interceptor_->GetRequestsAsString(); 1212 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find( 1213 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " 1214 "version=\"1.0\" nextversion=\"2.0\">" 1215 "<event eventtype=\"3\" eventresult=\"1\" " 1216 "diffresult=\"0\" differrorcat=\"2\" " 1217 "differrorcode=\"14\" diffextracode1=\"305\" " 1218 "previousfp=\"1\" nextfp=\"22\"/>")) 1219 << post_interceptor_->GetRequestsAsString(); 1220 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[4].find( 1221 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">" 1222 "<updatecheck /><packages><package fp=\"22\"/></packages></app>")) 1223 << post_interceptor_->GetRequestsAsString(); 1224 } 1225 1226 class TestResourceController : public content::ResourceController { 1227 public: 1228 virtual void SetThrottle(content::ResourceThrottle* throttle) {} 1229 }; 1230 1231 content::ResourceThrottle* RequestTestResourceThrottle( 1232 ComponentUpdateService* cus, 1233 TestResourceController* controller, 1234 const char* crx_id) { 1235 1236 net::TestURLRequestContext context; 1237 net::TestURLRequest url_request( 1238 GURL("http://foo.example.com/thing.bin"), 1239 net::DEFAULT_PRIORITY, 1240 NULL, 1241 &context); 1242 1243 content::ResourceThrottle* rt = 1244 cus->GetOnDemandResourceThrottle(&url_request, crx_id); 1245 rt->set_controller_for_testing(controller); 1246 controller->SetThrottle(rt); 1247 return rt; 1248 } 1249 1250 void RequestAndDeleteResourceThrottle( 1251 ComponentUpdateService* cus, const char* crx_id) { 1252 // By requesting a throttle and deleting it immediately we ensure that we 1253 // hit the case where the component updater tries to use the weak 1254 // pointer to a dead Resource throttle. 1255 class NoCallResourceController : public TestResourceController { 1256 public: 1257 virtual ~NoCallResourceController() {} 1258 virtual void Cancel() OVERRIDE { CHECK(false); } 1259 virtual void CancelAndIgnore() OVERRIDE { CHECK(false); } 1260 virtual void CancelWithError(int error_code) OVERRIDE { CHECK(false); } 1261 virtual void Resume() OVERRIDE { CHECK(false); } 1262 } controller; 1263 1264 delete RequestTestResourceThrottle(cus, &controller, crx_id); 1265 } 1266 1267 TEST_F(ComponentUpdaterTest, ResourceThrottleDeletedNoUpdate) { 1268 MockComponentObserver observer; 1269 EXPECT_CALL(observer, 1270 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 1271 .Times(1); 1272 EXPECT_CALL(observer, 1273 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 1274 .Times(1); 1275 EXPECT_CALL(observer, 1276 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 1277 .Times(1); 1278 1279 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1280 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 1281 1282 TestInstaller installer; 1283 CrxComponent com; 1284 com.observer = &observer; 1285 EXPECT_EQ(ComponentUpdateService::kOk, 1286 RegisterComponent(&com, 1287 kTestComponent_abag, 1288 Version("1.1"), 1289 &installer)); 1290 // The following two calls ensure that we don't do an update check via the 1291 // timer, so the only update check should be the on-demand one. 1292 test_configurator()->SetInitialDelay(1000000); 1293 test_configurator()->SetRecheckTime(1000000); 1294 test_configurator()->SetLoopCount(1); 1295 component_updater()->Start(); 1296 1297 RunThreadsUntilIdle(); 1298 1299 EXPECT_EQ(0, post_interceptor_->GetHitCount()); 1300 1301 BrowserThread::PostTask( 1302 BrowserThread::IO, 1303 FROM_HERE, 1304 base::Bind(&RequestAndDeleteResourceThrottle, 1305 component_updater(), 1306 "abagagagagagagagagagagagagagagag")); 1307 1308 RunThreads(); 1309 1310 EXPECT_EQ(1, post_interceptor_->GetHitCount()); 1311 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 1312 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count()); 1313 1314 component_updater()->Stop(); 1315 } 1316 1317 class CancelResourceController: public TestResourceController { 1318 public: 1319 CancelResourceController() : throttle_(NULL), resume_called_(0) {} 1320 virtual ~CancelResourceController() { 1321 // Check that the throttle has been resumed by the time we 1322 // exit the test. 1323 CHECK(resume_called_ == 1); 1324 delete throttle_; 1325 } 1326 virtual void Cancel() OVERRIDE { CHECK(false); } 1327 virtual void CancelAndIgnore() OVERRIDE { CHECK(false); } 1328 virtual void CancelWithError(int error_code) OVERRIDE { CHECK(false); } 1329 virtual void Resume() OVERRIDE { 1330 BrowserThread::PostTask( 1331 BrowserThread::IO, 1332 FROM_HERE, 1333 base::Bind(&CancelResourceController::ResumeCalled, 1334 base::Unretained(this))); 1335 } 1336 virtual void SetThrottle(content::ResourceThrottle* throttle) OVERRIDE { 1337 throttle_ = throttle; 1338 bool defer = false; 1339 // Initially the throttle is blocked. The CUS needs to run a 1340 // task on the UI thread to decide if it should unblock. 1341 throttle_->WillStartRequest(&defer); 1342 CHECK(defer); 1343 } 1344 1345 private: 1346 void ResumeCalled() { ++resume_called_; } 1347 1348 content::ResourceThrottle* throttle_; 1349 int resume_called_; 1350 }; 1351 1352 TEST_F(ComponentUpdaterTest, ResourceThrottleLiveNoUpdate) { 1353 MockComponentObserver observer; 1354 EXPECT_CALL(observer, 1355 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 1356 .Times(1); 1357 EXPECT_CALL(observer, 1358 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 1359 .Times(1); 1360 EXPECT_CALL(observer, 1361 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 1362 .Times(1); 1363 1364 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1365 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 1366 1367 TestInstaller installer; 1368 CrxComponent com; 1369 com.observer = &observer; 1370 EXPECT_EQ(ComponentUpdateService::kOk, 1371 RegisterComponent(&com, 1372 kTestComponent_abag, 1373 Version("1.1"), 1374 &installer)); 1375 // The following two calls ensure that we don't do an update check via the 1376 // timer, so the only update check should be the on-demand one. 1377 test_configurator()->SetInitialDelay(1000000); 1378 test_configurator()->SetRecheckTime(1000000); 1379 test_configurator()->SetLoopCount(1); 1380 component_updater()->Start(); 1381 1382 RunThreadsUntilIdle(); 1383 1384 EXPECT_EQ(0, post_interceptor_->GetHitCount()); 1385 1386 CancelResourceController controller; 1387 1388 BrowserThread::PostTask( 1389 BrowserThread::IO, 1390 FROM_HERE, 1391 base::Bind(base::IgnoreResult(&RequestTestResourceThrottle), 1392 component_updater(), 1393 &controller, 1394 "abagagagagagagagagagagagagagagag")); 1395 1396 RunThreads(); 1397 1398 EXPECT_EQ(1, post_interceptor_->GetHitCount()); 1399 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 1400 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count()); 1401 1402 component_updater()->Stop(); 1403 } 1404 1405 1406 } // namespace component_updater 1407 1408