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 "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h"
6
7#include "base/logging.h"
8#include "base/message_loop/message_loop.h"
9#include "base/time/time.h"
10#include "chrome/browser/chrome_notification_types.h"
11#include "chrome/browser/chromeos/app_mode/app_session_lifetime.h"
12#include "chrome/browser/chromeos/app_mode/certificate_manager_dialog.h"
13#include "chrome/browser/chromeos/login/ui/captive_portal_window_proxy.h"
14#include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
15#include "chrome/browser/chromeos/login/ui/webui_login_view.h"
16#include "chrome/browser/extensions/component_loader.h"
17#include "chrome/browser/extensions/extension_service.h"
18#include "chrome/browser/profiles/profile_manager.h"
19#include "chrome/browser/ui/extensions/application_launch.h"
20#include "chrome/browser/ui/webui/chromeos/login/native_window_delegate.h"
21#include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h"
22#include "chrome/grit/chromium_strings.h"
23#include "chrome/grit/generated_resources.h"
24#include "chromeos/dbus/dbus_thread_manager.h"
25#include "chromeos/dbus/power_manager_client.h"
26#include "chromeos/dbus/session_manager_client.h"
27#include "chromeos/network/portal_detector/network_portal_detector.h"
28#include "chromeos/network/portal_detector/network_portal_detector_strategy.h"
29#include "components/user_manager/user_manager.h"
30#include "extensions/browser/extension_system.h"
31#include "grit/browser_resources.h"
32#include "ui/strings/grit/ui_strings.h"
33
34namespace {
35
36const char kJsScreenPath[] = "login.ErrorMessageScreen";
37
38}  // namespace
39
40namespace chromeos {
41
42ErrorScreenHandler::ErrorScreenHandler(
43    const scoped_refptr<NetworkStateInformer>& network_state_informer)
44    : BaseScreenHandler(kJsScreenPath),
45      delegate_(NULL),
46      network_state_informer_(network_state_informer),
47      show_on_init_(false),
48      weak_ptr_factory_(this) {
49  DCHECK(network_state_informer_.get());
50}
51
52ErrorScreenHandler::~ErrorScreenHandler() {}
53
54void ErrorScreenHandler::SetDelegate(ErrorScreenActorDelegate* delegate) {
55  delegate_ = delegate;
56}
57
58void ErrorScreenHandler::Show(OobeDisplay::Screen parent_screen,
59                              base::DictionaryValue* params,
60                              const base::Closure& on_hide) {
61  if (!page_is_ready()) {
62    show_on_init_ = true;
63    return;
64  }
65  parent_screen_ = parent_screen;
66  on_hide_.reset(new base::Closure(on_hide));
67  ShowScreen(OobeUI::kScreenErrorMessage, params);
68  NetworkErrorShown();
69  NetworkPortalDetector::Get()->SetStrategy(
70      PortalDetectorStrategy::STRATEGY_ID_ERROR_SCREEN);
71  if (delegate_)
72    delegate_->OnErrorShow();
73  LOG(WARNING) << "Offline message is displayed";
74}
75
76void ErrorScreenHandler::CheckAndShowScreen() {
77  std::string screen_name;
78  if (GetScreenName(parent_screen(), &screen_name))
79    ShowScreen(screen_name.c_str(), NULL);
80}
81
82void ErrorScreenHandler::Show(OobeDisplay::Screen parent_screen,
83                              base::DictionaryValue* params) {
84  Show(parent_screen,
85       params,
86       base::Bind(&ErrorScreenHandler::CheckAndShowScreen,
87                  weak_ptr_factory_.GetWeakPtr()));
88}
89
90void ErrorScreenHandler::Hide() {
91  if (parent_screen_ == OobeUI::SCREEN_UNKNOWN)
92    return;
93  if (on_hide_)
94    on_hide_->Run();
95  NetworkPortalDetector::Get()->SetStrategy(
96      PortalDetectorStrategy::STRATEGY_ID_LOGIN_SCREEN);
97  if (delegate_)
98    delegate_->OnErrorHide();
99  LOG(WARNING) << "Offline message is hidden";
100}
101
102void ErrorScreenHandler::FixCaptivePortal() {
103  if (!captive_portal_window_proxy_.get()) {
104    content::WebContents* web_contents =
105        LoginDisplayHostImpl::default_host()->GetWebUILoginView()->
106            GetWebContents();
107    captive_portal_window_proxy_.reset(
108        new CaptivePortalWindowProxy(network_state_informer_.get(),
109                                     web_contents));
110  }
111  captive_portal_window_proxy_->ShowIfRedirected();
112}
113
114void ErrorScreenHandler::ShowCaptivePortal() {
115  // This call is an explicit user action
116  // i.e. clicking on link so force dialog show.
117  FixCaptivePortal();
118  captive_portal_window_proxy_->Show();
119}
120
121void ErrorScreenHandler::HideCaptivePortal() {
122  if (captive_portal_window_proxy_.get())
123    captive_portal_window_proxy_->Close();
124}
125
126void ErrorScreenHandler::SetUIState(ErrorScreen::UIState ui_state) {
127  show_connecting_indicator_ = false;
128  ui_state_ = ui_state;
129  if (page_is_ready())
130    CallJS("setUIState", static_cast<int>(ui_state_));
131}
132
133void ErrorScreenHandler::SetErrorState(ErrorScreen::ErrorState error_state,
134                                       const std::string& network) {
135  error_state_ = error_state;
136  network_ = network;
137  if (page_is_ready())
138    CallJS("setErrorState", static_cast<int>(error_state_), network);
139}
140
141void ErrorScreenHandler::AllowGuestSignin(bool allowed) {
142  guest_signin_allowed_ = allowed;
143  if (page_is_ready())
144    CallJS("allowGuestSignin", allowed);
145}
146
147void ErrorScreenHandler::AllowOfflineLogin(bool allowed) {
148  offline_login_allowed_ = allowed;
149  if (page_is_ready())
150    CallJS("allowOfflineLogin", allowed);
151}
152
153void ErrorScreenHandler::ShowConnectingIndicator(bool show) {
154  show_connecting_indicator_ = show;
155  if (page_is_ready())
156    CallJS("showConnectingIndicator", show);
157}
158
159void ErrorScreenHandler::NetworkErrorShown() {
160  content::NotificationService::current()->Notify(
161      chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
162      content::NotificationService::AllSources(),
163      content::NotificationService::NoDetails());
164}
165
166bool ErrorScreenHandler::GetScreenName(OobeUI::Screen screen,
167                                       std::string* name) const {
168  OobeUI* oobe_ui = static_cast<OobeUI*>(web_ui()->GetController());
169  if (!oobe_ui)
170    return false;
171  *name = oobe_ui->GetScreenName(screen);
172  return true;
173}
174
175void ErrorScreenHandler::HandleShowCaptivePortal() {
176  ShowCaptivePortal();
177}
178
179void ErrorScreenHandler::HandleHideCaptivePortal() {
180  HideCaptivePortal();
181}
182
183void ErrorScreenHandler::HandleLocalStateErrorPowerwashButtonClicked() {
184  chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->
185      StartDeviceWipe();
186}
187
188void ErrorScreenHandler::HandleRebootButtonClicked() {
189  chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
190}
191
192void ErrorScreenHandler::HandleDiagnoseButtonClicked() {
193  Profile* profile = ProfileManager::GetActiveUserProfile();
194  ExtensionService* extension_service =
195      extensions::ExtensionSystem::Get(profile)->extension_service();
196
197  std::string extension_id =
198      extension_service->component_loader()->Add(
199          IDR_CONNECTIVITY_DIAGNOSTICS_MANIFEST,
200          base::FilePath(extension_misc::kConnectivityDiagnosticsKioskPath));
201
202  const extensions::Extension* extension = extension_service->
203      GetExtensionById(extension_id, true);
204  OpenApplication(AppLaunchParams(profile, extension,
205                                  extensions::LAUNCH_CONTAINER_WINDOW,
206                                  NEW_WINDOW));
207  InitAppSession(profile, extension_id);
208
209  user_manager::UserManager::Get()->SessionStarted();
210
211  LoginDisplayHostImpl::default_host()->Finalize();
212}
213
214void ErrorScreenHandler::HandleConfigureCerts() {
215  CertificateManagerDialog* dialog =
216      new CertificateManagerDialog(ProfileManager::GetActiveUserProfile(),
217                                   NULL,
218                                   GetNativeWindow());
219  dialog->Show();
220}
221
222void ErrorScreenHandler::HandleLaunchOobeGuestSession() {
223  if (delegate_)
224    delegate_->OnLaunchOobeGuestSession();
225}
226
227void ErrorScreenHandler::RegisterMessages() {
228  AddCallback("showCaptivePortal",
229              &ErrorScreenHandler::HandleShowCaptivePortal);
230  AddCallback("hideCaptivePortal",
231              &ErrorScreenHandler::HandleHideCaptivePortal);
232  AddCallback("localStateErrorPowerwashButtonClicked",
233              &ErrorScreenHandler::HandleLocalStateErrorPowerwashButtonClicked);
234  AddCallback("rebootButtonClicked",
235              &ErrorScreenHandler::HandleRebootButtonClicked);
236  AddCallback("diagnoseButtonClicked",
237              &ErrorScreenHandler::HandleDiagnoseButtonClicked);
238  AddCallback("configureCertsClicked",
239              &ErrorScreenHandler::HandleConfigureCerts);
240  AddCallback("launchOobeGuestSession",
241              &ErrorScreenHandler::HandleLaunchOobeGuestSession);
242  AddCallback("rollbackOkButtonClicked",
243              &ErrorScreenHandler::HandleRebootButtonClicked);
244}
245
246void ErrorScreenHandler::DeclareLocalizedValues(
247    LocalizedValuesBuilder* builder) {
248  builder->Add("loginErrorTitle", IDS_LOGIN_ERROR_TITLE);
249  builder->Add("rollbackErrorTitle", IDS_RESET_SCREEN_REVERT_ERROR);
250  builder->Add("signinOfflineMessageBody", IDS_LOGIN_OFFLINE_MESSAGE);
251  builder->Add("kioskOfflineMessageBody", IDS_KIOSK_OFFLINE_MESSAGE);
252  builder->Add("kioskOnlineTitle", IDS_LOGIN_NETWORK_RESTORED_TITLE);
253  builder->Add("kioskOnlineMessageBody", IDS_KIOSK_ONLINE_MESSAGE);
254  builder->Add("autoEnrollmentOfflineMessageBody",
255               IDS_LOGIN_AUTO_ENROLLMENT_OFFLINE_MESSAGE);
256  builder->AddF("rollbackErrorMessageBody",
257               IDS_RESET_SCREEN_REVERT_ERROR_EXPLANATION,
258               IDS_SHORT_PRODUCT_NAME);
259  builder->Add("captivePortalTitle", IDS_LOGIN_MAYBE_CAPTIVE_PORTAL_TITLE);
260  builder->Add("captivePortalMessage", IDS_LOGIN_MAYBE_CAPTIVE_PORTAL);
261  builder->Add("captivePortalProxyMessage",
262               IDS_LOGIN_MAYBE_CAPTIVE_PORTAL_PROXY);
263  builder->Add("captivePortalNetworkSelect",
264               IDS_LOGIN_MAYBE_CAPTIVE_PORTAL_NETWORK_SELECT);
265  builder->Add("signinProxyMessageText", IDS_LOGIN_PROXY_ERROR_MESSAGE);
266  builder->Add("updateOfflineMessageBody", IDS_UPDATE_OFFLINE_MESSAGE);
267  builder->Add("updateProxyMessageText", IDS_UPDATE_PROXY_ERROR_MESSAGE);
268  builder->AddF("localStateErrorText0", IDS_LOCAL_STATE_ERROR_TEXT_0,
269                IDS_SHORT_PRODUCT_NAME);
270  builder->Add("localStateErrorText1", IDS_LOCAL_STATE_ERROR_TEXT_1);
271  builder->Add("localStateErrorPowerwashButton",
272               IDS_LOCAL_STATE_ERROR_POWERWASH_BUTTON);
273  builder->Add("connectingIndicatorText", IDS_LOGIN_CONNECTING_INDICATOR_TEXT);
274  builder->Add("guestSigninFixNetwork", IDS_LOGIN_GUEST_SIGNIN_FIX_NETWORK);
275  builder->Add("rebootButton", IDS_RELAUNCH_BUTTON);
276  builder->Add("diagnoseButton", IDS_DIAGNOSE_BUTTON);
277  builder->Add("configureCertsButton", IDS_MANAGE_CERTIFICATES);
278  builder->Add("continueButton", IDS_NETWORK_SELECTION_CONTINUE_BUTTON);
279  builder->Add("okButton", IDS_APP_OK);
280}
281
282void ErrorScreenHandler::Initialize() {
283  if (!page_is_ready())
284    return;
285  if (show_on_init_) {
286    base::DictionaryValue params;
287    params.SetInteger("uiState", static_cast<int>(ui_state_));
288    params.SetInteger("errorState", static_cast<int>(error_state_));
289    params.SetString("network", network_);
290    params.SetBoolean("guestSigninAllowed", guest_signin_allowed_);
291    params.SetBoolean("offlineLoginAllowed", offline_login_allowed_);
292    params.SetBoolean("showConnectingIndicator", show_connecting_indicator_);
293    Show(parent_screen_, &params);
294    show_on_init_ = false;
295  }
296}
297
298}  // namespace chromeos
299