OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/component_updater/component_updater_service.h" | 5 #include "chrome/browser/component_updater/component_updater_service.h" |
6 | 6 |
| 7 #include <list> |
| 8 #include <utility> |
| 9 |
7 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
8 #include "base/file_path.h" | 11 #include "base/file_path.h" |
9 #include "base/file_util.h" | 12 #include "base/file_util.h" |
10 #include "base/memory/scoped_vector.h" | 13 #include "base/memory/scoped_vector.h" |
11 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
12 #include "base/path_service.h" | 15 #include "base/path_service.h" |
13 #include "base/values.h" | 16 #include "base/values.h" |
14 #include "chrome/common/chrome_notification_types.h" | 17 #include "chrome/common/chrome_notification_types.h" |
15 #include "chrome/common/chrome_paths.h" | 18 #include "chrome/common/chrome_paths.h" |
16 #include "content/public/browser/notification_observer.h" | 19 #include "content/public/browser/notification_observer.h" |
17 #include "content/public/browser/notification_service.h" | 20 #include "content/public/browser/notification_service.h" |
18 #include "content/public/test/test_browser_thread.h" | 21 #include "content/public/test/test_browser_thread.h" |
19 #include "content/public/test/test_notification_tracker.h" | 22 #include "content/public/test/test_notification_tracker.h" |
20 #include "content/test/net/url_request_prepackaged_interceptor.h" | 23 #include "content/test/net/url_request_prepackaged_interceptor.h" |
21 #include "googleurl/src/gurl.h" | 24 #include "googleurl/src/gurl.h" |
22 #include "libxml/globals.h" | 25 #include "libxml/globals.h" |
23 #include "net/url_request/url_fetcher.h" | 26 #include "net/url_request/url_fetcher.h" |
24 #include "net/url_request/url_request_test_util.h" | 27 #include "net/url_request/url_request_test_util.h" |
25 #include "testing/gtest/include/gtest/gtest.h" | 28 #include "testing/gtest/include/gtest/gtest.h" |
26 | 29 |
27 using content::BrowserThread; | 30 using content::BrowserThread; |
28 using content::TestNotificationTracker; | 31 using content::TestNotificationTracker; |
29 | 32 |
30 namespace { | 33 namespace { |
31 // Overrides some of the component updater behaviors so it is easier to test | 34 // Overrides some of the component updater behaviors so it is easier to test |
32 // and loops faster. In actual usage it takes hours do to a full cycle. | 35 // and loops faster. In actual usage it takes hours do to a full cycle. |
33 class TestConfigurator : public ComponentUpdateService::Configurator { | 36 class TestConfigurator : public ComponentUpdateService::Configurator { |
34 public: | 37 public: |
35 TestConfigurator() : times_(1), recheck_time_(0) { | 38 TestConfigurator() |
| 39 : times_(1), recheck_time_(0), ondemand_time_(0), cus_(NULL) { |
36 } | 40 } |
37 | 41 |
38 virtual int InitialDelay() OVERRIDE { return 0; } | 42 virtual int InitialDelay() OVERRIDE { return 0; } |
39 | 43 |
| 44 typedef std::pair<CrxComponent*, int> CheckAtLoopCount; |
| 45 |
40 virtual int NextCheckDelay() OVERRIDE { | 46 virtual int NextCheckDelay() OVERRIDE { |
41 // This is called when a new full cycle of checking for updates is going | 47 // This is called when a new full cycle of checking for updates is going |
42 // to happen. In test we normally only test one cycle so it is a good | 48 // to happen. In test we normally only test one cycle so it is a good |
43 // time to break from the test messageloop Run() method so the test can | 49 // time to break from the test messageloop Run() method so the test can |
44 // finish. | 50 // finish. |
45 if (--times_ > 0) | 51 if (--times_ <= 0) { |
46 return 1; | 52 MessageLoop::current()->Quit(); |
| 53 return 0; |
47 | 54 |
48 MessageLoop::current()->Quit(); | 55 } |
49 return 0; | 56 |
| 57 // Look for checks to issue in the middle of the loop. |
| 58 for (std::list<CheckAtLoopCount>::iterator |
| 59 i = components_to_check_.begin(); |
| 60 i != components_to_check_.end(); ) { |
| 61 if (i->second == times_) { |
| 62 cus_->CheckForUpdateSoon(*i->first); |
| 63 i = components_to_check_.erase(i); |
| 64 } else { |
| 65 ++i; |
| 66 } |
| 67 } |
| 68 return 1; |
50 } | 69 } |
51 | 70 |
52 virtual int StepDelay() OVERRIDE { | 71 virtual int StepDelay() OVERRIDE { |
53 return 0; | 72 return 0; |
54 } | 73 } |
55 | 74 |
56 virtual int MinimumReCheckWait() OVERRIDE { | 75 virtual int MinimumReCheckWait() OVERRIDE { |
57 return recheck_time_; | 76 return recheck_time_; |
58 } | 77 } |
59 | 78 |
| 79 virtual int OnDemandDelay() OVERRIDE { |
| 80 return ondemand_time_; |
| 81 } |
| 82 |
60 virtual GURL UpdateUrl(CrxComponent::UrlSource source) OVERRIDE { | 83 virtual GURL UpdateUrl(CrxComponent::UrlSource source) OVERRIDE { |
61 switch (source) { | 84 switch (source) { |
62 case CrxComponent::BANDAID: | 85 case CrxComponent::BANDAID: |
63 return GURL("http://localhost/upd"); | 86 return GURL("http://localhost/upd"); |
64 case CrxComponent::CWS_PUBLIC: | 87 case CrxComponent::CWS_PUBLIC: |
65 return GURL("http://localhost/cws"); | 88 return GURL("http://localhost/cws"); |
66 default: | 89 default: |
67 return GURL("http://wronghost/bad"); | 90 return GURL("http://wronghost/bad"); |
68 }; | 91 }; |
69 } | 92 } |
(...skipping 12 matching lines...) Expand all Loading... |
82 | 105 |
83 virtual void OnEvent(Events event, int extra) OVERRIDE { } | 106 virtual void OnEvent(Events event, int extra) OVERRIDE { } |
84 | 107 |
85 // Set how many update checks are called, the default value is just once. | 108 // Set how many update checks are called, the default value is just once. |
86 void SetLoopCount(int times) { times_ = times; } | 109 void SetLoopCount(int times) { times_ = times; } |
87 | 110 |
88 void SetRecheckTime(int seconds) { | 111 void SetRecheckTime(int seconds) { |
89 recheck_time_ = seconds; | 112 recheck_time_ = seconds; |
90 } | 113 } |
91 | 114 |
| 115 void SetOnDemandTime(int seconds) { |
| 116 ondemand_time_ = seconds; |
| 117 } |
| 118 |
| 119 void AddComponentToCheck(CrxComponent* com, int at_loop_iter) { |
| 120 components_to_check_.push_back(std::make_pair(com, at_loop_iter)); |
| 121 } |
| 122 |
| 123 void SetComponentUpdateService(ComponentUpdateService* cus) { |
| 124 cus_ = cus; |
| 125 } |
| 126 |
92 private: | 127 private: |
93 int times_; | 128 int times_; |
94 int recheck_time_; | 129 int recheck_time_; |
| 130 int ondemand_time_; |
| 131 |
| 132 std::list<CheckAtLoopCount> components_to_check_; |
| 133 ComponentUpdateService* cus_; |
95 }; | 134 }; |
96 | 135 |
97 class TestInstaller : public ComponentInstaller { | 136 class TestInstaller : public ComponentInstaller { |
98 public : | 137 public : |
99 explicit TestInstaller() | 138 explicit TestInstaller() |
100 : error_(0), install_count_(0) { | 139 : error_(0), install_count_(0) { |
101 } | 140 } |
102 | 141 |
103 virtual void OnUpdateError(int error) OVERRIDE { | 142 virtual void OnUpdateError(int error) OVERRIDE { |
104 EXPECT_NE(0, error); | 143 EXPECT_NE(0, error); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 public: | 183 public: |
145 enum TestComponents { | 184 enum TestComponents { |
146 kTestComponent_abag, | 185 kTestComponent_abag, |
147 kTestComponent_jebg | 186 kTestComponent_jebg |
148 }; | 187 }; |
149 | 188 |
150 ComponentUpdaterTest() : component_updater_(NULL), test_config_(NULL) { | 189 ComponentUpdaterTest() : component_updater_(NULL), test_config_(NULL) { |
151 // The component updater instance under test. | 190 // The component updater instance under test. |
152 test_config_ = new TestConfigurator; | 191 test_config_ = new TestConfigurator; |
153 component_updater_.reset(ComponentUpdateServiceFactory(test_config_)); | 192 component_updater_.reset(ComponentUpdateServiceFactory(test_config_)); |
| 193 test_config_->SetComponentUpdateService(component_updater_.get()); |
154 // The test directory is chrome/test/data/components. | 194 // The test directory is chrome/test/data/components. |
155 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_); | 195 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_); |
156 test_data_dir_ = test_data_dir_.AppendASCII("components"); | 196 test_data_dir_ = test_data_dir_.AppendASCII("components"); |
157 | 197 |
158 // Subscribe to all component updater notifications. | 198 // Subscribe to all component updater notifications. |
159 const int notifications[] = { | 199 const int notifications[] = { |
160 chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, | 200 chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, |
161 chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, | 201 chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, |
162 chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, | 202 chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, |
163 chrome::NOTIFICATION_COMPONENT_UPDATE_READY | 203 chrome::NOTIFICATION_COMPONENT_UPDATE_READY |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 TestNotificationTracker::Event ev1 = notification_tracker().at(1); | 413 TestNotificationTracker::Event ev1 = notification_tracker().at(1); |
374 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type); | 414 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type); |
375 | 415 |
376 TestNotificationTracker::Event ev2 = notification_tracker().at(2); | 416 TestNotificationTracker::Event ev2 = notification_tracker().at(2); |
377 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type); | 417 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type); |
378 | 418 |
379 TestNotificationTracker::Event ev3 = notification_tracker().at(3); | 419 TestNotificationTracker::Event ev3 = notification_tracker().at(3); |
380 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type); | 420 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type); |
381 | 421 |
382 TestNotificationTracker::Event ev4 = notification_tracker().at(4); | 422 TestNotificationTracker::Event ev4 = notification_tracker().at(4); |
383 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type); | 423 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type); |
384 | 424 |
385 component_updater()->Stop(); | 425 component_updater()->Stop(); |
386 } | 426 } |
387 | 427 |
388 // This test is like the above InstallCrx but the second component | 428 // This test is like the above InstallCrx but the second component |
389 // has a different source. In this case there would be two manifest | 429 // has a different source. In this case there would be two manifest |
390 // checks to different urls, each only containing one component. | 430 // checks to different urls, each only containing one component. |
391 TEST_F(ComponentUpdaterTest, InstallCrxTwoSources) { | 431 TEST_F(ComponentUpdaterTest, InstallCrxTwoSources) { |
392 MessageLoop message_loop; | 432 MessageLoop message_loop; |
393 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); | 433 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 TestNotificationTracker::Event ev1 = notification_tracker().at(2); | 485 TestNotificationTracker::Event ev1 = notification_tracker().at(2); |
446 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type); | 486 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type); |
447 | 487 |
448 TestNotificationTracker::Event ev2 = notification_tracker().at(3); | 488 TestNotificationTracker::Event ev2 = notification_tracker().at(3); |
449 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type); | 489 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type); |
450 | 490 |
451 TestNotificationTracker::Event ev3 = notification_tracker().at(4); | 491 TestNotificationTracker::Event ev3 = notification_tracker().at(4); |
452 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type); | 492 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type); |
453 | 493 |
454 TestNotificationTracker::Event ev4 = notification_tracker().at(5); | 494 TestNotificationTracker::Event ev4 = notification_tracker().at(5); |
455 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type); | 495 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type); |
456 | 496 |
457 component_updater()->Stop(); | 497 component_updater()->Stop(); |
458 } | 498 } |
459 | 499 |
460 // This test checks that the "prodversionmin" value is handled correctly. In | 500 // This test checks that the "prodversionmin" value is handled correctly. In |
461 // particular there should not be an install because the minimum product | 501 // particular there should not be an install because the minimum product |
462 // version is much higher than of chrome. | 502 // version is much higher than of chrome. |
463 TEST_F(ComponentUpdaterTest, ProdVersionCheck) { | 503 TEST_F(ComponentUpdaterTest, ProdVersionCheck) { |
464 MessageLoop message_loop; | 504 MessageLoop message_loop; |
465 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); | 505 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); |
(...skipping 20 matching lines...) Expand all Loading... |
486 test_configurator()->SetLoopCount(1); | 526 test_configurator()->SetLoopCount(1); |
487 component_updater()->Start(); | 527 component_updater()->Start(); |
488 message_loop.Run(); | 528 message_loop.Run(); |
489 | 529 |
490 EXPECT_EQ(1, interceptor.GetHitCount()); | 530 EXPECT_EQ(1, interceptor.GetHitCount()); |
491 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); | 531 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); |
492 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count()); | 532 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count()); |
493 | 533 |
494 component_updater()->Stop(); | 534 component_updater()->Stop(); |
495 } | 535 } |
| 536 |
| 537 // Test that a ping for an update check can cause installs. |
| 538 // Here is the timeline: |
| 539 // - First loop: we return a reply that indicates no update, so |
| 540 // nothing happens. |
| 541 // - We ping. |
| 542 // - This triggers a second loop, which has a reply that triggers an install. |
| 543 TEST_F(ComponentUpdaterTest, CheckForUpdateSoon) { |
| 544 MessageLoop message_loop; |
| 545 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); |
| 546 content::TestBrowserThread file_thread(BrowserThread::FILE); |
| 547 content::TestBrowserThread io_thread(BrowserThread::IO); |
| 548 |
| 549 io_thread.StartIOThread(); |
| 550 file_thread.Start(); |
| 551 |
| 552 content::URLRequestPrepackagedInterceptor interceptor; |
| 553 |
| 554 CrxComponent com1; |
| 555 RegisterComponent(&com1, kTestComponent_abag, Version("2.2")); |
| 556 CrxComponent com2; |
| 557 RegisterComponent(&com2, kTestComponent_jebg, Version("0.9")); |
| 558 |
| 559 const GURL expected_update_url_1( |
| 560 "http://localhost/upd?extra=foo&x=id%3D" |
| 561 "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc&x=id%3D" |
| 562 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc"); |
| 563 |
| 564 const GURL expected_update_url_2( |
| 565 "http://localhost/upd?extra=foo&x=id%3D" |
| 566 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc&x=id%3D" |
| 567 "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc"); |
| 568 |
| 569 interceptor.SetResponse(expected_update_url_1, |
| 570 test_file("updatecheck_reply_empty")); |
| 571 interceptor.SetResponse(expected_update_url_2, |
| 572 test_file("updatecheck_reply_1.xml")); |
| 573 interceptor.SetResponse(GURL(expected_crx_url), |
| 574 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); |
| 575 // Test success. |
| 576 test_configurator()->SetLoopCount(2); |
| 577 test_configurator()->AddComponentToCheck(&com2, 1); |
| 578 component_updater()->Start(); |
| 579 message_loop.Run(); |
| 580 |
| 581 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error()); |
| 582 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count()); |
| 583 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error()); |
| 584 EXPECT_EQ(1, static_cast<TestInstaller*>(com2.installer)->install_count()); |
| 585 |
| 586 EXPECT_EQ(3, interceptor.GetHitCount()); |
| 587 |
| 588 ASSERT_EQ(5ul, notification_tracker().size()); |
| 589 |
| 590 TestNotificationTracker::Event ev0= notification_tracker().at(0); |
| 591 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type); |
| 592 |
| 593 TestNotificationTracker::Event ev1 = notification_tracker().at(1); |
| 594 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type); |
| 595 |
| 596 TestNotificationTracker::Event ev2 = notification_tracker().at(2); |
| 597 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev2.type); |
| 598 |
| 599 TestNotificationTracker::Event ev3 = notification_tracker().at(3); |
| 600 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev3.type); |
| 601 |
| 602 TestNotificationTracker::Event ev4 = notification_tracker().at(4); |
| 603 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type); |
| 604 |
| 605 // Also check what happens if previous check too soon. |
| 606 test_configurator()->SetOnDemandTime(60 * 60); |
| 607 EXPECT_EQ(ComponentUpdateService::kError, |
| 608 component_updater()->CheckForUpdateSoon(com2)); |
| 609 // Okay, now reset to 0 for the other tests. |
| 610 test_configurator()->SetOnDemandTime(0); |
| 611 component_updater()->Stop(); |
| 612 |
| 613 // Test a few error cases. NOTE: We don't have callbacks for |
| 614 // when the updates failed yet. |
| 615 const GURL expected_update_url_3( |
| 616 "http://localhost/upd?extra=foo&x=id%3D" |
| 617 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26uc&x=id%3D" |
| 618 "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc"); |
| 619 |
| 620 // No update: error from no server response |
| 621 interceptor.SetResponse(expected_update_url_3, |
| 622 test_file("updatecheck_reply_empty")); |
| 623 notification_tracker().Reset(); |
| 624 test_configurator()->SetLoopCount(1); |
| 625 component_updater()->Start(); |
| 626 EXPECT_EQ(ComponentUpdateService::kOk, |
| 627 component_updater()->CheckForUpdateSoon(com2)); |
| 628 |
| 629 message_loop.Run(); |
| 630 |
| 631 ASSERT_EQ(2ul, notification_tracker().size()); |
| 632 ev0 = notification_tracker().at(0); |
| 633 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type); |
| 634 ev1 = notification_tracker().at(1); |
| 635 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type); |
| 636 component_updater()->Stop(); |
| 637 |
| 638 // No update: already updated to 1.0 so nothing new |
| 639 interceptor.SetResponse(expected_update_url_3, |
| 640 test_file("updatecheck_reply_1.xml")); |
| 641 notification_tracker().Reset(); |
| 642 test_configurator()->SetLoopCount(1); |
| 643 component_updater()->Start(); |
| 644 EXPECT_EQ(ComponentUpdateService::kOk, |
| 645 component_updater()->CheckForUpdateSoon(com2)); |
| 646 |
| 647 message_loop.Run(); |
| 648 |
| 649 ASSERT_EQ(2ul, notification_tracker().size()); |
| 650 ev0 = notification_tracker().at(0); |
| 651 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type); |
| 652 ev1 = notification_tracker().at(1); |
| 653 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type); |
| 654 component_updater()->Stop(); |
| 655 } |
OLD | NEW |