Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / chromeos / login / app_launch_controller.cc
blobe93d3a7188dabbc221684dcca49954a12157ebfd
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 "apps/shell_window_registry.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/time/time.h"
12 #include "base/values.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/chromeos/app_mode/app_session_lifetime.h"
16 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
17 #include "chrome/browser/chromeos/app_mode/startup_app_launcher.h"
18 #include "chrome/browser/chromeos/login/login_display_host.h"
19 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
20 #include "chrome/browser/chromeos/login/oobe_display.h"
21 #include "chrome/browser/chromeos/login/screens/error_screen_actor.h"
22 #include "chrome/browser/chromeos/login/webui_login_view.h"
23 #include "chrome/browser/chromeos/settings/cros_settings.h"
24 #include "chrome/browser/lifetime/application_lifetime.h"
25 #include "chrome/browser/policy/browser_policy_connector.h"
26 #include "chrome/browser/profiles/profile.h"
27 #include "chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h"
28 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
29 #include "content/public/browser/notification_service.h"
30 #include "net/base/network_change_notifier.h"
32 namespace chromeos {
34 namespace {
36 // Application install splash screen minimum show time in milliseconds.
37 const int kAppInstallSplashScreenMinTimeMS = 3000;
39 } // namespace
41 // static
42 bool AppLaunchController::skip_splash_wait_ = false;
43 int AppLaunchController::network_wait_time_ = 10;
44 base::Closure* AppLaunchController::network_timeout_callback_ = NULL;
45 AppLaunchController::ReturnBoolCallback*
46 AppLaunchController::can_configure_network_callback_ = NULL;
47 AppLaunchController::ReturnBoolCallback*
48 AppLaunchController::need_owner_auth_to_configure_network_callback_ = NULL;
50 ////////////////////////////////////////////////////////////////////////////////
51 // AppLaunchController::AppWindowWatcher
53 class AppLaunchController::AppWindowWatcher
54 : public apps::ShellWindowRegistry::Observer {
55 public:
56 explicit AppWindowWatcher(AppLaunchController* controller)
57 : controller_(controller),
58 window_registry_(apps::ShellWindowRegistry::Get(controller->profile_)) {
59 window_registry_->AddObserver(this);
61 virtual ~AppWindowWatcher() {
62 window_registry_->RemoveObserver(this);
65 private:
66 // apps::ShellWindowRegistry::Observer overrides:
67 virtual void OnShellWindowAdded(apps::ShellWindow* shell_window) OVERRIDE {
68 if (controller_) {
69 controller_->OnAppWindowCreated();
70 controller_= NULL;
73 virtual void OnShellWindowIconChanged(
74 apps::ShellWindow* shell_window) OVERRIDE {}
75 virtual void OnShellWindowRemoved(apps::ShellWindow* shell_window) OVERRIDE {}
77 AppLaunchController* controller_;
78 apps::ShellWindowRegistry* window_registry_;
80 DISALLOW_COPY_AND_ASSIGN(AppWindowWatcher);
83 ////////////////////////////////////////////////////////////////////////////////
84 // AppLaunchController
86 AppLaunchController::AppLaunchController(const std::string& app_id,
87 LoginDisplayHost* host,
88 OobeDisplay* oobe_display)
89 : profile_(NULL),
90 app_id_(app_id),
91 host_(host),
92 oobe_display_(oobe_display),
93 app_launch_splash_screen_actor_(
94 oobe_display_->GetAppLaunchSplashScreenActor()),
95 webui_visible_(false),
96 launcher_ready_(false),
97 waiting_for_network_(false),
98 network_wait_timedout_(false),
99 showing_network_dialog_(false),
100 launch_splash_start_time_(0) {
103 AppLaunchController::~AppLaunchController() {
104 app_launch_splash_screen_actor_->SetDelegate(NULL);
107 void AppLaunchController::StartAppLaunch() {
108 DVLOG(1) << "Starting kiosk mode...";
110 webui_visible_ = host_->GetWebUILoginView()->webui_visible();
111 if (!webui_visible_) {
112 registrar_.Add(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
113 content::NotificationService::AllSources());
115 launch_splash_start_time_ = base::TimeTicks::Now().ToInternalValue();
117 // TODO(tengs): Add a loading profile app launch state.
118 app_launch_splash_screen_actor_->SetDelegate(this);
119 app_launch_splash_screen_actor_->Show(app_id_);
121 kiosk_profile_loader_.reset(
122 new KioskProfileLoader(KioskAppManager::Get(), app_id_, this));
123 kiosk_profile_loader_->Start();
126 // static
127 void AppLaunchController::SkipSplashWaitForTesting() {
128 skip_splash_wait_ = true;
131 // static
132 void AppLaunchController::SetNetworkWaitForTesting(int wait_time_secs) {
133 network_wait_time_ = wait_time_secs;
136 // static
137 void AppLaunchController::SetNetworkTimeoutCallbackForTesting(
138 base::Closure* callback) {
139 network_timeout_callback_ = callback;
142 // static
143 void AppLaunchController::SetCanConfigureNetworkCallbackForTesting(
144 ReturnBoolCallback* can_configure_network_callback) {
145 can_configure_network_callback_ = can_configure_network_callback;
148 // static
149 void AppLaunchController::SetNeedOwnerAuthToConfigureNetworkCallbackForTesting(
150 ReturnBoolCallback* need_owner_auth_callback) {
151 need_owner_auth_to_configure_network_callback_ = need_owner_auth_callback;
154 void AppLaunchController::OnConfigureNetwork() {
155 DCHECK(profile_);
156 showing_network_dialog_ = true;
157 if (CanConfigureNetwork() && NeedOwnerAuthToConfigureNetwork()) {
158 signin_screen_.reset(new AppLaunchSigninScreen(
159 static_cast<OobeUI*>(oobe_display_), this));
160 signin_screen_->Show();
161 } else {
162 // If kiosk mode was configured through enterprise policy, we may
163 // not have an owner user.
164 // TODO(tengs): We need to figure out the appropriate security meausres
165 // for this case.
166 NOTREACHED();
170 void AppLaunchController::OnOwnerSigninSuccess() {
171 app_launch_splash_screen_actor_->ShowNetworkConfigureUI();
172 signin_screen_.reset();
175 void AppLaunchController::Observe(
176 int type,
177 const content::NotificationSource& source,
178 const content::NotificationDetails& details) {
179 DCHECK_EQ(chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, type);
180 DCHECK(!webui_visible_);
181 webui_visible_ = true;
182 launch_splash_start_time_ = base::TimeTicks::Now().ToInternalValue();
183 if (launcher_ready_)
184 OnReadyToLaunch();
187 void AppLaunchController::OnCancelAppLaunch() {
188 if (KioskAppManager::Get()->GetDisableBailoutShortcut())
189 return;
191 OnLaunchFailed(KioskAppLaunchError::USER_CANCEL);
194 void AppLaunchController::OnNetworkStateChanged(bool online) {
195 if (!waiting_for_network_)
196 return;
198 if (online)
199 startup_app_launcher_->ContinueWithNetworkReady();
200 else if (network_wait_timedout_)
201 MaybeShowNetworkConfigureUI();
204 void AppLaunchController::OnProfileLoaded(Profile* profile) {
205 DVLOG(1) << "Profile loaded... Starting app launch.";
206 profile_ = profile;
208 kiosk_profile_loader_.reset();
209 startup_app_launcher_.reset(new StartupAppLauncher(profile_, app_id_, this));
210 startup_app_launcher_->Initialize();
213 void AppLaunchController::OnProfileLoadFailed(
214 KioskAppLaunchError::Error error) {
215 OnLaunchFailed(error);
218 void AppLaunchController::CleanUp() {
219 kiosk_profile_loader_.reset();
220 startup_app_launcher_.reset();
221 splash_wait_timer_.Stop();
223 if (host_)
224 host_->Finalize();
227 void AppLaunchController::OnNetworkWaitTimedout() {
228 DCHECK(waiting_for_network_);
229 LOG(WARNING) << "OnNetworkWaitTimedout... connection = "
230 << net::NetworkChangeNotifier::GetConnectionType();
231 network_wait_timedout_ = true;
233 MaybeShowNetworkConfigureUI();
235 if (network_timeout_callback_)
236 network_timeout_callback_->Run();
239 void AppLaunchController::OnAppWindowCreated() {
240 DVLOG(1) << "App window created, closing splash screen.";
241 CleanUp();
244 bool AppLaunchController::CanConfigureNetwork() {
245 if (can_configure_network_callback_)
246 return can_configure_network_callback_->Run();
248 if (g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
249 bool should_prompt;
250 if (CrosSettings::Get()->GetBoolean(
251 kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline,
252 &should_prompt)) {
253 return should_prompt;
256 // Default to true to allow network configuration if the policy is missing.
257 return true;
260 return !UserManager::Get()->GetOwnerEmail().empty();
263 bool AppLaunchController::NeedOwnerAuthToConfigureNetwork() {
264 if (need_owner_auth_to_configure_network_callback_)
265 return need_owner_auth_to_configure_network_callback_->Run();
267 return !g_browser_process->browser_policy_connector()->IsEnterpriseManaged();
270 void AppLaunchController::MaybeShowNetworkConfigureUI() {
271 if (CanConfigureNetwork()) {
272 if (NeedOwnerAuthToConfigureNetwork()) {
273 app_launch_splash_screen_actor_->ToggleNetworkConfig(true);
274 } else {
275 showing_network_dialog_ = true;
276 app_launch_splash_screen_actor_->ShowNetworkConfigureUI();
278 } else {
279 app_launch_splash_screen_actor_->UpdateAppLaunchState(
280 AppLaunchSplashScreenActor::APP_LAUNCH_STATE_NETWORK_WAIT_TIMEOUT);
284 void AppLaunchController::InitializeNetwork() {
285 // Show the network configration dialog if network is not initialized
286 // after a brief wait time.
287 waiting_for_network_ = true;
288 network_wait_timer_.Start(
289 FROM_HERE,
290 base::TimeDelta::FromSeconds(network_wait_time_),
291 this, &AppLaunchController::OnNetworkWaitTimedout);
293 app_launch_splash_screen_actor_->UpdateAppLaunchState(
294 AppLaunchSplashScreenActor::APP_LAUNCH_STATE_PREPARING_NETWORK);
297 void AppLaunchController::OnLoadingOAuthFile() {
298 app_launch_splash_screen_actor_->UpdateAppLaunchState(
299 AppLaunchSplashScreenActor::APP_LAUNCH_STATE_LOADING_AUTH_FILE);
302 void AppLaunchController::OnInitializingTokenService() {
303 app_launch_splash_screen_actor_->UpdateAppLaunchState(
304 AppLaunchSplashScreenActor::APP_LAUNCH_STATE_LOADING_TOKEN_SERVICE);
307 void AppLaunchController::OnInstallingApp() {
308 app_launch_splash_screen_actor_->UpdateAppLaunchState(
309 AppLaunchSplashScreenActor::APP_LAUNCH_STATE_INSTALLING_APPLICATION);
311 waiting_for_network_ = false;
312 network_wait_timer_.Stop();
313 app_launch_splash_screen_actor_->ToggleNetworkConfig(false);
315 // We have connectivity at this point, so we can skip the network
316 // configuration dialog if it is being shown.
317 if (showing_network_dialog_) {
318 app_launch_splash_screen_actor_->Show(app_id_);
319 showing_network_dialog_ = false;
320 launch_splash_start_time_ = base::TimeTicks::Now().ToInternalValue();
324 void AppLaunchController::OnReadyToLaunch() {
325 launcher_ready_ = true;
326 if (!webui_visible_)
327 return;
329 if (splash_wait_timer_.IsRunning())
330 return;
332 const int64 time_taken_ms = (base::TimeTicks::Now() -
333 base::TimeTicks::FromInternalValue(launch_splash_start_time_)).
334 InMilliseconds();
336 // Enforce that we show app install splash screen for some minimum amount
337 // of time.
338 if (!skip_splash_wait_ && time_taken_ms < kAppInstallSplashScreenMinTimeMS) {
339 splash_wait_timer_.Start(
340 FROM_HERE,
341 base::TimeDelta::FromMilliseconds(
342 kAppInstallSplashScreenMinTimeMS - time_taken_ms),
343 this,
344 &AppLaunchController::OnReadyToLaunch);
345 return;
348 startup_app_launcher_->LaunchApp();
351 void AppLaunchController::OnLaunchSucceeded() {
352 DVLOG(1) << "Kiosk launch succeeded, wait for app window.";
353 app_launch_splash_screen_actor_->UpdateAppLaunchState(
354 AppLaunchSplashScreenActor::APP_LAUNCH_STATE_WAITING_APP_WINDOW);
356 DCHECK(!app_window_watcher_);
357 app_window_watcher_.reset(new AppWindowWatcher(this));
360 void AppLaunchController::OnLaunchFailed(KioskAppLaunchError::Error error) {
361 LOG(ERROR) << "Kiosk launch failed. Will now shut down."
362 << ", error=" << error;
363 DCHECK_NE(KioskAppLaunchError::NONE, error);
365 // Saves the error and ends the session to go back to login screen.
366 KioskAppLaunchError::Save(error);
367 chrome::AttemptUserExit();
368 CleanUp();
371 } // namespace chromeos