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