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