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