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.
5 #include "chrome/browser/chromeos/login/screens/error_screen.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/logging.h"
11 #include "chrome/browser/app_mode/app_mode_utils.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/chromeos/app_mode/app_session_lifetime.h"
14 #include "chrome/browser/chromeos/app_mode/certificate_manager_dialog.h"
15 #include "chrome/browser/chromeos/login/auth/chrome_login_performer.h"
16 #include "chrome/browser/chromeos/login/chrome_restart_request.h"
17 #include "chrome/browser/chromeos/login/screens/network_error_view.h"
18 #include "chrome/browser/chromeos/login/startup_utils.h"
19 #include "chrome/browser/chromeos/login/ui/captive_portal_window_proxy.h"
20 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
21 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
22 #include "chrome/browser/chromeos/login/wizard_controller.h"
23 #include "chrome/browser/chromeos/profiles/profile_helper.h"
24 #include "chrome/browser/chromeos/settings/cros_settings.h"
25 #include "chrome/browser/chromeos/settings/device_settings_service.h"
26 #include "chrome/browser/extensions/component_loader.h"
27 #include "chrome/browser/extensions/extension_service.h"
28 #include "chrome/browser/profiles/profile_manager.h"
29 #include "chrome/browser/ui/extensions/app_launch_params.h"
30 #include "chrome/browser/ui/extensions/application_launch.h"
31 #include "chrome/common/extensions/extension_constants.h"
32 #include "chromeos/dbus/dbus_thread_manager.h"
33 #include "chromeos/dbus/power_manager_client.h"
34 #include "chromeos/dbus/session_manager_client.h"
35 #include "chromeos/network/portal_detector/network_portal_detector.h"
36 #include "chromeos/network/portal_detector/network_portal_detector_strategy.h"
37 #include "components/user_manager/user_manager.h"
38 #include "content/public/browser/notification_service.h"
39 #include "extensions/browser/extension_system.h"
40 #include "extensions/common/constants.h"
41 #include "grit/browser_resources.h"
42 #include "ui/gfx/native_widget_types.h"
48 // Returns the current running kiosk app profile in a kiosk session. Otherwise,
50 Profile
* GetAppProfile() {
51 return chrome::IsRunningInForcedAppMode()
52 ? ProfileManager::GetActiveUserProfile()
58 ErrorScreen::ErrorScreen(BaseScreenDelegate
* base_screen_delegate
,
59 NetworkErrorView
* view
)
60 : NetworkErrorModel(base_screen_delegate
),
62 ui_state_(NetworkError::UI_STATE_UNKNOWN
),
63 error_state_(NetworkError::ERROR_STATE_UNKNOWN
),
64 parent_screen_(OobeUI::SCREEN_UNKNOWN
),
66 network_state_informer_
= new NetworkStateInformer();
67 network_state_informer_
->Init();
72 ErrorScreen::~ErrorScreen() {
77 void ErrorScreen::PrepareToShow() {
79 view_
->PrepareToShow();
82 void ErrorScreen::Show() {
83 if (!on_hide_callback_
) {
84 SetHideCallback(base::Bind(&ErrorScreen::DefaultHideCallback
,
85 weak_factory_
.GetWeakPtr()));
91 void ErrorScreen::Hide() {
96 void ErrorScreen::OnShow() {
97 LOG(WARNING
) << "Network error screen message is shown";
98 content::NotificationService::current()->Notify(
99 chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN
,
100 content::NotificationService::AllSources(),
101 content::NotificationService::NoDetails());
102 NetworkPortalDetector::Get()->SetStrategy(
103 PortalDetectorStrategy::STRATEGY_ID_ERROR_SCREEN
);
106 void ErrorScreen::OnHide() {
107 LOG(WARNING
) << "Network error screen message is hidden";
108 if (on_hide_callback_
) {
109 on_hide_callback_
->Run();
110 on_hide_callback_
.reset();
112 NetworkPortalDetector::Get()->SetStrategy(
113 PortalDetectorStrategy::STRATEGY_ID_LOGIN_SCREEN
);
116 void ErrorScreen::OnUserAction(const std::string
& action_id
) {
117 if (action_id
== kUserActionShowCaptivePortalClicked
)
119 else if (action_id
== kUserActionConfigureCertsButtonClicked
)
121 else if (action_id
== kUserActionDiagnoseButtonClicked
)
122 OnDiagnoseButtonClicked();
123 else if (action_id
== kUserActionLaunchOobeGuestSessionClicked
)
124 OnLaunchOobeGuestSession();
125 else if (action_id
== kUserActionLocalStateErrorPowerwashButtonClicked
)
126 OnLocalStateErrorPowerwashButtonClicked();
127 else if (action_id
== kUserActionRebootButtonClicked
)
128 OnRebootButtonClicked();
129 else if (action_id
== kUserActionConnectRequested
)
130 OnConnectRequested();
132 BaseScreen::OnUserAction(action_id
);
135 void ErrorScreen::OnContextKeyUpdated(
136 const ::login::ScreenContext::KeyType
& key
) {
137 BaseScreen::OnContextKeyUpdated(key
);
140 void ErrorScreen::AllowGuestSignin(bool allowed
) {
141 GetContextEditor().SetBoolean(kContextKeyGuestSigninAllowed
, allowed
);
144 void ErrorScreen::AllowOfflineLogin(bool allowed
) {
145 GetContextEditor().SetBoolean(kContextKeyOfflineSigninAllowed
, allowed
);
148 void ErrorScreen::FixCaptivePortal() {
149 if (!captive_portal_window_proxy_
.get()) {
150 content::WebContents
* web_contents
= LoginDisplayHostImpl::default_host()
151 ->GetWebUILoginView()
153 captive_portal_window_proxy_
.reset(new CaptivePortalWindowProxy(
154 network_state_informer_
.get(), web_contents
));
156 captive_portal_window_proxy_
->ShowIfRedirected();
159 NetworkError::UIState
ErrorScreen::GetUIState() const {
163 NetworkError::ErrorState
ErrorScreen::GetErrorState() const {
167 OobeUI::Screen
ErrorScreen::GetParentScreen() const {
168 return parent_screen_
;
171 void ErrorScreen::HideCaptivePortal() {
172 if (captive_portal_window_proxy_
.get())
173 captive_portal_window_proxy_
->Close();
176 void ErrorScreen::OnViewDestroyed(NetworkErrorView
* view
) {
181 void ErrorScreen::SetUIState(NetworkError::UIState ui_state
) {
182 ui_state_
= ui_state
;
183 GetContextEditor().SetInteger(kContextKeyUIState
,
184 static_cast<int>(ui_state_
));
187 void ErrorScreen::SetErrorState(NetworkError::ErrorState error_state
,
188 const std::string
& network
) {
189 error_state_
= error_state
;
191 .SetInteger(kContextKeyErrorStateCode
, static_cast<int>(error_state_
))
192 .SetString(kContextKeyErrorStateNetwork
, network
);
195 void ErrorScreen::SetParentScreen(OobeUI::Screen parent_screen
) {
196 parent_screen_
= parent_screen
;
197 // Not really used on JS side yet so no need to propagate to screen context.
200 void ErrorScreen::SetHideCallback(const base::Closure
& on_hide
) {
201 on_hide_callback_
.reset(new base::Closure(on_hide
));
204 void ErrorScreen::ShowCaptivePortal() {
205 // This call is an explicit user action
206 // i.e. clicking on link so force dialog show.
208 captive_portal_window_proxy_
->Show();
211 void ErrorScreen::ShowConnectingIndicator(bool show
) {
212 GetContextEditor().SetBoolean(kContextKeyShowConnectingIndicator
, show
);
215 void ErrorScreen::OnAuthFailure(const AuthFailure
& error
) {
216 // The only condition leading here is guest mount failure, which should not
217 // happen in practice. For now, just log an error so this situation is visible
218 // in logs if it ever occurs.
219 NOTREACHED() << "Guest login failed.";
220 guest_login_performer_
.reset();
223 void ErrorScreen::OnAuthSuccess(const UserContext
& user_context
) {
227 void ErrorScreen::OnOffTheRecordAuthSuccess() {
228 // Restart Chrome to enter the guest session.
229 const base::CommandLine
& browser_command_line
=
230 *base::CommandLine::ForCurrentProcess();
231 base::CommandLine
command_line(browser_command_line
.GetProgram());
232 GetOffTheRecordCommandLine(GURL(), StartupUtils::IsOobeCompleted(),
233 browser_command_line
, &command_line
);
234 RestartChrome(command_line
);
237 void ErrorScreen::OnPasswordChangeDetected() {
241 void ErrorScreen::WhiteListCheckFailed(const std::string
& email
) {
245 void ErrorScreen::PolicyLoadFailed() {
249 ErrorScreen::ConnectRequestCallbackSubscription
250 ErrorScreen::RegisterConnectRequestCallback(const base::Closure
& callback
) {
251 return connect_request_callbacks_
.Add(callback
);
254 void ErrorScreen::DefaultHideCallback() {
255 if (parent_screen_
!= OobeUI::SCREEN_UNKNOWN
&& view_
)
256 view_
->ShowScreen(parent_screen_
);
258 // TODO(antrim): Due to potential race with GAIA reload and hiding network
259 // error UI we can't just reset parent screen to SCREEN_UNKNOWN here.
262 void ErrorScreen::OnConfigureCerts() {
263 gfx::NativeWindow native_window
=
264 LoginDisplayHostImpl::default_host()->GetNativeWindow();
265 CertificateManagerDialog
* dialog
= new CertificateManagerDialog(
266 GetAppProfile(), NULL
, native_window
);
270 void ErrorScreen::OnDiagnoseButtonClicked() {
271 Profile
* profile
= GetAppProfile();
272 ExtensionService
* extension_service
=
273 extensions::ExtensionSystem::Get(profile
)->extension_service();
275 std::string extension_id
= extension_service
->component_loader()->Add(
276 IDR_CONNECTIVITY_DIAGNOSTICS_MANIFEST
,
277 base::FilePath(extension_misc::kConnectivityDiagnosticsPath
));
279 const extensions::Extension
* extension
=
280 extension_service
->GetExtensionById(extension_id
, true);
282 AppLaunchParams(profile
, extension
, extensions::LAUNCH_CONTAINER_WINDOW
,
283 NEW_WINDOW
, extensions::SOURCE_CHROME_INTERNAL
));
284 InitAppSession(profile
, extension_id
);
286 user_manager::UserManager::Get()->SessionStarted();
288 LoginDisplayHostImpl::default_host()->Finalize();
291 void ErrorScreen::OnLaunchOobeGuestSession() {
292 DeviceSettingsService::Get()->GetOwnershipStatusAsync(
293 base::Bind(&ErrorScreen::StartGuestSessionAfterOwnershipCheck
,
294 weak_factory_
.GetWeakPtr()));
297 void ErrorScreen::OnLocalStateErrorPowerwashButtonClicked() {
298 chromeos::DBusThreadManager::Get()
299 ->GetSessionManagerClient()
303 void ErrorScreen::OnRebootButtonClicked() {
304 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
307 void ErrorScreen::OnConnectRequested() {
308 connect_request_callbacks_
.Notify();
311 void ErrorScreen::StartGuestSessionAfterOwnershipCheck(
312 DeviceSettingsService::OwnershipStatus ownership_status
) {
314 // Make sure to disallow guest login if it's explicitly disabled.
315 CrosSettingsProvider::TrustedStatus trust_status
=
316 CrosSettings::Get()->PrepareTrustedValues(
317 base::Bind(&ErrorScreen::StartGuestSessionAfterOwnershipCheck
,
318 weak_factory_
.GetWeakPtr(),
320 switch (trust_status
) {
321 case CrosSettingsProvider::TEMPORARILY_UNTRUSTED
:
322 // Wait for a callback.
324 case CrosSettingsProvider::PERMANENTLY_UNTRUSTED
:
325 // Only allow guest sessions if there is no owner yet.
326 if (ownership_status
== DeviceSettingsService::OWNERSHIP_NONE
)
329 case CrosSettingsProvider::TRUSTED
: {
330 // Honor kAccountsPrefAllowGuest.
331 bool allow_guest
= false;
332 CrosSettings::Get()->GetBoolean(kAccountsPrefAllowGuest
, &allow_guest
);
339 if (guest_login_performer_
)
342 guest_login_performer_
.reset(new ChromeLoginPerformer(this));
343 guest_login_performer_
->LoginOffTheRecord();
346 } // namespace chromeos