Home | History | Annotate | Download | only in screens
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/command_line.h"
      6 #include "base/memory/scoped_ptr.h"
      7 #include "chrome/browser/chromeos/login/screens/mock_error_screen.h"
      8 #include "chrome/browser/chromeos/login/screens/mock_screen_observer.h"
      9 #include "chrome/browser/chromeos/login/screens/update_screen.h"
     10 #include "chrome/browser/chromeos/login/wizard_controller.h"
     11 #include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h"
     12 #include "chrome/browser/chromeos/net/network_portal_detector.h"
     13 #include "chrome/browser/chromeos/net/network_portal_detector_stub.h"
     14 #include "chromeos/chromeos_switches.h"
     15 #include "chromeos/dbus/fake_update_engine_client.h"
     16 #include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h"
     17 #include "testing/gmock/include/gmock/gmock.h"
     18 #include "testing/gtest/include/gtest/gtest.h"
     19 
     20 using ::testing::AnyNumber;
     21 using ::testing::AtLeast;
     22 using ::testing::Exactly;
     23 using ::testing::Invoke;
     24 using ::testing::Return;
     25 using ::testing::_;
     26 
     27 namespace chromeos {
     28 
     29 namespace {
     30 
     31 const char kStubEthernetServicePath[] = "eth0";
     32 const char kStubWifiServicePath[] = "wlan0";
     33 
     34 }  // namespace
     35 
     36 class UpdateScreenTest : public WizardInProcessBrowserTest {
     37  public:
     38   UpdateScreenTest() : WizardInProcessBrowserTest("update"),
     39                        fake_update_engine_client_(NULL),
     40                        network_portal_detector_stub_(NULL) {
     41   }
     42 
     43  protected:
     44   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
     45     MockDBusThreadManagerWithoutGMock* mock_dbus_thread_manager =
     46         new MockDBusThreadManagerWithoutGMock;
     47     DBusThreadManager::InitializeForTesting(mock_dbus_thread_manager);
     48     WizardInProcessBrowserTest::SetUpInProcessBrowserTestFixture();
     49 
     50     fake_update_engine_client_
     51         = mock_dbus_thread_manager->fake_update_engine_client();
     52 
     53     // Setup network portal detector to return online state for both
     54     // ethernet and wifi networks. Ethernet is an active network by
     55     // default.
     56     network_portal_detector_stub_ =
     57         static_cast<NetworkPortalDetectorStub*>(
     58             NetworkPortalDetector::GetInstance());
     59     NetworkPortalDetector::CaptivePortalState online_state;
     60     online_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE;
     61     online_state.response_code = 204;
     62     SetDefaultNetworkPath(kStubEthernetServicePath);
     63     SetDetectionResults(kStubEthernetServicePath, online_state);
     64     SetDetectionResults(kStubWifiServicePath, online_state);
     65   }
     66 
     67   virtual void SetUpOnMainThread() OVERRIDE {
     68     WizardInProcessBrowserTest::SetUpOnMainThread();
     69 
     70     mock_screen_observer_.reset(new MockScreenObserver());
     71     mock_error_screen_actor_.reset(new MockErrorScreenActor());
     72     mock_error_screen_.reset(
     73         new MockErrorScreen(mock_screen_observer_.get(),
     74                             mock_error_screen_actor_.get()));
     75     EXPECT_CALL(*mock_screen_observer_, ShowCurrentScreen())
     76         .Times(AnyNumber());
     77     EXPECT_CALL(*mock_screen_observer_, GetErrorScreen())
     78         .Times(AnyNumber())
     79         .WillRepeatedly(Return(mock_error_screen_.get()));
     80 
     81     ASSERT_TRUE(WizardController::default_controller() != NULL);
     82     update_screen_ = WizardController::default_controller()->GetUpdateScreen();
     83     ASSERT_TRUE(update_screen_ != NULL);
     84     ASSERT_EQ(WizardController::default_controller()->current_screen(),
     85               update_screen_);
     86     update_screen_->screen_observer_ = mock_screen_observer_.get();
     87   }
     88 
     89   virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
     90     WizardInProcessBrowserTest::TearDownInProcessBrowserTestFixture();
     91     DBusThreadManager::Shutdown();
     92   }
     93 
     94   void SetDefaultNetworkPath(const std::string& service_path) {
     95     DCHECK(network_portal_detector_stub_);
     96     network_portal_detector_stub_->SetDefaultNetworkPathForTesting(
     97         service_path);
     98   }
     99 
    100   void SetDetectionResults(
    101       const std::string& service_path,
    102       const NetworkPortalDetector::CaptivePortalState& state) {
    103     DCHECK(network_portal_detector_stub_);
    104     network_portal_detector_stub_->SetDetectionResultsForTesting(service_path,
    105                                                                  state);
    106   }
    107 
    108   void NotifyPortalDetectionCompleted() {
    109     DCHECK(network_portal_detector_stub_);
    110     network_portal_detector_stub_->NotifyObserversForTesting();
    111   }
    112 
    113   FakeUpdateEngineClient* fake_update_engine_client_;
    114   scoped_ptr<MockScreenObserver> mock_screen_observer_;
    115   scoped_ptr<MockErrorScreenActor> mock_error_screen_actor_;
    116   scoped_ptr<MockErrorScreen> mock_error_screen_;
    117   UpdateScreen* update_screen_;
    118   NetworkPortalDetectorStub* network_portal_detector_stub_;
    119 
    120  private:
    121   DISALLOW_COPY_AND_ASSIGN(UpdateScreenTest);
    122 };
    123 
    124 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestBasic) {
    125   ASSERT_TRUE(update_screen_->actor_ != NULL);
    126 }
    127 
    128 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestNoUpdate) {
    129   update_screen_->SetIgnoreIdleStatus(true);
    130   UpdateEngineClient::Status status;
    131   status.status = UpdateEngineClient::UPDATE_STATUS_IDLE;
    132   update_screen_->UpdateStatusChanged(status);
    133   status.status = UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE;
    134   update_screen_->UpdateStatusChanged(status);
    135   status.status = UpdateEngineClient::UPDATE_STATUS_IDLE;
    136   // GetLastStatus() will be called via ExitUpdate() called from
    137   // UpdateStatusChanged().
    138   fake_update_engine_client_->set_default_status(status);
    139 
    140   EXPECT_CALL(*mock_screen_observer_, OnExit(ScreenObserver::UPDATE_NOUPDATE))
    141       .Times(1);
    142   update_screen_->UpdateStatusChanged(status);
    143 }
    144 
    145 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestUpdateAvailable) {
    146   update_screen_->is_ignore_update_deadlines_ = true;
    147 
    148   UpdateEngineClient::Status status;
    149   status.status = UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE;
    150   status.new_version = "latest and greatest";
    151   update_screen_->UpdateStatusChanged(status);
    152 
    153   status.status = UpdateEngineClient::UPDATE_STATUS_DOWNLOADING;
    154   status.download_progress = 0.0;
    155   update_screen_->UpdateStatusChanged(status);
    156 
    157   status.download_progress = 0.5;
    158   update_screen_->UpdateStatusChanged(status);
    159 
    160   status.download_progress = 1.0;
    161   update_screen_->UpdateStatusChanged(status);
    162 
    163   status.status = UpdateEngineClient::UPDATE_STATUS_VERIFYING;
    164   update_screen_->UpdateStatusChanged(status);
    165 
    166   status.status = UpdateEngineClient::UPDATE_STATUS_FINALIZING;
    167   update_screen_->UpdateStatusChanged(status);
    168 
    169   status.status = UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT;
    170   update_screen_->UpdateStatusChanged(status);
    171   // UpdateStatusChanged(status) calls RebootAfterUpdate().
    172   EXPECT_EQ(1, fake_update_engine_client_->reboot_after_update_call_count());
    173 }
    174 
    175 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestErrorIssuingUpdateCheck) {
    176   // First, cancel the update that is already in progress.
    177   EXPECT_CALL(*mock_screen_observer_,
    178               OnExit(ScreenObserver::UPDATE_NOUPDATE))
    179       .Times(1);
    180   update_screen_->CancelUpdate();
    181 
    182   fake_update_engine_client_->set_update_check_result(
    183       chromeos::UpdateEngineClient::UPDATE_RESULT_FAILED);
    184   EXPECT_CALL(*mock_screen_observer_,
    185               OnExit(ScreenObserver::UPDATE_ERROR_CHECKING_FOR_UPDATE))
    186       .Times(1);
    187   update_screen_->StartNetworkCheck();
    188 }
    189 
    190 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestErrorCheckingForUpdate) {
    191   UpdateEngineClient::Status status;
    192   status.status = UpdateEngineClient::UPDATE_STATUS_ERROR;
    193   // GetLastStatus() will be called via ExitUpdate() called from
    194   // UpdateStatusChanged().
    195   fake_update_engine_client_->set_default_status(status);
    196 
    197   EXPECT_CALL(*mock_screen_observer_,
    198               OnExit(ScreenObserver::UPDATE_ERROR_CHECKING_FOR_UPDATE))
    199       .Times(1);
    200   update_screen_->UpdateStatusChanged(status);
    201 }
    202 
    203 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestErrorUpdating) {
    204   UpdateEngineClient::Status status;
    205   status.status = UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE;
    206   status.new_version = "latest and greatest";
    207   // GetLastStatus() will be called via ExitUpdate() called from
    208   // UpdateStatusChanged().
    209   fake_update_engine_client_->set_default_status(status);
    210 
    211   update_screen_->UpdateStatusChanged(status);
    212 
    213   status.status = UpdateEngineClient::UPDATE_STATUS_ERROR;
    214   // GetLastStatus() will be called via ExitUpdate() called from
    215   // UpdateStatusChanged().
    216   fake_update_engine_client_->set_default_status(status);
    217 
    218   EXPECT_CALL(*mock_screen_observer_,
    219               OnExit(ScreenObserver::UPDATE_ERROR_UPDATING))
    220       .Times(1);
    221   update_screen_->UpdateStatusChanged(status);
    222 }
    223 
    224 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestTemproraryOfflineNetwork) {
    225   EXPECT_CALL(*mock_screen_observer_,
    226               OnExit(ScreenObserver::UPDATE_NOUPDATE))
    227       .Times(1);
    228   update_screen_->CancelUpdate();
    229 
    230   // Change ethernet state to portal.
    231   NetworkPortalDetector::CaptivePortalState portal_state;
    232   portal_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL;
    233   portal_state.response_code = 200;
    234   SetDetectionResults(kStubEthernetServicePath, portal_state);
    235 
    236   // Update screen will show error message about portal state because
    237   // ethernet is behind captive portal.
    238   EXPECT_CALL(*mock_error_screen_actor_,
    239               SetUIState(ErrorScreen::UI_STATE_UPDATE))
    240       .Times(1);
    241   EXPECT_CALL(*mock_error_screen_actor_,
    242               SetErrorState(ErrorScreen::ERROR_STATE_PORTAL, std::string()))
    243       .Times(1);
    244   EXPECT_CALL(*mock_error_screen_actor_, FixCaptivePortal())
    245       .Times(1);
    246   EXPECT_CALL(*mock_screen_observer_, ShowErrorScreen())
    247       .Times(1);
    248 
    249   update_screen_->StartNetworkCheck();
    250 
    251   NetworkPortalDetector::CaptivePortalState online_state;
    252   online_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE;
    253   online_state.response_code = 204;
    254   SetDetectionResults(kStubEthernetServicePath, online_state);
    255 
    256   // Second notification from portal detector will be about online state,
    257   // so update screen will hide error message and proceed to update.
    258   EXPECT_CALL(*mock_screen_observer_, HideErrorScreen(update_screen_))
    259       .Times(1);
    260   fake_update_engine_client_->set_update_check_result(
    261       chromeos::UpdateEngineClient::UPDATE_RESULT_FAILED);
    262 
    263   EXPECT_CALL(*mock_screen_observer_,
    264               OnExit(ScreenObserver::UPDATE_ERROR_CHECKING_FOR_UPDATE))
    265       .Times(1);
    266 
    267   NotifyPortalDetectionCompleted();
    268 }
    269 
    270 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestTwoOfflineNetworks) {
    271   EXPECT_CALL(*mock_screen_observer_,
    272               OnExit(ScreenObserver::UPDATE_NOUPDATE))
    273       .Times(1);
    274   update_screen_->CancelUpdate();
    275 
    276   // Change ethernet state to portal.
    277   NetworkPortalDetector::CaptivePortalState portal_state;
    278   portal_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL;
    279   portal_state.response_code = 200;
    280   SetDetectionResults(kStubEthernetServicePath, portal_state);
    281 
    282   // Update screen will show error message about portal state because
    283   // ethernet is behind captive portal.
    284   EXPECT_CALL(*mock_error_screen_actor_,
    285               SetUIState(ErrorScreen::UI_STATE_UPDATE))
    286       .Times(1);
    287   EXPECT_CALL(*mock_error_screen_actor_,
    288               SetErrorState(ErrorScreen::ERROR_STATE_PORTAL, std::string()))
    289       .Times(1);
    290   EXPECT_CALL(*mock_error_screen_actor_, FixCaptivePortal())
    291       .Times(1);
    292   EXPECT_CALL(*mock_screen_observer_, ShowErrorScreen())
    293       .Times(1);
    294 
    295   update_screen_->StartNetworkCheck();
    296 
    297   // Change active network to the wifi behind proxy.
    298   NetworkPortalDetector::CaptivePortalState proxy_state;
    299   proxy_state.status =
    300       NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED;
    301   proxy_state.response_code = -1;
    302   SetDefaultNetworkPath(kStubWifiServicePath);
    303   SetDetectionResults(kStubWifiServicePath, proxy_state);
    304 
    305   // Update screen will show message about proxy error because wifie
    306   // network requires proxy authentication.
    307   EXPECT_CALL(*mock_error_screen_actor_,
    308               SetErrorState(ErrorScreen::ERROR_STATE_PROXY, std::string()))
    309       .Times(1);
    310 
    311   NotifyPortalDetectionCompleted();
    312 }
    313 
    314 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestVoidNetwork) {
    315   SetDefaultNetworkPath("");
    316 
    317   // Cancels pending update request.
    318   EXPECT_CALL(*mock_screen_observer_,
    319               OnExit(ScreenObserver::UPDATE_NOUPDATE))
    320       .Times(1);
    321   update_screen_->CancelUpdate();
    322 
    323   // First portal detection attempt returns NULL network and undefined
    324   // results, so detection is restarted.
    325   EXPECT_CALL(*mock_error_screen_actor_,
    326               SetUIState(_))
    327       .Times(Exactly(0));
    328   EXPECT_CALL(*mock_error_screen_actor_,
    329               SetErrorState(_, _))
    330       .Times(Exactly(0));
    331   EXPECT_CALL(*mock_screen_observer_, ShowErrorScreen())
    332       .Times(Exactly(0));
    333   update_screen_->StartNetworkCheck();
    334 
    335   // Second portal detection also returns NULL network and undefined
    336   // results.  In this case, offline message should be displayed.
    337   EXPECT_CALL(*mock_error_screen_actor_,
    338               SetUIState(ErrorScreen::UI_STATE_UPDATE))
    339       .Times(1);
    340   EXPECT_CALL(*mock_error_screen_actor_,
    341               SetErrorState(ErrorScreen::ERROR_STATE_OFFLINE, std::string()))
    342       .Times(1);
    343   EXPECT_CALL(*mock_screen_observer_, ShowErrorScreen())
    344       .Times(1);
    345   base::MessageLoop::current()->RunUntilIdle();
    346   NotifyPortalDetectionCompleted();
    347 }
    348 
    349 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestAPReselection) {
    350   EXPECT_CALL(*mock_screen_observer_,
    351               OnExit(ScreenObserver::UPDATE_NOUPDATE))
    352       .Times(1);
    353   update_screen_->CancelUpdate();
    354 
    355   // Change ethernet state to portal.
    356   NetworkPortalDetector::CaptivePortalState portal_state;
    357   portal_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL;
    358   portal_state.response_code = 200;
    359   SetDetectionResults(kStubEthernetServicePath, portal_state);
    360 
    361   // Update screen will show error message about portal state because
    362   // ethernet is behind captive portal.
    363   EXPECT_CALL(*mock_error_screen_actor_,
    364               SetUIState(ErrorScreen::UI_STATE_UPDATE))
    365       .Times(1);
    366   EXPECT_CALL(*mock_error_screen_actor_,
    367               SetErrorState(ErrorScreen::ERROR_STATE_PORTAL, std::string()))
    368       .Times(1);
    369   EXPECT_CALL(*mock_error_screen_actor_, FixCaptivePortal())
    370       .Times(1);
    371   EXPECT_CALL(*mock_screen_observer_, ShowErrorScreen())
    372       .Times(1);
    373 
    374   update_screen_->StartNetworkCheck();
    375 
    376   // User re-selects the same network manually. In this case, hide
    377   // offline message and skip network check. Since ethernet is still
    378   // behind portal, update engine fails to update.
    379   EXPECT_CALL(*mock_screen_observer_, HideErrorScreen(update_screen_))
    380       .Times(1);
    381   fake_update_engine_client_->set_update_check_result(
    382       chromeos::UpdateEngineClient::UPDATE_RESULT_FAILED);
    383   EXPECT_CALL(*mock_screen_observer_,
    384               OnExit(ScreenObserver::UPDATE_ERROR_CHECKING_FOR_UPDATE))
    385       .Times(1);
    386 
    387   update_screen_->OnConnectToNetworkRequested(kStubEthernetServicePath);
    388   base::MessageLoop::current()->RunUntilIdle();
    389 }
    390 
    391 }  // namespace chromeos
    392