Update broken references to image assets
[chromium-blink-merge.git] / chrome / browser / chromeos / login / app_launch_controller.cc
blobeb33f14a2e702ad06c348fbec2471b9d4a4319f0
1 // Copyright 2013 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/app_launch_controller.h"
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/files/file_path.h"
10 #include "base/json/json_file_value_serializer.h"
11 #include "base/logging.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/time/time.h"
15 #include "base/values.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/chromeos/app_mode/app_session_lifetime.h"
19 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
20 #include "chrome/browser/chromeos/app_mode/startup_app_launcher.h"
21 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
22 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
23 #include "chrome/browser/chromeos/login/ui/oobe_display.h"
24 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
25 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
26 #include "chrome/browser/chromeos/settings/cros_settings.h"
27 #include "chrome/browser/lifetime/application_lifetime.h"
28 #include "chrome/browser/profiles/profile.h"
29 #include "chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h"
30 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
31 #include "chromeos/settings/cros_settings_names.h"
32 #include "components/user_manager/user_manager.h"
33 #include "content/public/browser/notification_service.h"
34 #include "extensions/browser/app_window/app_window.h"
35 #include "extensions/browser/app_window/app_window_registry.h"
36 #include "net/base/network_change_notifier.h"
38 namespace chromeos {
40 namespace {
42 // Application install splash screen minimum show time in milliseconds.
43 const int kAppInstallSplashScreenMinTimeMS = 3000;
45 } // namespace
47 // static
48 bool AppLaunchController::skip_splash_wait_ = false;
49 int AppLaunchController::network_wait_time_ = 10;
50 base::Closure* AppLaunchController::network_timeout_callback_ = NULL;
51 AppLaunchController::ReturnBoolCallback*
52 AppLaunchController::can_configure_network_callback_ = NULL;
53 AppLaunchController::ReturnBoolCallback*
54 AppLaunchController::need_owner_auth_to_configure_network_callback_ = NULL;
56 ////////////////////////////////////////////////////////////////////////////////
57 // AppLaunchController::AppWindowWatcher
59 class AppLaunchController::AppWindowWatcher
60 : public extensions::AppWindowRegistry::Observer {
61 public:
62 explicit AppWindowWatcher(AppLaunchController* controller,
63 const std::string& app_id)
64 : controller_(controller),
65 app_id_(app_id),
66 window_registry_(
67 extensions::AppWindowRegistry::Get(controller->profile_)),
68 weak_factory_(this) {
69 if (!window_registry_->GetAppWindowsForApp(app_id).empty()) {
70 base::MessageLoop::current()->PostTask(
71 FROM_HERE,
72 base::Bind(&AppWindowWatcher::NotifyAppWindowCreated,
73 weak_factory_.GetWeakPtr()));
74 return;
75 } else {
76 window_registry_->AddObserver(this);
79 ~AppWindowWatcher() override { window_registry_->RemoveObserver(this); }
81 private:
82 // extensions::AppWindowRegistry::Observer overrides:
83 void OnAppWindowAdded(extensions::AppWindow* app_window) override {
84 if (app_window->extension_id() == app_id_) {
85 window_registry_->RemoveObserver(this);
86 NotifyAppWindowCreated();
90 void NotifyAppWindowCreated() {
91 controller_->OnAppWindowCreated();
94 AppLaunchController* controller_;
95 std::string app_id_;
96 extensions::AppWindowRegistry* window_registry_;
97 base::WeakPtrFactory<AppWindowWatcher> weak_factory_;
99 DISALLOW_COPY_AND_ASSIGN(AppWindowWatcher);
102 ////////////////////////////////////////////////////////////////////////////////
103 // AppLaunchController
105 AppLaunchController::AppLaunchController(const std::string& app_id,
106 bool diagnostic_mode,
107 LoginDisplayHost* host,
108 OobeDisplay* oobe_display)
109 : profile_(NULL),
110 app_id_(app_id),
111 diagnostic_mode_(diagnostic_mode),
112 host_(host),
113 oobe_display_(oobe_display),
114 app_launch_splash_screen_actor_(
115 oobe_display_->GetAppLaunchSplashScreenActor()),
116 webui_visible_(false),
117 launcher_ready_(false),
118 waiting_for_network_(false),
119 network_wait_timedout_(false),
120 showing_network_dialog_(false),
121 network_config_requested_(false),
122 launch_splash_start_time_(0) {
125 AppLaunchController::~AppLaunchController() {
126 app_launch_splash_screen_actor_->SetDelegate(NULL);
129 void AppLaunchController::StartAppLaunch(bool is_auto_launch) {
130 DVLOG(1) << "Starting kiosk mode...";
132 // Ensure WebUILoginView is enabled so that bailout shortcut key works.
133 host_->GetWebUILoginView()->SetUIEnabled(true);
135 webui_visible_ = host_->GetWebUILoginView()->webui_visible();
136 if (!webui_visible_) {
137 registrar_.Add(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
138 content::NotificationService::AllSources());
140 launch_splash_start_time_ = base::TimeTicks::Now().ToInternalValue();
142 // TODO(tengs): Add a loading profile app launch state.
143 app_launch_splash_screen_actor_->SetDelegate(this);
144 app_launch_splash_screen_actor_->Show(app_id_);
146 KioskAppManager::App app;
147 CHECK(KioskAppManager::Get());
148 CHECK(KioskAppManager::Get()->GetApp(app_id_, &app));
150 if (is_auto_launch) {
151 int delay;
152 if (!CrosSettings::Get()->GetInteger(
153 kAccountsPrefDeviceLocalAccountAutoLoginDelay, &delay)) {
154 delay = 0;
156 DCHECK_EQ(0, delay) << "Kiosks do not support non-zero auto-login delays";
158 // If we are launching a kiosk app with zero delay, mark it appropriately.
159 if (delay == 0)
160 KioskAppManager::Get()->SetAppWasAutoLaunchedWithZeroDelay(app_id_);
163 kiosk_profile_loader_.reset(
164 new KioskProfileLoader(app.user_id, false, this));
165 kiosk_profile_loader_->Start();
168 // static
169 void AppLaunchController::SkipSplashWaitForTesting() {
170 skip_splash_wait_ = true;
173 // static
174 void AppLaunchController::SetNetworkWaitForTesting(int wait_time_secs) {
175 network_wait_time_ = wait_time_secs;
178 // static
179 void AppLaunchController::SetNetworkTimeoutCallbackForTesting(
180 base::Closure* callback) {
181 network_timeout_callback_ = callback;
184 // static
185 void AppLaunchController::SetCanConfigureNetworkCallbackForTesting(
186 ReturnBoolCallback* can_configure_network_callback) {
187 can_configure_network_callback_ = can_configure_network_callback;
190 // static
191 void AppLaunchController::SetNeedOwnerAuthToConfigureNetworkCallbackForTesting(
192 ReturnBoolCallback* need_owner_auth_callback) {
193 need_owner_auth_to_configure_network_callback_ = need_owner_auth_callback;
196 void AppLaunchController::OnConfigureNetwork() {
197 DCHECK(profile_);
198 if (showing_network_dialog_)
199 return;
201 showing_network_dialog_ = true;
202 if (CanConfigureNetwork() && NeedOwnerAuthToConfigureNetwork()) {
203 signin_screen_.reset(new AppLaunchSigninScreen(
204 static_cast<OobeUI*>(oobe_display_), this));
205 signin_screen_->Show();
206 } else {
207 // If kiosk mode was configured through enterprise policy, we may
208 // not have an owner user.
209 // TODO(tengs): We need to figure out the appropriate security meausres
210 // for this case.
211 NOTREACHED();
215 void AppLaunchController::OnOwnerSigninSuccess() {
216 app_launch_splash_screen_actor_->ShowNetworkConfigureUI();
217 signin_screen_.reset();
220 void AppLaunchController::Observe(
221 int type,
222 const content::NotificationSource& source,
223 const content::NotificationDetails& details) {
224 DCHECK_EQ(chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, type);
225 DCHECK(!webui_visible_);
226 webui_visible_ = true;
227 launch_splash_start_time_ = base::TimeTicks::Now().ToInternalValue();
228 if (launcher_ready_)
229 OnReadyToLaunch();
232 void AppLaunchController::OnCancelAppLaunch() {
233 if (KioskAppManager::Get()->GetDisableBailoutShortcut())
234 return;
236 OnLaunchFailed(KioskAppLaunchError::USER_CANCEL);
239 void AppLaunchController::OnNetworkConfigRequested(bool requested) {
240 network_config_requested_ = requested;
241 if (requested)
242 MaybeShowNetworkConfigureUI();
243 else
244 startup_app_launcher_->RestartLauncher();
247 void AppLaunchController::OnNetworkStateChanged(bool online) {
248 if (!waiting_for_network_)
249 return;
251 if (online && !network_config_requested_)
252 startup_app_launcher_->ContinueWithNetworkReady();
253 else if (network_wait_timedout_)
254 MaybeShowNetworkConfigureUI();
257 void AppLaunchController::OnProfileLoaded(Profile* profile) {
258 DVLOG(1) << "Profile loaded... Starting app launch.";
259 profile_ = profile;
261 // This is needed to trigger input method extensions being loaded.
262 profile_->InitChromeOSPreferences();
264 kiosk_profile_loader_.reset();
265 startup_app_launcher_.reset(
266 new StartupAppLauncher(profile_, app_id_, diagnostic_mode_, this));
267 startup_app_launcher_->Initialize();
270 void AppLaunchController::OnProfileLoadFailed(
271 KioskAppLaunchError::Error error) {
272 OnLaunchFailed(error);
275 void AppLaunchController::ClearNetworkWaitTimer() {
276 waiting_for_network_ = false;
277 network_wait_timer_.Stop();
280 void AppLaunchController::CleanUp() {
281 ClearNetworkWaitTimer();
282 kiosk_profile_loader_.reset();
283 startup_app_launcher_.reset();
284 splash_wait_timer_.Stop();
286 if (host_)
287 host_->Finalize();
290 void AppLaunchController::OnNetworkWaitTimedout() {
291 DCHECK(waiting_for_network_);
292 LOG(WARNING) << "OnNetworkWaitTimedout... connection = "
293 << net::NetworkChangeNotifier::GetConnectionType();
294 network_wait_timedout_ = true;
296 MaybeShowNetworkConfigureUI();
298 if (network_timeout_callback_)
299 network_timeout_callback_->Run();
302 void AppLaunchController::OnAppWindowCreated() {
303 DVLOG(1) << "App window created, closing splash screen.";
304 CleanUp();
307 bool AppLaunchController::CanConfigureNetwork() {
308 if (can_configure_network_callback_)
309 return can_configure_network_callback_->Run();
311 policy::BrowserPolicyConnectorChromeOS* connector =
312 g_browser_process->platform_part()->browser_policy_connector_chromeos();
313 if (connector->IsEnterpriseManaged()) {
314 bool should_prompt;
315 if (CrosSettings::Get()->GetBoolean(
316 kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline,
317 &should_prompt)) {
318 return should_prompt;
321 // Default to true to allow network configuration if the policy is missing.
322 return true;
325 return !user_manager::UserManager::Get()->GetOwnerEmail().empty();
328 bool AppLaunchController::NeedOwnerAuthToConfigureNetwork() {
329 if (need_owner_auth_to_configure_network_callback_)
330 return need_owner_auth_to_configure_network_callback_->Run();
332 policy::BrowserPolicyConnectorChromeOS* connector =
333 g_browser_process->platform_part()->browser_policy_connector_chromeos();
334 return !connector->IsEnterpriseManaged();
337 void AppLaunchController::MaybeShowNetworkConfigureUI() {
338 if (CanConfigureNetwork()) {
339 if (NeedOwnerAuthToConfigureNetwork()) {
340 if (network_config_requested_)
341 OnConfigureNetwork();
342 else
343 app_launch_splash_screen_actor_->ToggleNetworkConfig(true);
344 } else {
345 showing_network_dialog_ = true;
346 app_launch_splash_screen_actor_->ShowNetworkConfigureUI();
348 } else {
349 app_launch_splash_screen_actor_->UpdateAppLaunchState(
350 AppLaunchSplashScreenActor::APP_LAUNCH_STATE_NETWORK_WAIT_TIMEOUT);
354 void AppLaunchController::InitializeNetwork() {
355 // Show the network configuration dialog if network is not initialized
356 // after a brief wait time.
357 waiting_for_network_ = true;
358 network_wait_timer_.Start(
359 FROM_HERE,
360 base::TimeDelta::FromSeconds(network_wait_time_),
361 this, &AppLaunchController::OnNetworkWaitTimedout);
363 app_launch_splash_screen_actor_->UpdateAppLaunchState(
364 AppLaunchSplashScreenActor::APP_LAUNCH_STATE_PREPARING_NETWORK);
367 bool AppLaunchController::IsNetworkReady() {
368 return app_launch_splash_screen_actor_->IsNetworkReady();
371 void AppLaunchController::OnLoadingOAuthFile() {
372 app_launch_splash_screen_actor_->UpdateAppLaunchState(
373 AppLaunchSplashScreenActor::APP_LAUNCH_STATE_LOADING_AUTH_FILE);
376 void AppLaunchController::OnInitializingTokenService() {
377 app_launch_splash_screen_actor_->UpdateAppLaunchState(
378 AppLaunchSplashScreenActor::APP_LAUNCH_STATE_LOADING_TOKEN_SERVICE);
381 void AppLaunchController::OnInstallingApp() {
382 app_launch_splash_screen_actor_->UpdateAppLaunchState(
383 AppLaunchSplashScreenActor::APP_LAUNCH_STATE_INSTALLING_APPLICATION);
385 ClearNetworkWaitTimer();
386 app_launch_splash_screen_actor_->ToggleNetworkConfig(false);
388 // We have connectivity at this point, so we can skip the network
389 // configuration dialog if it is being shown.
390 if (showing_network_dialog_) {
391 app_launch_splash_screen_actor_->Show(app_id_);
392 showing_network_dialog_ = false;
393 launch_splash_start_time_ = base::TimeTicks::Now().ToInternalValue();
397 void AppLaunchController::OnReadyToLaunch() {
398 launcher_ready_ = true;
400 if (network_config_requested_)
401 return;
403 if (!webui_visible_)
404 return;
406 if (splash_wait_timer_.IsRunning())
407 return;
409 ClearNetworkWaitTimer();
411 const int64 time_taken_ms = (base::TimeTicks::Now() -
412 base::TimeTicks::FromInternalValue(launch_splash_start_time_)).
413 InMilliseconds();
415 // Enforce that we show app install splash screen for some minimum amount
416 // of time.
417 if (!skip_splash_wait_ && time_taken_ms < kAppInstallSplashScreenMinTimeMS) {
418 splash_wait_timer_.Start(
419 FROM_HERE,
420 base::TimeDelta::FromMilliseconds(
421 kAppInstallSplashScreenMinTimeMS - time_taken_ms),
422 this,
423 &AppLaunchController::OnReadyToLaunch);
424 return;
427 startup_app_launcher_->LaunchApp();
430 void AppLaunchController::OnLaunchSucceeded() {
431 DVLOG(1) << "Kiosk launch succeeded, wait for app window.";
432 app_launch_splash_screen_actor_->UpdateAppLaunchState(
433 AppLaunchSplashScreenActor::APP_LAUNCH_STATE_WAITING_APP_WINDOW);
435 DCHECK(!app_window_watcher_);
436 app_window_watcher_.reset(new AppWindowWatcher(this, app_id_));
439 void AppLaunchController::OnLaunchFailed(KioskAppLaunchError::Error error) {
440 LOG(ERROR) << "Kiosk launch failed. Will now shut down."
441 << ", error=" << error;
442 DCHECK_NE(KioskAppLaunchError::NONE, error);
444 // Saves the error and ends the session to go back to login screen.
445 KioskAppLaunchError::Save(error);
446 chrome::AttemptUserExit();
447 CleanUp();
450 bool AppLaunchController::IsShowingNetworkConfigScreen() {
451 return network_config_requested_;
454 } // namespace chromeos