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:
UpdateScreenTest()42 UpdateScreenTest() : WizardInProcessBrowserTest("update"),
43 fake_update_engine_client_(NULL),
44 network_portal_detector_(NULL) {
45 }
46
47 protected:
SetUpInProcessBrowserTestFixture()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
SetUpOnMainThread()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
CleanUpOnMainThread()94 virtual void CleanUpOnMainThread() OVERRIDE {
95 mock_error_screen_.reset();
96 mock_error_screen_actor_.reset();
97 WizardInProcessBrowserTest::CleanUpOnMainThread();
98 }
99
TearDownInProcessBrowserTestFixture()100 virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
101 NetworkPortalDetector::Shutdown();
102 WizardInProcessBrowserTest::TearDownInProcessBrowserTestFixture();
103 }
104
SetDefaultNetworkPath(const std::string & service_path)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
SetDetectionResults(const std::string & service_path,const NetworkPortalDetector::CaptivePortalState & state)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
NotifyPortalDetectionCompleted()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
IN_PROC_BROWSER_TEST_F(UpdateScreenTest,TestBasic)136 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestBasic) {
137 ASSERT_TRUE(update_screen_->actor_ != NULL);
138 }
139
IN_PROC_BROWSER_TEST_F(UpdateScreenTest,TestNoUpdate)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
IN_PROC_BROWSER_TEST_F(UpdateScreenTest,TestUpdateAvailable)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
IN_PROC_BROWSER_TEST_F(UpdateScreenTest,TestErrorIssuingUpdateCheck)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
IN_PROC_BROWSER_TEST_F(UpdateScreenTest,TestErrorCheckingForUpdate)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
IN_PROC_BROWSER_TEST_F(UpdateScreenTest,TestErrorUpdating)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
IN_PROC_BROWSER_TEST_F(UpdateScreenTest,TestTemproraryOfflineNetwork)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
IN_PROC_BROWSER_TEST_F(UpdateScreenTest,TestTwoOfflineNetworks)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
IN_PROC_BROWSER_TEST_F(UpdateScreenTest,TestVoidNetwork)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
IN_PROC_BROWSER_TEST_F(UpdateScreenTest,TestAPReselection)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