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