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