update_screen_browsertest.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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
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_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
124IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestBasic) {
125  ASSERT_TRUE(update_screen_->actor_ != NULL);
126}
127
128IN_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
145IN_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
175IN_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
190IN_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
203IN_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
224IN_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
270IN_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
314IN_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}  // namespace chromeos
350