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