diff options
author | tengs@chromium.org <tengs@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-20 12:14:47 +0000 |
---|---|---|
committer | tengs@chromium.org <tengs@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-20 12:14:47 +0000 |
commit | 535d2b1d7883ed07295ce3b8987309aedcd99fc7 (patch) | |
tree | ea20736277c8e23058cf6a8874ee4da3e9e821e0 | |
parent | 1d55316d81e8057c548bd025c0ba7bf8d020170f (diff) | |
download | chromium_src-535d2b1d7883ed07295ce3b8987309aedcd99fc7.zip chromium_src-535d2b1d7883ed07295ce3b8987309aedcd99fc7.tar.gz chromium_src-535d2b1d7883ed07295ce3b8987309aedcd99fc7.tar.bz2 |
Refactor kiosk app launch to be part of login screen UI flow.
The app launch UI no longer creates its own view and is no longer
a separate WebUI page. The splash screen is now a screen included
in the oobe and login flows.
BUG=269182
TEST=updated tests and manually tested on device
Review URL: https://chromiumcodereview.appspot.com/22914008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@218461 0039d316-1c4b-4281-b951-d872f2087c98
59 files changed, 943 insertions, 772 deletions
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 977b96c..6ef5425 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -27,8 +27,6 @@ <if expr="pp_ifdef('chromeos')"> <structure name="IDR_DEMO_USER_LOGIN_HTML" file="resources\chromeos\login\demo_user_login.html" flattenhtml="true" type="chrome_html" /> <structure name="IDR_DEMO_USER_LOGIN_JS" file="resources\chromeos\login\demo_user_login.js" flattenhtml="true" type="chrome_html" /> - <structure name="IDR_APP_LAUNCH_SPLASH_HTML" file="resources\chromeos\app_launch\app_launch.html" flattenhtml="true" type="chrome_html" /> - <structure name="IDR_APP_LAUNCH_SPLASH_JS" file="resources\chromeos\app_launch\app_launch.js" flattenhtml="true" type="chrome_html" /> </if> <structure name="IDR_DOWNLOADS_CSS" file="resources\downloads\downloads.css" flattenhtml="true" type="chrome_html" /> <structure name="IDR_DOWNLOADS_HTML" file="resources\downloads\downloads.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" /> diff --git a/chrome/browser/chromeos/app_mode/app_launch_utils.cc b/chrome/browser/chromeos/app_mode/app_launch_utils.cc new file mode 100644 index 0000000..9b993e4 --- /dev/null +++ b/chrome/browser/chromeos/app_mode/app_launch_utils.cc @@ -0,0 +1,54 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/app_mode/app_launch_utils.h" + +#include "chrome/browser/chromeos/app_mode/kiosk_app_launch_error.h" +#include "chrome/browser/chromeos/app_mode/startup_app_launcher.h" +#include "chrome/browser/lifetime/application_lifetime.h" + +namespace chromeos { + +// A simple manager for the app launch that starts the launch +// and deletes itself when the launch finishes. On launch failure, +// it exits the browser process. +class AppLaunchManager : public StartupAppLauncher::Observer { + public: + AppLaunchManager(Profile* profile, const std::string& app_id) { + startup_app_launcher_.reset(new StartupAppLauncher(profile, app_id)); + } + + void Start() { + startup_app_launcher_->AddObserver(this); + startup_app_launcher_->Start(); + } + + private: + virtual ~AppLaunchManager() {} + + void Cleanup() { delete this; } + + virtual void OnLoadingOAuthFile() OVERRIDE {} + virtual void OnInitializingTokenService() OVERRIDE {} + virtual void OnInitializingNetwork() OVERRIDE {} + virtual void OnNetworkWaitTimedout() OVERRIDE {} + virtual void OnInstallingApp() OVERRIDE {} + virtual void OnLaunchSucceeded() OVERRIDE { Cleanup(); } + virtual void OnLaunchFailed(KioskAppLaunchError::Error error) OVERRIDE { + KioskAppLaunchError::Save(error); + chrome::AttemptUserExit(); + Cleanup(); + } + + scoped_ptr<StartupAppLauncher> startup_app_launcher_; + + DISALLOW_COPY_AND_ASSIGN(AppLaunchManager); +}; + +void LaunchAppOrDie(Profile* profile, const std::string& app_id) { + // AppLaunchManager manages its own lifetime. + (new AppLaunchManager(profile, app_id))->Start(); +} + +} // namespace chromeos diff --git a/chrome/browser/chromeos/app_mode/app_launch_utils.h b/chrome/browser/chromeos/app_mode/app_launch_utils.h new file mode 100644 index 0000000..ac30933 --- /dev/null +++ b/chrome/browser/chromeos/app_mode/app_launch_utils.h @@ -0,0 +1,22 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_APP_MODE_APP_LAUNCH_UTILS_H_ +#define CHROME_BROWSER_CHROMEOS_APP_MODE_APP_LAUNCH_UTILS_H_ + +#include <string> + +class Profile; + +namespace chromeos { + +// Attempts to launch the app given by |app_id| in app mode +// or exit on failure. This function will not show any launch UI +// during the launch. Use StartupAppLauncher for finer control +// over the app launch processes. +void LaunchAppOrDie(Profile *profile, const std::string& app_id); + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_APP_MODE_APP_LAUNCH_UTILS_H_ diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_launcher.cc b/chrome/browser/chromeos/app_mode/kiosk_profile_loader.cc index a2cac72..530cc4d 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_launcher.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_profile_loader.cc @@ -2,19 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/chromeos/app_mode/kiosk_app_launcher.h" +#include "chrome/browser/chromeos/app_mode/kiosk_profile_loader.h" #include "base/chromeos/chromeos_version.h" #include "base/logging.h" #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" -#include "chrome/browser/chromeos/app_mode/startup_app_launcher.h" #include "chrome/browser/chromeos/login/login_display_host_impl.h" #include "chrome/browser/chromeos/login/login_utils.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/settings/cros_settings.h" -#include "chrome/browser/chromeos/ui/app_launch_view.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chromeos/cryptohome/async_method_caller.h" #include "chromeos/cryptohome/cryptohome_library.h" @@ -32,21 +30,18 @@ void IgnoreResult(bool mount_success, cryptohome::MountError mount_error) {} } // namespace -// static -KioskAppLauncher* KioskAppLauncher::running_instance_ = NULL; - //////////////////////////////////////////////////////////////////////////////// -// KioskAppLauncher::CryptohomedChecker ensures cryptohome daemon is up +// KioskProfileLoader::CryptohomedChecker ensures cryptohome daemon is up // and running by issuing an IsMounted call. If the call does not go through // and chromeos::DBUS_METHOD_CALL_SUCCESS is not returned, it will retry after // some time out and at the maximum five times before it gives up. Upon -// success, it resumes the launch by calling KioskAppLauncher::StartMount. +// success, it resumes the launch by calling KioskProfileLoader::StartMount. -class KioskAppLauncher::CryptohomedChecker +class KioskProfileLoader::CryptohomedChecker : public base::SupportsWeakPtr<CryptohomedChecker> { public: - explicit CryptohomedChecker(KioskAppLauncher* launcher) - : launcher_(launcher), + explicit CryptohomedChecker(KioskProfileLoader* loader) + : loader_(loader), retry_count_(0) { } ~CryptohomedChecker() {} @@ -89,26 +84,26 @@ class KioskAppLauncher::CryptohomedChecker void ReportCheckResult(KioskAppLaunchError::Error error) { if (error == KioskAppLaunchError::NONE) - launcher_->StartMount(); + loader_->StartMount(); else - launcher_->ReportLaunchResult(error); + loader_->ReportLaunchResult(error); } - KioskAppLauncher* launcher_; + KioskProfileLoader* loader_; int retry_count_; DISALLOW_COPY_AND_ASSIGN(CryptohomedChecker); }; //////////////////////////////////////////////////////////////////////////////// -// KioskAppLauncher::ProfileLoader creates or loads the app profile. +// KioskProfileLoader::ProfileLoader actually creates or loads the app profile. -class KioskAppLauncher::ProfileLoader : public LoginUtils::Delegate { +class KioskProfileLoader::ProfileLoader : public LoginUtils::Delegate { public: ProfileLoader(KioskAppManager* kiosk_app_manager, - KioskAppLauncher* kiosk_app_launcher) - : kiosk_app_launcher_(kiosk_app_launcher), - user_id_(kiosk_app_launcher->user_id_) { + KioskProfileLoader* kiosk_profile_loader) + : kiosk_profile_loader_(kiosk_profile_loader), + user_id_(kiosk_profile_loader->user_id_) { CHECK(!user_id_.empty()); } @@ -129,7 +124,7 @@ class KioskAppLauncher::ProfileLoader : public LoginUtils::Delegate { if (!success) { LOG(ERROR) << "Unable to retrieve username hash for user '" << user_id_ << "'."; - kiosk_app_launcher_->ReportLaunchResult( + kiosk_profile_loader_->ReportLaunchResult( KioskAppLaunchError::UNABLE_TO_RETRIEVE_HASH); return; } @@ -147,66 +142,50 @@ class KioskAppLauncher::ProfileLoader : public LoginUtils::Delegate { // LoginUtils::Delegate overrides: virtual void OnProfilePrepared(Profile* profile) OVERRIDE { - kiosk_app_launcher_->OnProfilePrepared(profile); + kiosk_profile_loader_->OnProfilePrepared(profile); } - KioskAppLauncher* kiosk_app_launcher_; + KioskProfileLoader* kiosk_profile_loader_; std::string user_id_; DISALLOW_COPY_AND_ASSIGN(ProfileLoader); }; //////////////////////////////////////////////////////////////////////////////// -// KioskAppLauncher +// KioskProfileLoader -KioskAppLauncher::KioskAppLauncher(KioskAppManager* kiosk_app_manager, - const std::string& app_id) +KioskProfileLoader::KioskProfileLoader(KioskAppManager* kiosk_app_manager, + const std::string& app_id, + Delegate* delegate) : kiosk_app_manager_(kiosk_app_manager), app_id_(app_id), + delegate_(delegate), remove_attempted_(false) { KioskAppManager::App app; CHECK(kiosk_app_manager_->GetApp(app_id_, &app)); user_id_ = app.user_id; } -KioskAppLauncher::~KioskAppLauncher() {} +KioskProfileLoader::~KioskProfileLoader() {} -void KioskAppLauncher::Start() { +void KioskProfileLoader::Start() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (running_instance_) { - LOG(WARNING) << "Unable to launch " << app_id_ << "with a pending launch."; - ReportLaunchResult(KioskAppLaunchError::HAS_PENDING_LAUNCH); - return; - } - - running_instance_ = this; // Reset in ReportLaunchResult. - - // Show app launch splash. The spash is removed either after a successful - // launch or chrome exit because of launch failure. - chromeos::ShowAppLaunchSplashScreen(app_id_); - // Check cryptohomed. If all goes good, flow goes to StartMount. Otherwise // it goes to ReportLaunchResult with failure. crytohomed_checker.reset(new CryptohomedChecker(this)); crytohomed_checker->StartCheck(); } -void KioskAppLauncher::ReportLaunchResult(KioskAppLaunchError::Error error) { +void KioskProfileLoader::ReportLaunchResult(KioskAppLaunchError::Error error) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - running_instance_ = NULL; - if (error != KioskAppLaunchError::NONE) { - // Saves the error and ends the session to go back to login screen. - KioskAppLaunchError::Save(error); - chrome::AttemptUserExit(); + delegate_->OnProfileLoadFailed(error); } - - delete this; } -void KioskAppLauncher::StartMount() { +void KioskProfileLoader::StartMount() { // Nuke old home that uses |app_id_| as cryptohome user id. // TODO(xiyuan): Remove this after all clients migrated to new home. cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove( @@ -216,12 +195,12 @@ void KioskAppLauncher::StartMount() { cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountPublic( user_id_, cryptohome::CREATE_IF_MISSING, - base::Bind(&KioskAppLauncher::MountCallback, + base::Bind(&KioskProfileLoader::MountCallback, base::Unretained(this))); } -void KioskAppLauncher::MountCallback(bool mount_success, - cryptohome::MountError mount_error) { +void KioskProfileLoader::MountCallback(bool mount_success, + cryptohome::MountError mount_error) { if (mount_success) { profile_loader_.reset(new ProfileLoader(kiosk_app_manager_, this)); profile_loader_->Start(); @@ -241,32 +220,27 @@ void KioskAppLauncher::MountCallback(bool mount_success, ReportLaunchResult(KioskAppLaunchError::UNABLE_TO_MOUNT); } -void KioskAppLauncher::AttemptRemove() { +void KioskProfileLoader::AttemptRemove() { cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove( user_id_, - base::Bind(&KioskAppLauncher::RemoveCallback, + base::Bind(&KioskProfileLoader::RemoveCallback, base::Unretained(this))); } -void KioskAppLauncher::RemoveCallback(bool success, +void KioskProfileLoader::RemoveCallback(bool success, cryptohome::MountError return_code) { if (success) { StartMount(); return; } - LOG(ERROR) << "Failed to remove app cryptohome, erro=" << return_code; + LOG(ERROR) << "Failed to remove app cryptohome, error=" << return_code; ReportLaunchResult(KioskAppLaunchError::UNABLE_TO_REMOVE); } -void KioskAppLauncher::OnProfilePrepared(Profile* profile) { - // StartupAppLauncher deletes itself when done. - (new chromeos::StartupAppLauncher(profile, app_id_))->Start(); - - if (LoginDisplayHostImpl::default_host()) - LoginDisplayHostImpl::default_host()->Finalize(); +void KioskProfileLoader::OnProfilePrepared(Profile* profile) { UserManager::Get()->SessionStarted(); - + delegate_->OnProfileLoaded(profile); ReportLaunchResult(KioskAppLaunchError::NONE); } diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_launcher.h b/chrome/browser/chromeos/app_mode/kiosk_profile_loader.h index 5b9908f..7c54304 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_launcher.h +++ b/chrome/browser/chromeos/app_mode/kiosk_profile_loader.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_CHROMEOS_APP_MODE_KIOSK_APP_LAUNCHER_H_ -#define CHROME_BROWSER_CHROMEOS_APP_MODE_KIOSK_APP_LAUNCHER_H_ +#ifndef CHROME_BROWSER_CHROMEOS_APP_MODE_KIOSK_PROFILE_LOADER_H_ +#define CHROME_BROWSER_CHROMEOS_APP_MODE_KIOSK_PROFILE_LOADER_H_ #include <string> @@ -19,28 +19,33 @@ namespace chromeos { class KioskAppManager; -// KioskAppLauncher launches a given app from login screen. It first attempts +// KioskProfileLoader loads a special profile for a given app. It first attempts // to mount a cryptohome for the app. If the mount is successful, it prepares -// app profile then calls StartupAppLauncher to finish the launch. If mount -// fails, it sets relevant launch error and restart chrome to gets back to -// the login screen. Note that there should only be one launch attempt in -// progress. -class KioskAppLauncher { +// app profile then calls the delegate. +class KioskProfileLoader { public: - KioskAppLauncher(KioskAppManager* kiosk_app_manager, - const std::string& app_id); + class Delegate { + public: + virtual void OnProfileLoaded(Profile* profile) = 0; + virtual void OnProfileLoadFailed(KioskAppLaunchError::Error error) = 0; - // Starts a launch attempt. Fails immediately if there is already a launch - // attempt running. + protected: + virtual ~Delegate() {} + }; + + KioskProfileLoader(KioskAppManager* kiosk_app_manager, + const std::string& app_id, + Delegate* delegate); + + ~KioskProfileLoader(); + + // Starts profile load. Calls delegate on success or failure. void Start(); private: class CryptohomedChecker; class ProfileLoader; - // Private dtor because this class manages its own lifetime. - ~KioskAppLauncher(); - void ReportLaunchResult(KioskAppLaunchError::Error error); void StartMount(); @@ -52,12 +57,10 @@ class KioskAppLauncher { void OnProfilePrepared(Profile* profile); - // The instance of the current running launch. - static KioskAppLauncher* running_instance_; - KioskAppManager* kiosk_app_manager_; const std::string app_id_; std::string user_id_; + Delegate* delegate_; scoped_ptr<CryptohomedChecker> crytohomed_checker; scoped_ptr<ProfileLoader> profile_loader_; @@ -65,9 +68,9 @@ class KioskAppLauncher { // Whether remove existing cryptohome has attempted. bool remove_attempted_; - DISALLOW_COPY_AND_ASSIGN(KioskAppLauncher); + DISALLOW_COPY_AND_ASSIGN(KioskProfileLoader); }; } // namespace chromeos -#endif // CHROME_BROWSER_CHROMEOS_APP_MODE_KIOSK_APP_LAUNCHER_H_ +#endif // CHROME_BROWSER_CHROMEOS_APP_MODE_KIOSK_PROFILE_LOADER_H_ diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc index 8308bf0..9f6bc11e 100644 --- a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc +++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc @@ -4,7 +4,6 @@ #include "chrome/browser/chromeos/app_mode/startup_app_launcher.h" -#include "ash/shell.h" #include "base/command_line.h" #include "base/files/file_path.h" #include "base/json/json_file_value_serializer.h" @@ -15,7 +14,6 @@ #include "chrome/browser/chromeos/app_mode/app_session_lifetime.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/chromeos/login/user_manager.h" -#include "chrome/browser/chromeos/ui/app_launch_view.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_system.h" #include "chrome/browser/extensions/webstore_startup_installer.h" @@ -49,9 +47,6 @@ const char kOAuthClientSecret[] = "client_secret"; const base::FilePath::CharType kOAuthFileName[] = FILE_PATH_LITERAL("kiosk_auth"); -// Application install splash screen minimum show time in milliseconds. -const int kAppInstallSplashScreenMinTimeMS = 3000; - bool IsAppInstalled(Profile* profile, const std::string& app_id) { return extensions::ExtensionSystem::Get(profile)->extension_service()-> GetInstalledExtension(app_id); @@ -59,31 +54,35 @@ bool IsAppInstalled(Profile* profile, const std::string& app_id) { } // namespace + StartupAppLauncher::StartupAppLauncher(Profile* profile, const std::string& app_id) : profile_(profile), - app_id_(app_id), - launch_splash_start_time_(0) { + app_id_(app_id) { DCHECK(profile_); DCHECK(Extension::IdIsValid(app_id_)); - DCHECK(ash::Shell::HasInstance()); - ash::Shell::GetInstance()->AddPreTargetHandler(this); } StartupAppLauncher::~StartupAppLauncher() { - DCHECK(ash::Shell::HasInstance()); - ash::Shell::GetInstance()->RemovePreTargetHandler(this); } void StartupAppLauncher::Start() { - launch_splash_start_time_ = base::TimeTicks::Now().ToInternalValue(); DVLOG(1) << "Starting... connection = " << net::NetworkChangeNotifier::GetConnectionType(); - chromeos::ShowAppLaunchSplashScreen(app_id_); StartLoadingOAuthFile(); } +void StartupAppLauncher::AddObserver(Observer* observer) { + observer_list_.AddObserver(observer); +} + +void StartupAppLauncher::RemoveObserver(Observer* observer) { + observer_list_.RemoveObserver(observer); +} + void StartupAppLauncher::StartLoadingOAuthFile() { + FOR_EACH_OBSERVER(Observer, observer_list_, OnLoadingOAuthFile()); + KioskOAuthParams* auth_params = new KioskOAuthParams(); BrowserThread::PostBlockingPoolTaskAndReply( FROM_HERE, @@ -134,8 +133,8 @@ void StartupAppLauncher::OnOAuthFileLoaded(KioskOAuthParams* auth_params) { } void StartupAppLauncher::InitializeNetwork() { - chromeos::UpdateAppLaunchSplashScreenState( - chromeos::APP_LAUNCH_STATE_PREPARING_NETWORK); + FOR_EACH_OBSERVER(Observer, observer_list_, OnInitializingNetwork()); + // Set a maximum allowed wait time for network. const int kMaxNetworkWaitSeconds = 5 * 60; network_wait_timer_.Start( @@ -148,8 +147,8 @@ void StartupAppLauncher::InitializeNetwork() { } void StartupAppLauncher::InitializeTokenService() { - chromeos::UpdateAppLaunchSplashScreenState( - chromeos::APP_LAUNCH_STATE_LOADING_TOKEN_SERVICE); + FOR_EACH_OBSERVER(Observer, observer_list_, OnInitializingTokenService()); + ProfileOAuth2TokenService* profile_token_service = ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); if (profile_token_service->RefreshTokenIsAvailable()) { @@ -199,40 +198,15 @@ void StartupAppLauncher::OnRefreshTokensLoaded() { InitializeNetwork(); } -void StartupAppLauncher::Cleanup() { - chromeos::CloseAppLaunchSplashScreen(); - - delete this; -} - void StartupAppLauncher::OnLaunchSuccess() { - const int64 time_taken_ms = (base::TimeTicks::Now() - - base::TimeTicks::FromInternalValue(launch_splash_start_time_)). - InMilliseconds(); - - // Enforce that we show app install splash screen for some minimum amount - // of time. - if (time_taken_ms < kAppInstallSplashScreenMinTimeMS) { - BrowserThread::PostDelayedTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&StartupAppLauncher::OnLaunchSuccess, AsWeakPtr()), - base::TimeDelta::FromMilliseconds( - kAppInstallSplashScreenMinTimeMS - time_taken_ms)); - return; - } - - Cleanup(); + FOR_EACH_OBSERVER(Observer, observer_list_, OnLaunchSucceeded()); } void StartupAppLauncher::OnLaunchFailure(KioskAppLaunchError::Error error) { + LOG(ERROR) << "App launch failed"; DCHECK_NE(KioskAppLaunchError::NONE, error); - // Saves the error and ends the session to go back to login screen. - KioskAppLaunchError::Save(error); - chrome::AttemptUserExit(); - - Cleanup(); + FOR_EACH_OBSERVER(Observer, observer_list_, OnLaunchFailed(error)); } void StartupAppLauncher::Launch() { @@ -261,12 +235,11 @@ void StartupAppLauncher::Launch() { } void StartupAppLauncher::BeginInstall() { + FOR_EACH_OBSERVER(Observer, observer_list_, OnInstallingApp()); + DVLOG(1) << "BeginInstall... connection = " << net::NetworkChangeNotifier::GetConnectionType(); - chromeos::UpdateAppLaunchSplashScreenState( - chromeos::APP_LAUNCH_STATE_INSTALLING_APPLICATION); - if (IsAppInstalled(profile_, app_id_)) { Launch(); return; @@ -293,13 +266,18 @@ void StartupAppLauncher::InstallCallback(bool success, return; } - LOG(ERROR) << "Failed to install app with error: " << error; + // TODO: revert this. + LOG(ERROR) << "Failed to install app with error: " << error << "."; + LOG(ERROR) << " " << app_id_; OnLaunchFailure(KioskAppLaunchError::UNABLE_TO_INSTALL); } void StartupAppLauncher::OnNetworkWaitTimedout() { LOG(WARNING) << "OnNetworkWaitTimedout... connection = " << net::NetworkChangeNotifier::GetConnectionType(); + + FOR_EACH_OBSERVER(Observer, observer_list_, OnNetworkWaitTimedout()); + // Timeout in waiting for online. Try the install anyway. net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); BeginInstall(); @@ -320,20 +298,4 @@ void StartupAppLauncher::OnNetworkChanged( } } -void StartupAppLauncher::OnKeyEvent(ui::KeyEvent* event) { - if (event->type() != ui::ET_KEY_PRESSED) - return; - - if (KioskAppManager::Get()->GetDisableBailoutShortcut()) - return; - - if (event->key_code() != ui::VKEY_S || - !(event->flags() & ui::EF_CONTROL_DOWN) || - !(event->flags() & ui::EF_ALT_DOWN)) { - return; - } - - OnLaunchFailure(KioskAppLaunchError::USER_CANCEL); -} - } // namespace chromeos diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.h b/chrome/browser/chromeos/app_mode/startup_app_launcher.h index ac7e5ae..5ed968e 100644 --- a/chrome/browser/chromeos/app_mode/startup_app_launcher.h +++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.h @@ -10,11 +10,11 @@ #include "base/basictypes.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "base/observer_list.h" #include "base/timer/timer.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_launch_error.h" #include "chrome/browser/signin/oauth2_token_service.h" #include "net/base/network_change_notifier.h" -#include "ui/base/events/event_handler.h" class Profile; @@ -25,26 +25,43 @@ class WebstoreStandaloneInstaller; namespace chromeos { // Launches the app at startup. The flow roughly looks like this: -// - Starts the app launch splash screen; // - Checks if the app is installed in user profile (aka app profile); // - If the app is installed, launch it and finish the flow; // - If not installed, prepare to start install by checking network online // state; // - If network gets online in time, start to install the app from web store; // - If all goes good, launches the app and finish the flow; -// If anything goes wrong, it exits app mode and goes back to login screen. class StartupAppLauncher : public base::SupportsWeakPtr<StartupAppLauncher>, public OAuth2TokenService::Observer, - public net::NetworkChangeNotifier::NetworkChangeObserver, - public ui::EventHandler { + public net::NetworkChangeNotifier::NetworkChangeObserver { public: + class Observer { + public: + virtual void OnLoadingOAuthFile() = 0; + virtual void OnInitializingTokenService() = 0; + virtual void OnInitializingNetwork() = 0; + virtual void OnNetworkWaitTimedout() = 0; + virtual void OnInstallingApp() = 0; + virtual void OnLaunchSucceeded() = 0; + virtual void OnLaunchFailed(KioskAppLaunchError::Error error) = 0; + + protected: + virtual ~Observer() {} + }; + StartupAppLauncher(Profile* profile, const std::string& app_id); + virtual ~StartupAppLauncher(); + // Starts app launcher. If |skip_auth_setup| is set, we will skip // TokenService initialization. void Start(); + // Add and remove observers for app launch procedure. + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + private: // OAuth parameters from /home/chronos/kiosk_auth file. struct KioskOAuthParams { @@ -53,10 +70,6 @@ class StartupAppLauncher std::string client_secret; }; - // Private dtor because this class manages its own lifetime. - virtual ~StartupAppLauncher(); - - void Cleanup(); void OnLaunchSuccess(); void OnLaunchFailure(KioskAppLaunchError::Error error); @@ -82,13 +95,9 @@ class StartupAppLauncher virtual void OnNetworkChanged( net::NetworkChangeNotifier::ConnectionType type) OVERRIDE; - // ui::EventHandler overrides: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - Profile* profile_; const std::string app_id_; - - int64 launch_splash_start_time_; + ObserverList<Observer> observer_list_; scoped_refptr<extensions::WebstoreStandaloneInstaller> installer_; base::OneShotTimer<StartupAppLauncher> network_wait_timer_; diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index d6a251e..08261d2 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc @@ -27,7 +27,6 @@ #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/accessibility/magnification_manager.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_launch_error.h" -#include "chrome/browser/chromeos/app_mode/kiosk_app_launcher.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/chromeos/boot_times_loader.h" #include "chrome/browser/chromeos/contacts/contact_manager.h" @@ -202,9 +201,20 @@ bool ShouldAutoLaunchKioskApp(const CommandLine& command_line) { KioskAppLaunchError::Get() == KioskAppLaunchError::NONE; } +void RunAutoLaunchKioskApp() { + ShowLoginWizard(chromeos::WizardController::kAppLaunchSplashScreenName); + + // Login screen is skipped but 'login-prompt-visible' signal is still needed. + LOG(INFO) << "Kiosk app auto launch >> login-prompt-visible"; + DBusThreadManager::Get()->GetSessionManagerClient()-> + EmitLoginPromptVisible(); +} + void OptionallyRunChromeOSLoginManager(const CommandLine& parsed_command_line, Profile* profile) { - if (parsed_command_line.HasSwitch(switches::kLoginManager)) { + if (ShouldAutoLaunchKioskApp(parsed_command_line)) { + RunAutoLaunchKioskApp(); + } else if (parsed_command_line.HasSwitch(switches::kLoginManager)) { const std::string first_screen = parsed_command_line.HasSwitch(switches::kLoginScreen) ? WizardController::kLoginScreenName : std::string(); @@ -234,17 +244,6 @@ void OptionallyRunChromeOSLoginManager(const CommandLine& parsed_command_line, } } -void RunAutoLaunchKioskApp() { - // KioskAppLauncher deletes itself when done. - (new KioskAppLauncher(KioskAppManager::Get(), - KioskAppManager::Get()->GetAutoLaunchApp()))->Start(); - - // Login screen is skipped but 'login-prompt-visible' signal is still needed. - LOG(INFO) << "Kiosk app auto launch >> login-prompt-visible"; - DBusThreadManager::Get()->GetSessionManagerClient()-> - EmitLoginPromptVisible(); -} - } // namespace namespace internal { @@ -597,11 +596,7 @@ void ChromeBrowserMainPartsChromeos::PostProfileInit() { // Thus only show login manager in normal (non-testing) mode. if (!parameters().ui_task || parsed_command_line().HasSwitch(switches::kForceLoginManagerInTests)) { - if (ShouldAutoLaunchKioskApp(parsed_command_line())) { - RunAutoLaunchKioskApp(); - } else { - OptionallyRunChromeOSLoginManager(parsed_command_line(), profile()); - } + OptionallyRunChromeOSLoginManager(parsed_command_line(), profile()); } // These observers must be initialized after the profile because diff --git a/chrome/browser/chromeos/login/app_launch_controller.cc b/chrome/browser/chromeos/login/app_launch_controller.cc new file mode 100644 index 0000000..65819ec --- /dev/null +++ b/chrome/browser/chromeos/login/app_launch_controller.cc @@ -0,0 +1,157 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/login/app_launch_controller.h" + +#include "base/files/file_path.h" +#include "base/json/json_file_value_serializer.h" +#include "base/time/time.h" +#include "base/values.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/app_mode/app_session_lifetime.h" +#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" +#include "chrome/browser/chromeos/app_mode/startup_app_launcher.h" +#include "chrome/browser/chromeos/login/login_display_host.h" +#include "chrome/browser/chromeos/login/oobe_display.h" +#include "chrome/browser/lifetime/application_lifetime.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h" +#include "content/public/browser/browser_thread.h" + +namespace chromeos { + +namespace { + +// Application install splash screen minimum show time in milliseconds. +const int kAppInstallSplashScreenMinTimeMS = 3000; + +} // namespace + +// static +bool AppLaunchController::skip_splash_wait_ = false; + +AppLaunchController::AppLaunchController(const std::string& app_id, + LoginDisplayHost* host, + OobeDisplay* oobe_display) + : profile_(NULL), + app_id_(app_id), + host_(host), + oobe_display_(oobe_display), + app_launch_splash_screen_actor_( + oobe_display_->GetAppLaunchSplashScreenActor()), + launch_splash_start_time_(0) { +} + +AppLaunchController::~AppLaunchController() { +} + +void AppLaunchController::StartAppLaunch() { + DVLOG(1) << "Starting kiosk mode..."; + launch_splash_start_time_ = base::TimeTicks::Now().ToInternalValue(); + + // TODO(tengs): Add a loading profile app launch state. + app_launch_splash_screen_actor_->SetDelegate(this); + app_launch_splash_screen_actor_->Show(app_id_); + + // KioskProfileLoader manages its own lifetime. + kiosk_profile_loader_.reset( + new KioskProfileLoader(KioskAppManager::Get(), app_id_, this)); + kiosk_profile_loader_->Start(); +} + +// static +void AppLaunchController::SkipSplashWaitForTesting() { + skip_splash_wait_ = true; +} + +void AppLaunchController::OnConfigureNetwork() { + // TODO(tengs): Implement network configuration in app launch. +} + +void AppLaunchController::OnCancelAppLaunch() { + if (KioskAppManager::Get()->GetDisableBailoutShortcut()) + return; + + OnLaunchFailed(KioskAppLaunchError::USER_CANCEL); +} + +void AppLaunchController::OnProfileLoaded(Profile* profile) { + DVLOG(1) << "Profile loaded... Starting app launch."; + profile_ = profile; + + // StartupAppLauncher manages its own lifetime. + startup_app_launcher_.reset(new StartupAppLauncher(profile_, app_id_)); + startup_app_launcher_->AddObserver(this); + startup_app_launcher_->Start(); +} + +void AppLaunchController::OnProfileLoadFailed( + KioskAppLaunchError::Error error) { + OnLaunchFailed(error); +} + +void AppLaunchController::Cleanup() { + kiosk_profile_loader_.reset(); + startup_app_launcher_.reset(); + + if (host_) + host_->Finalize(); +} + +void AppLaunchController::OnLoadingOAuthFile() { + app_launch_splash_screen_actor_->UpdateAppLaunchState( + AppLaunchSplashScreenActor::APP_LAUNCH_STATE_LOADING_AUTH_FILE); +} + +void AppLaunchController::OnInitializingTokenService() { + app_launch_splash_screen_actor_->UpdateAppLaunchState( + AppLaunchSplashScreenActor::APP_LAUNCH_STATE_LOADING_TOKEN_SERVICE); +} + +void AppLaunchController::OnInitializingNetwork() { + app_launch_splash_screen_actor_->UpdateAppLaunchState( + AppLaunchSplashScreenActor::APP_LAUNCH_STATE_PREPARING_NETWORK); +} + +void AppLaunchController::OnNetworkWaitTimedout() { +} + +void AppLaunchController::OnInstallingApp() { + app_launch_splash_screen_actor_->UpdateAppLaunchState( + AppLaunchSplashScreenActor::APP_LAUNCH_STATE_INSTALLING_APPLICATION); +} + +void AppLaunchController::OnLaunchSucceeded() { + const int64 time_taken_ms = (base::TimeTicks::Now() - + base::TimeTicks::FromInternalValue(launch_splash_start_time_)). + InMilliseconds(); + + // Enforce that we show app install splash screen for some minimum amount + // of time. + if (!skip_splash_wait_ && time_taken_ms < kAppInstallSplashScreenMinTimeMS) { + content::BrowserThread::PostDelayedTask( + content::BrowserThread::UI, + FROM_HERE, + base::Bind(&AppLaunchController::OnLaunchSucceeded, AsWeakPtr()), + base::TimeDelta::FromMilliseconds( + kAppInstallSplashScreenMinTimeMS - time_taken_ms)); + return; + } + + DVLOG(1) << "Kiosk launch succeeded!"; + Cleanup(); +} + +void AppLaunchController::OnLaunchFailed(KioskAppLaunchError::Error error) { + LOG(ERROR) << "Kiosk launch failed. Will now shut down."; + DCHECK_NE(KioskAppLaunchError::NONE, error); + + // Saves the error and ends the session to go back to login screen. + KioskAppLaunchError::Save(error); + chrome::AttemptUserExit(); + Cleanup(); +} + + +} // namespace chromeos diff --git a/chrome/browser/chromeos/login/app_launch_controller.h b/chrome/browser/chromeos/login/app_launch_controller.h new file mode 100644 index 0000000..f1bb749 --- /dev/null +++ b/chrome/browser/chromeos/login/app_launch_controller.h @@ -0,0 +1,82 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_APP_LAUNCH_CONTROLLER_H_ +#define CHROME_BROWSER_CHROMEOS_LOGIN_APP_LAUNCH_CONTROLLER_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/timer/timer.h" +#include "chrome/browser/chromeos/app_mode/kiosk_app_launch_error.h" +#include "chrome/browser/chromeos/app_mode/kiosk_profile_loader.h" +#include "chrome/browser/chromeos/app_mode/startup_app_launcher.h" +#include "chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h" + +class Profile; + +namespace chromeos { + +class LoginDisplayHost; +class OobeDisplay; + +// Controller for the kiosk app launch process, responsible for +// coordinating loading the kiosk profile, launching the app, and +// updating the splash screen UI. +class AppLaunchController + : public base::SupportsWeakPtr<AppLaunchController>, + public AppLaunchSplashScreenActor::Delegate, + public KioskProfileLoader::Delegate, + public StartupAppLauncher::Observer { + public: + AppLaunchController(const std::string& app_id, + LoginDisplayHost* host, + OobeDisplay* oobe_display); + + virtual ~AppLaunchController(); + + void StartAppLaunch(); + + static void SkipSplashWaitForTesting(); + + private: + void Cleanup(); + + // KioskProfileLoader::Delegate overrides: + virtual void OnProfileLoaded(Profile* profile) OVERRIDE; + virtual void OnProfileLoadFailed(KioskAppLaunchError::Error error) OVERRIDE; + + // AppLaunchSplashScreenActor::Delegate overrides: + virtual void OnConfigureNetwork() OVERRIDE; + virtual void OnCancelAppLaunch() OVERRIDE; + + // StartupAppLauncher::Observer overrides: + virtual void OnLoadingOAuthFile() OVERRIDE; + virtual void OnInitializingTokenService() OVERRIDE; + virtual void OnInitializingNetwork() OVERRIDE; + virtual void OnNetworkWaitTimedout() OVERRIDE; + virtual void OnInstallingApp() OVERRIDE; + virtual void OnLaunchSucceeded() OVERRIDE; + virtual void OnLaunchFailed(KioskAppLaunchError::Error error) OVERRIDE; + + Profile* profile_; + const std::string app_id_; + LoginDisplayHost* host_; + OobeDisplay* oobe_display_; + AppLaunchSplashScreenActor* app_launch_splash_screen_actor_; + scoped_ptr<KioskProfileLoader> kiosk_profile_loader_; + scoped_ptr<StartupAppLauncher> startup_app_launcher_; + + int64 launch_splash_start_time_; + + static bool skip_splash_wait_; + + DISALLOW_COPY_AND_ASSIGN(AppLaunchController); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_APP_LAUNCH_CONTROLLER_H_ diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc index bc3d737..4078fde 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.cc +++ b/chrome/browser/chromeos/login/existing_user_controller.cc @@ -216,14 +216,6 @@ void ExistingUserController::ResumeLogin() { resume_login_callback_.Reset(); } -void ExistingUserController::PrepareKioskAppLaunch() { - // Disable login UI while waiting for the kiosk app launch. There is no - // balanced UI enable call because this very login screen will not be - // accessed again. If app is launched, it will be destroyed. If app fails to - // launch, chrome is restarted to go back to a new login screen. - login_display_->SetUIEnabled(false); -} - //////////////////////////////////////////////////////////////////////////////// // ExistingUserController, content::NotificationObserver implementation: // @@ -580,6 +572,10 @@ void ExistingUserController::LoginAsPublicAccount( l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_PUBLIC_ACCOUNT)); } +void ExistingUserController::LoginAsKioskApp(const std::string& app_id) { + host_->StartAppLaunch(app_id); +} + void ExistingUserController::OnSigninScreenReady() { signin_screen_ready_ = true; StartPublicSessionAutoLoginTimer(); diff --git a/chrome/browser/chromeos/login/existing_user_controller.h b/chrome/browser/chromeos/login/existing_user_controller.h index 7a2ff11..0580c0b 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.h +++ b/chrome/browser/chromeos/login/existing_user_controller.h @@ -67,9 +67,6 @@ class ExistingUserController : public LoginDisplay::Delegate, // Tells the controller to resume a pending login. void ResumeLogin(); - // Invoked to prepare for a kiosk app launch attempt. - void PrepareKioskAppLaunch(); - // Start the public session auto-login timer. void StartPublicSessionAutoLoginTimer(); @@ -87,6 +84,7 @@ class ExistingUserController : public LoginDisplay::Delegate, virtual void LoginAsRetailModeUser() OVERRIDE; virtual void LoginAsGuest() OVERRIDE; virtual void LoginAsPublicAccount(const std::string& username) OVERRIDE; + virtual void LoginAsKioskApp(const std::string& app_id) OVERRIDE; virtual void OnSigninScreenReady() OVERRIDE; virtual void OnUserSelected(const std::string& username) OVERRIDE; virtual void OnStartEnterpriseEnrollment() OVERRIDE; diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc index 08dd367..cadcabc 100644 --- a/chrome/browser/chromeos/login/kiosk_browsertest.cc +++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc @@ -12,6 +12,7 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_launch_error.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" +#include "chrome/browser/chromeos/login/app_launch_controller.h" #include "chrome/browser/chromeos/login/existing_user_controller.h" #include "chrome/browser/chromeos/login/login_display_host_impl.h" #include "chrome/browser/chromeos/login/webui_login_display.h" @@ -114,8 +115,6 @@ class KioskAppLaunchScenarioHandler : public TestBrowserMainExtraParts { private: // ChromeBrowserMainExtraParts implementation. virtual void PreEarlyInitialization() OVERRIDE { - registrar_.Add(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, - content::NotificationService::AllSources()); registrar_.Add(this, chrome::NOTIFICATION_KIOSK_APPS_LOADED, content::NotificationService::AllSources()); registrar_.Add(this, chrome::NOTIFICATION_KIOSK_APP_LAUNCHED, @@ -126,10 +125,7 @@ class KioskAppLaunchScenarioHandler : public TestBrowserMainExtraParts { virtual void Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) OVERRIDE { - if (type == chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE) { - LOG(INFO) << "NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE"; - SetupSigninScreen(); - } else if (type == chrome::NOTIFICATION_KIOSK_APPS_LOADED) { + if (type == chrome::NOTIFICATION_KIOSK_APPS_LOADED) { LOG(INFO) << "chrome::NOTIFICATION_KIOSK_APPS_LOADED"; content::WebUI* web_ui = static_cast<chromeos::LoginDisplayHostImpl*>( chromeos::LoginDisplayHostImpl::default_host())-> @@ -544,6 +540,7 @@ class KioskLaunchTest : public KioskTest { IN_PROC_BROWSER_TEST_P(KioskLaunchTest, InstallAndLaunchApp) { EnableConsumerKioskMode(); + chromeos::AppLaunchController::SkipSplashWaitForTesting(); // Start UI, find menu entry for this app and launch it. chromeos::WizardController::SkipPostLoginScreensForTesting(); chromeos::WizardController* wizard_controller = diff --git a/chrome/browser/chromeos/login/login_display.h b/chrome/browser/chromeos/login/login_display.h index 12db78d..763a66e 100644 --- a/chrome/browser/chromeos/login/login_display.h +++ b/chrome/browser/chromeos/login/login_display.h @@ -64,6 +64,9 @@ class LoginDisplay : public RemoveUserDelegate { // Sign in into the public account identified by |username|. virtual void LoginAsPublicAccount(const std::string& username) = 0; + // Login to kiosk mode for app with |app_id|. + virtual void LoginAsKioskApp(const std::string& app_id) = 0; + // Notify the delegate when the sign-in UI is finished loading. virtual void OnSigninScreenReady() = 0; diff --git a/chrome/browser/chromeos/login/login_display_host.h b/chrome/browser/chromeos/login/login_display_host.h index 72b83c5..cb9d6f4 100644 --- a/chrome/browser/chromeos/login/login_display_host.h +++ b/chrome/browser/chromeos/login/login_display_host.h @@ -98,6 +98,9 @@ class LoginDisplayHost { // Initiates authentication network prewarming. virtual void PrewarmAuthentication() = 0; + + // Starts app launch splash screen. + virtual void StartAppLaunch(const std::string& app_id) = 0; }; } // namespace chromeos diff --git a/chrome/browser/chromeos/login/login_display_host_impl.cc b/chrome/browser/chromeos/login/login_display_host_impl.cc index 72cf588..df3c123 100644 --- a/chrome/browser/chromeos/login/login_display_host_impl.cc +++ b/chrome/browser/chromeos/login/login_display_host_impl.cc @@ -23,6 +23,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_shutdown.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/chromeos/customization_document.h" #include "chrome/browser/chromeos/input_method/input_method_util.h" #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h" @@ -85,6 +86,9 @@ const char kOobeURL[] = "chrome://oobe/oobe"; // URL which corresponds to the user adding WebUI. const char kUserAddingURL[] = "chrome://oobe/user-adding"; +// URL which corresponds to the app launch splash WebUI. +const char kAppLaunchSplashURL[] = "chrome://oobe/app-launch-splash"; + // Duration of sign-in transition animation. const int kLoginFadeoutTransitionDurationMs = 700; @@ -509,6 +513,20 @@ void LoginDisplayHostImpl::PrewarmAuthentication() { pointer_factory_.GetWeakPtr())); } +void LoginDisplayHostImpl::StartAppLaunch(const std::string& app_id) { + LOG(WARNING) << "Login WebUI >> start app launch."; + SetStatusAreaVisible(false); + if (!login_window_) + LoadURL(GURL(kAppLaunchSplashURL)); + + login_view_->set_should_emit_login_prompt_visible(false); + + app_launch_controller_.reset(new AppLaunchController( + app_id, this, GetOobeUI())); + + app_launch_controller_->StartAppLaunch(); +} + //////////////////////////////////////////////////////////////////////////////// // LoginDisplayHostImpl, public @@ -875,13 +893,23 @@ void ShowLoginWizard(const std::string& first_screen_name) { LoginState::Get()->SetLoggedInState( LoginState::LOGGED_IN_NONE, LoginState::LOGGED_IN_USER_NONE); } + + LoginDisplayHost* display_host = new LoginDisplayHostImpl(screen_bounds); + + bool show_app_launch_splash_screen = (first_screen_name == + chromeos::WizardController::kAppLaunchSplashScreenName); + + if (show_app_launch_splash_screen) { + const std::string& auto_launch_app_id = + chromeos::KioskAppManager::Get()->GetAutoLaunchApp(); + display_host->StartAppLaunch(auto_launch_app_id); + return; + } + bool show_login_screen = (first_screen_name.empty() && oobe_complete) || first_screen_name == chromeos::WizardController::kLoginScreenName; - chromeos::LoginDisplayHost* display_host = - new chromeos::LoginDisplayHostImpl(screen_bounds); - if (show_login_screen) { // R11 > R12 migration fix. See http://crosbug.com/p/4898. // If user has manually changed locale during R11 OOBE, locale will be set. diff --git a/chrome/browser/chromeos/login/login_display_host_impl.h b/chrome/browser/chromeos/login/login_display_host_impl.h index 8d25d3f..fd1f0ec 100644 --- a/chrome/browser/chromeos/login/login_display_host_impl.h +++ b/chrome/browser/chromeos/login/login_display_host_impl.h @@ -10,6 +10,7 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "chrome/browser/chromeos/login/app_launch_controller.h" #include "chrome/browser/chromeos/login/auth_prewarmer.h" #include "chrome/browser/chromeos/login/existing_user_controller.h" #include "chrome/browser/chromeos/login/login_display.h" @@ -72,6 +73,7 @@ class LoginDisplayHostImpl : public LoginDisplayHost, virtual void ResumeSignInScreen() OVERRIDE; virtual void OnPreferencesChanged() OVERRIDE; virtual void PrewarmAuthentication() OVERRIDE; + virtual void StartAppLaunch(const std::string& app_id) OVERRIDE; // Creates WizardController instance. WizardController* CreateWizardController(); @@ -153,6 +155,9 @@ class LoginDisplayHostImpl : public LoginDisplayHost, // OOBE and some screens (camera, recovery) controller. scoped_ptr<WizardController> wizard_controller_; + // App launch controller. + scoped_ptr<AppLaunchController> app_launch_controller_; + // Client for enterprise auto-enrollment check. scoped_ptr<policy::AutoEnrollmentClient> auto_enrollment_client_; diff --git a/chrome/browser/chromeos/login/mock_login_display_host.h b/chrome/browser/chromeos/login/mock_login_display_host.h index 1a03afb..89ff5a1 100644 --- a/chrome/browser/chromeos/login/mock_login_display_host.h +++ b/chrome/browser/chromeos/login/mock_login_display_host.h @@ -42,6 +42,7 @@ class MockLoginDisplayHost : public LoginDisplayHost { MOCK_METHOD0(ResumeSignInScreen, void(void)); MOCK_METHOD0(OnPreferencesChanged, void(void)); MOCK_METHOD0(PrewarmAuthentication, void(void)); + MOCK_METHOD1(StartAppLaunch, void(const std::string&)); private: DISALLOW_COPY_AND_ASSIGN(MockLoginDisplayHost); diff --git a/chrome/browser/chromeos/login/oobe_display.h b/chrome/browser/chromeos/login/oobe_display.h index b1f5485..c0f7942 100644 --- a/chrome/browser/chromeos/login/oobe_display.h +++ b/chrome/browser/chromeos/login/oobe_display.h @@ -12,6 +12,7 @@ namespace chromeos { +class AppLaunchSplashScreenActor; class EnrollmentScreenActor; class ErrorScreenActor; class EulaScreenActor; @@ -49,6 +50,7 @@ class OobeDisplay { SCREEN_CREATE_MANAGED_USER_FLOW, SCREEN_TERMS_OF_SERVICE, SCREEN_WRONG_HWID, + SCREEN_APP_LAUNCH_SPLASH, SCREEN_UNKNOWN }; @@ -75,6 +77,7 @@ class OobeDisplay { virtual WrongHWIDScreenActor* GetWrongHWIDScreenActor() = 0; virtual LocallyManagedUserCreationScreenHandler* GetLocallyManagedUserCreationScreenActor() = 0; + virtual AppLaunchSplashScreenActor* GetAppLaunchSplashScreenActor() = 0; // Returns if JS side is fully loaded and ready to accept messages. // If |false| is returned, then |display_is_ready_callback| is stored diff --git a/chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h b/chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h new file mode 100644 index 0000000..234ce71 --- /dev/null +++ b/chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h @@ -0,0 +1,54 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_APP_LAUNCH_SPLASH_SCREEN_ACTOR_H_ +#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_APP_LAUNCH_SPLASH_SCREEN_ACTOR_H_ + +#include "base/strings/string16.h" + +namespace chromeos { + +// Interface for UI implemenations of the ApplaunchSplashScreen. +class AppLaunchSplashScreenActor { + public: + enum AppLaunchState { + APP_LAUNCH_STATE_LOADING_AUTH_FILE, + APP_LAUNCH_STATE_LOADING_TOKEN_SERVICE, + APP_LAUNCH_STATE_PREPARING_NETWORK, + APP_LAUNCH_STATE_INSTALLING_APPLICATION, + }; + + class Delegate { + public: + virtual void OnConfigureNetwork() = 0; + virtual void OnCancelAppLaunch() = 0; + + protected: + virtual ~Delegate() {} + }; + + virtual ~AppLaunchSplashScreenActor() {} + + // Sets screen this actor belongs to. + virtual void SetDelegate(Delegate* screen) = 0; + + // Prepare the contents to showing. + virtual void PrepareToShow() = 0; + + // Shows the contents of the screen. + virtual void Show(const std::string& app_id) = 0; + + // Hides the contents of the screen. + virtual void Hide() = 0; + + // Set the current app launch state. + virtual void UpdateAppLaunchState(AppLaunchState state) = 0; + + // Sets whether continue control is enabled. + virtual void ToggleNetworkConfig(bool visible) = 0; +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_APP_LAUNCH_SPLASH_SCREEN_ACTOR_H_ diff --git a/chrome/browser/chromeos/login/webui_login_display.cc b/chrome/browser/chromeos/login/webui_login_display.cc index 48bcbc4..e9a8675 100644 --- a/chrome/browser/chromeos/login/webui_login_display.cc +++ b/chrome/browser/chromeos/login/webui_login_display.cc @@ -364,6 +364,10 @@ void WebUILoginDisplay::Signout() { delegate_->Signout(); } +void WebUILoginDisplay::LoginAsKioskApp(const std::string& app_id) { + delegate_->LoginAsKioskApp(app_id); +} + void WebUILoginDisplay::OnUserActivity(const ui::Event* event) { if (!password_clear_timer_.IsRunning()) StartPasswordClearTimer(); diff --git a/chrome/browser/chromeos/login/webui_login_display.h b/chrome/browser/chromeos/login/webui_login_display.h index f8a0341..db33fdc 100644 --- a/chrome/browser/chromeos/login/webui_login_display.h +++ b/chrome/browser/chromeos/login/webui_login_display.h @@ -84,6 +84,7 @@ class WebUILoginDisplay : public LoginDisplay, virtual bool IsUserSigninCompleted() const OVERRIDE; virtual void SetDisplayEmail(const std::string& email) OVERRIDE; virtual void Signout() OVERRIDE; + virtual void LoginAsKioskApp(const std::string& app_id) OVERRIDE; // UserActivityDetector implementation: virtual void OnUserActivity(const ui::Event* event) OVERRIDE; diff --git a/chrome/browser/chromeos/login/webui_login_view.cc b/chrome/browser/chromeos/login/webui_login_view.cc index 590a943..d3051f7 100644 --- a/chrome/browser/chromeos/login/webui_login_view.cc +++ b/chrome/browser/chromeos/login/webui_login_view.cc @@ -48,7 +48,8 @@ using web_modal::WebContentsModalDialogManager; namespace { -// These strings must be kept in sync with handleAccelerator() in oobe.js. +// These strings must be kept in sync with handleAccelerator() +// in display_manager.js. const char kAccelNameCancel[] = "cancel"; const char kAccelNameEnrollment[] = "enrollment"; const char kAccelNameKioskEnable[] = "kiosk_enable"; @@ -58,6 +59,7 @@ const char kAccelNameLeft[] = "left"; const char kAccelNameRight[] = "right"; const char kAccelNameDeviceRequisition[] = "device_requisition"; const char kAccelNameDeviceRequisitionRemora[] = "device_requisition_remora"; +const char kAccelNameAppLaunchBailout[] = "app_launch_bailout"; // Observes IPC messages from the FrameSniffer and notifies JS if error // appears. @@ -183,6 +185,10 @@ WebUILoginView::WebUILoginView() ui::Accelerator(ui::VKEY_H, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)] = kAccelNameDeviceRequisitionRemora; + accel_map_[ui::Accelerator(ui::VKEY_S, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)] = + kAccelNameAppLaunchBailout; + for (AccelMap::iterator i(accel_map_.begin()); i != accel_map_.end(); ++i) AddAccelerator(i->first); } diff --git a/chrome/browser/chromeos/login/webui_screen_locker.cc b/chrome/browser/chromeos/login/webui_screen_locker.cc index 9c4210f..77b15a0 100644 --- a/chrome/browser/chromeos/login/webui_screen_locker.cc +++ b/chrome/browser/chromeos/login/webui_screen_locker.cc @@ -271,6 +271,10 @@ void WebUIScreenLocker::Signout() { chromeos::ScreenLocker::default_screen_locker()->Signout(); } +void WebUIScreenLocker::LoginAsKioskApp(const std::string& app_id) { + NOTREACHED(); +} + //////////////////////////////////////////////////////////////////////////////// // LockWindow::Observer implementation: diff --git a/chrome/browser/chromeos/login/webui_screen_locker.h b/chrome/browser/chromeos/login/webui_screen_locker.h index 4521525..b8637f9 100644 --- a/chrome/browser/chromeos/login/webui_screen_locker.h +++ b/chrome/browser/chromeos/login/webui_screen_locker.h @@ -89,6 +89,7 @@ class WebUIScreenLocker : public WebUILoginView, virtual void ResyncUserData() OVERRIDE; virtual void SetDisplayEmail(const std::string& email) OVERRIDE; virtual void Signout() OVERRIDE; + virtual void LoginAsKioskApp(const std::string& app_id) OVERRIDE; // content::NotificationObserver (via WebUILoginView) implementation. virtual void Observe(int type, diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index bc83452..ab322607 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc @@ -21,7 +21,7 @@ #include "base/values.h" #include "chrome/app/breakpad_linux.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/chromeos/app_mode/kiosk_app_launcher.h" +#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/chromeos/customization_document.h" #include "chrome/browser/chromeos/login/enrollment/enrollment_screen.h" @@ -122,6 +122,8 @@ const char WizardController::kTermsOfServiceScreenName[] = "tos"; const char WizardController::kWrongHWIDScreenName[] = "wrong-hwid"; const char WizardController::kLocallyManagedUserCreationScreenName[] = "locally-managed-user-creation-flow"; +const char WizardController::kAppLaunchSplashScreenName[] = + "app-launch-splash"; // Passing this parameter as a "first screen" initiates full OOBE flow. const char WizardController::kOutOfBoxScreenName[] = "oobe"; @@ -717,6 +719,8 @@ void WizardController::AdvanceToScreen(const std::string& screen_name) { ShowWrongHWIDScreen(); } else if (screen_name == kLocallyManagedUserCreationScreenName) { ShowLocallyManagedUserCreationScreen(); + } else if (screen_name == kAppLaunchSplashScreenName) { + AutoLaunchKioskApp(); } else if (screen_name != kTestNoScreenName) { if (is_out_of_box_) { ShowNetworkScreen(); @@ -825,11 +829,8 @@ void WizardController::AutoLaunchKioskApp() { KioskAppManager::App app_data; std::string app_id = KioskAppManager::Get()->GetAutoLaunchApp(); CHECK(KioskAppManager::Get()->GetApp(app_id, &app_data)); - if (ExistingUserController::current_controller()) - ExistingUserController::current_controller()->PrepareKioskAppLaunch(); - // KioskAppLauncher deletes itself when done. - (new KioskAppLauncher(KioskAppManager::Get(), app_id))->Start(); + host_->StartAppLaunch(app_id); } // static diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h index 8022003..d4fb70c 100644 --- a/chrome/browser/chromeos/login/wizard_controller.h +++ b/chrome/browser/chromeos/login/wizard_controller.h @@ -145,6 +145,7 @@ class WizardController : public ScreenObserver { static const char kTermsOfServiceScreenName[]; static const char kWrongHWIDScreenName[]; static const char kLocallyManagedUserCreationScreenName[]; + static const char kAppLaunchSplashScreenName[]; private: // Show specific screen. diff --git a/chrome/browser/chromeos/ui/app_launch_view.cc b/chrome/browser/chromeos/ui/app_launch_view.cc deleted file mode 100644 index 9b8da56..0000000 --- a/chrome/browser/chromeos/ui/app_launch_view.cc +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/chromeos/ui/app_launch_view.h" - -#include "ash/shell.h" -#include "ash/shell_delegate.h" -#include "ash/shell_window_ids.h" -#include "base/bind.h" -#include "base/logging.h" -#include "base/values.h" -#include "chrome/browser/ui/webui/chromeos/app_launch_ui.h" -#include "chrome/common/url_constants.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/render_widget_host_view.h" -#include "content/public/browser/web_contents.h" -#include "grit/generated_resources.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/aura/root_window.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/gfx/screen.h" -#include "ui/views/controls/webview/webview.h" -#include "ui/views/layout/fill_layout.h" -#include "ui/views/widget/widget.h" - -using content::BrowserThread; - -namespace chromeos { - -internal::AppLaunchView* g_instance = NULL; - -void ShowAppLaunchSplashScreen(const std::string& app_id) { - // TODO(zelidrag): Come up with a better UI for this purpose. - internal::AppLaunchView::ShowAppLaunchSplashScreen(app_id); -} - -void UpdateAppLaunchSplashScreenState(AppLaunchState state) { - internal::AppLaunchView::UpdateAppLaunchState(state); -} - -void CloseAppLaunchSplashScreen() { - internal::AppLaunchView::CloseAppLaunchSplashScreen(); -} - -namespace internal { - -int GetProgressMessageFromState(AppLaunchState state) { - switch (state) { - case APP_LAUNCH_STATE_LOADING_AUTH_FILE: - case APP_LAUNCH_STATE_LOADING_TOKEN_SERVICE: - // TODO(zelidrag): Add better string for this one than "Please wait..." - return IDS_SYNC_SETUP_SPINNER_TITLE; - case APP_LAUNCH_STATE_PREPARING_NETWORK: - return IDS_APP_START_NETWORK_WAIT_MESSAGE; - case APP_LAUNCH_STATE_INSTALLING_APPLICATION: - return IDS_APP_START_APP_WAIT_MESSAGE; - } - return IDS_APP_START_NETWORK_WAIT_MESSAGE; -} - -// static -void AppLaunchView::ShowAppLaunchSplashScreen(const std::string& app_id) { - if (!g_instance) { - g_instance = new AppLaunchView(app_id); - g_instance->Show(); - } -} - -void AppLaunchView::UpdateAppLaunchState(AppLaunchState state) { - if (g_instance) - g_instance->UpdateState(state); -} - - -// static -void AppLaunchView::CloseAppLaunchSplashScreen() { - if (g_instance) { - g_instance->GetWidget()->Close(); - g_instance = NULL; - } -} - -//////////////////////////////////////////////////////////////////////////////// -// AppLaunchView, views::WidgetDelegateView implementation. -views::View* AppLaunchView::GetContentsView() { - return this; -} - -//////////////////////////////////////////////////////////////////////////////// -// AppLaunchView, content::WebContentsObserver implementation. -void AppLaunchView::RenderProcessGone( - base::TerminationStatus status) { - LOG(ERROR) << "Splash screen terminated with status " << status; - AppLaunchView::CloseAppLaunchSplashScreen(); -} - -//////////////////////////////////////////////////////////////////////////////// -// AppLaunchView private methods. -AppLaunchView::AppLaunchView(const std::string& app_id) - : app_launch_webview_(NULL), - container_window_(NULL), - app_id_(app_id), - state_(APP_LAUNCH_STATE_LOADING_AUTH_FILE), - app_launch_ui_(NULL) { -} - -AppLaunchView::~AppLaunchView() { -} - -void AppLaunchView::Show() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - // Add the WebView to our view. - AddChildWebContents(); - // Initialize container window. - InitializeWindow(); - // Show the window. - ShowWindow(); -} - -void AppLaunchView::AddChildWebContents() { - content::BrowserContext* context = - ash::Shell::GetInstance()->delegate()->GetCurrentBrowserContext(); - app_launch_webview_ = new views::WebView(context); - SetLayoutManager(new views::FillLayout); - AddChildView(app_launch_webview_); - - LoadSplashScreen(); - content::WebContentsObserver::Observe( - app_launch_webview_->GetWebContents()); -} - -void AppLaunchView::UpdateState(AppLaunchState state) { - if (state == state_) - return; - - state_ = state; - if (!app_launch_ui_) - return; - - app_launch_ui_->SetLaunchText( - l10n_util::GetStringUTF8(GetProgressMessageFromState(state_))); -} - -void AppLaunchView::LoadSplashScreen() { - std::string url = chrome::kChromeUIAppLaunchURL; - url += "?app=" + app_id_; - - app_launch_webview_->GetWebContents()->GetController().LoadURL( - GURL(url), - content::Referrer(), - content::PAGE_TRANSITION_AUTO_TOPLEVEL, - std::string()); - - app_launch_ui_ = static_cast<AppLaunchUI*>( - app_launch_webview_->GetWebContents()->GetWebUI()->GetController()); - - // Use a background with transparency to trigger transparency in Webkit. - SkBitmap background; - background.setConfig(SkBitmap::kARGB_8888_Config, 1, 1); - background.allocPixels(); - background.eraseARGB(0x00, 0x00, 0x00, 0x00); - content::RenderViewHost* host = - app_launch_webview_->GetWebContents()->GetRenderViewHost(); - host->GetView()->SetBackground(background); -} - -void AppLaunchView::InitializeWindow() { - DCHECK(!container_window_); - aura::RootWindow* root_window = ash::Shell::GetPrimaryRootWindow(); - - // We want to be the fullscreen topmost child of the root window. - // There should be nothing ever really that should show up on top of us. - container_window_ = new views::Widget(); - views::Widget::InitParams params( - views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - params.delegate = this; - params.parent = ash::Shell::GetContainer( - root_window, - ash::internal::kShellWindowId_LockScreenContainer); - params.show_state = ui::SHOW_STATE_FULLSCREEN; - container_window_->Init(params); -} - -void AppLaunchView::ShowWindow() { - DCHECK(container_window_); - container_window_->Show(); -} - -} // namespace internal - -} // namespace chromeos diff --git a/chrome/browser/chromeos/ui/app_launch_view.h b/chrome/browser/chromeos/ui/app_launch_view.h deleted file mode 100644 index f4c4382..0000000 --- a/chrome/browser/chromeos/ui/app_launch_view.h +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_CHROMEOS_UI_APP_LAUNCH_VIEW_H_ -#define CHROME_BROWSER_CHROMEOS_UI_APP_LAUNCH_VIEW_H_ - -#include <string> - -#include "ash/ash_export.h" -#include "base/callback.h" -#include "content/public/browser/web_contents_observer.h" -#include "ui/views/widget/widget_delegate.h" -#include "url/gurl.h" - -namespace content { -class BrowserContent; -} - -namespace views { -class WebView; -} - -namespace chromeos { - -class AppLaunchUI; - -enum AppLaunchState { - APP_LAUNCH_STATE_LOADING_AUTH_FILE, - APP_LAUNCH_STATE_LOADING_TOKEN_SERVICE, - APP_LAUNCH_STATE_PREPARING_NETWORK, - APP_LAUNCH_STATE_INSTALLING_APPLICATION, -}; - -void ShowAppLaunchSplashScreen(const std::string& app_id); -void CloseAppLaunchSplashScreen(); -void UpdateAppLaunchSplashScreenState(AppLaunchState state); - -namespace internal { - -// Shows application launch/install splash screen in exclusive app mode (kiosk). -class AppLaunchView : public views::WidgetDelegateView, - public content::WebContentsObserver { - public: - static void ShowAppLaunchSplashScreen(const std::string& app_id); - static void CloseAppLaunchSplashScreen(); - static void UpdateAppLaunchState(AppLaunchState state); - - private: - explicit AppLaunchView(const std::string& app_id); - virtual ~AppLaunchView(); - - // views::WidgetDelegate overrides. - virtual views::View* GetContentsView() OVERRIDE; - - // content::WebContentsObserver overrides. - virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE; - - void Show(); - - // Updates UI state of the app launch splash screen. - void UpdateState(AppLaunchState state); - - // Creates and adds web contents to our view. - void AddChildWebContents(); - - // Loads the splash screen in the WebView's webcontent. If the webcontents - // don't exist, they'll be created by WebView. - void LoadSplashScreen(); - - // Initializes container window. - void InitializeWindow(); - - // Creates and shows a frameless full screen window containing our view. - void ShowWindow(); - - // Host for the extension that implements this dialog. - views::WebView* app_launch_webview_; - - // Window that holds the webview. - views::Widget* container_window_; - - const std::string app_id_; - - // Launch state. - AppLaunchState state_; - - AppLaunchUI* app_launch_ui_; // Not owned. - - DISALLOW_COPY_AND_ASSIGN(AppLaunchView); -}; - -} // namespace internal - -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_UI_APP_LAUNCH_VIEW_H_ diff --git a/chrome/browser/resources/chromeos/app_launch/app_launch.html b/chrome/browser/resources/chromeos/app_launch/app_launch.html deleted file mode 100644 index d2c37f8..0000000 --- a/chrome/browser/resources/chromeos/app_launch/app_launch.html +++ /dev/null @@ -1,23 +0,0 @@ -<!DOCTYPE HTML> -<html i18n-values="dir:textdirection"> -<head> -<link rel="stylesheet" href="chrome://resources/css/spinner.css"> -<link rel="stylesheet" href="chrome://resources/css/chrome_shared.css"> -<link rel="stylesheet" href="app_launch.css"> -<script src="chrome://resources/js/util.js"></script> -<script src="chrome://resources/js/load_time_data.js"></script> -<script src="chrome://app-launch/app_launch.js"></script> -<script src="chrome://app-launch/strings.js"></script> -</head> -<body i18n-values=".style.fontFamily:fontfamily;"> - <div id="page"> - <div id="content"> - <div id="header" i18n-content="productName"></div> - <div id="launch-text" i18n-content="appStartMessage"></div> - <div id="spinner" class="spinner"></div> - </div> - <p id="shortcut-info" i18n-content="shortcutInfo"></p> - </div> - <script src="chrome://resources/js/i18n_template2.js"></script> -</body> -</html> diff --git a/chrome/browser/resources/chromeos/app_launch/app_launch.js b/chrome/browser/resources/chromeos/app_launch/app_launch.js deleted file mode 100644 index a2a3fe2..0000000 --- a/chrome/browser/resources/chromeos/app_launch/app_launch.js +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview App install/launch splash screen. - */ - -/** - * Initializes the click handler. - */ -initialize = function() { - var params = parseQueryParams(window.location); - var appId = params['app'] || ''; - - chrome.send('initialize', [appId]); - - $('shortcut-info').hidden = !loadTimeData.getBoolean('shortcutEnabled'); - $('page').style.opacity = 1; - window.webkitRequestAnimationFrame(function() {}); -}; - -updateApp = function(app) { - $('header').textContent = app.name; - $('header').style.backgroundImage = 'url(' + app.iconURL + ')'; -}; - -updateMessage = function(message) { - $('launch-text').textContent = message; -}; - -disableTextSelectAndDrag(); -document.addEventListener('DOMContentLoaded', initialize); diff --git a/chrome/browser/resources/chromeos/login/display_manager.js b/chrome/browser/resources/chromeos/login/display_manager.js index 638cc5c..d650aa3 100644 --- a/chrome/browser/resources/chromeos/login/display_manager.js +++ b/chrome/browser/resources/chromeos/login/display_manager.js @@ -20,6 +20,7 @@ /** @const */ var SCREEN_PASSWORD_CHANGED = 'password-changed'; /** @const */ var SCREEN_CREATE_MANAGED_USER_FLOW = 'managed-user-creation'; +/** @const */ var SCREEN_APP_LAUNCH_SPLASH = 'app-launch-splash'; /* Accelerator identifiers. Must be kept in sync with webui_login_view.cc. */ /** @const */ var ACCELERATOR_CANCEL = 'cancel'; @@ -32,6 +33,7 @@ /** @const */ var ACCELERATOR_DEVICE_REQUISITION = 'device_requisition'; /** @const */ var ACCELERATOR_DEVICE_REQUISITION_REMORA = 'device_requisition_remora'; +/** @const */ var ACCELERATOR_APP_LAUNCH_BAILOUT = 'app_launch_bailout'; /* Help topic identifiers. */ /** @const */ var HELP_TOPIC_ENTERPRISE_REPORTING = 2535613; @@ -59,7 +61,8 @@ OOBE: 'oobe', LOGIN: 'login', LOCK: 'lock', - USER_ADDING: 'user-adding' + USER_ADDING: 'user-adding', + APP_LAUNCH_SPLASH: 'app-launch-splash' }; cr.define('cr.ui.login', function() { @@ -235,6 +238,10 @@ cr.define('cr.ui.login', function() { this.deviceRequisition_ = 'remora'; this.showDeviceRequisitionPrompt_(); } + } else if (name == ACCELERATOR_APP_LAUNCH_BAILOUT) { + var currentStepId = this.screens_[this.currentStep_]; + if (currentStepId == SCREEN_APP_LAUNCH_SPLASH) + chrome.send('cancelAppLaunch'); } if (!this.forceKeyboardFlow_) @@ -487,9 +494,14 @@ cr.define('cr.ui.login', function() { // Have to reset any previously predefined screen size first // so that screen contents would define it instead (offsetHeight/width). // http://crbug.com/146539 + $('inner-container').style.height = ''; + $('inner-container').style.width = ''; screen.style.width = ''; screen.style.height = ''; + $('outer-container').classList.toggle( + 'fullscreen', screen.classList.contains('fullscreen')); + var height = screen.offsetHeight; var width = screen.offsetWidth; for (var i = 0, screenGroup; screenGroup = SCREEN_GROUPS[i]; i++) { diff --git a/chrome/browser/resources/chromeos/login/login.js b/chrome/browser/resources/chromeos/login/login.js index 65c7fe5..36a2fba 100644 --- a/chrome/browser/resources/chromeos/login/login.js +++ b/chrome/browser/resources/chromeos/login/login.js @@ -28,6 +28,7 @@ cr.define('cr.ui.Oobe', function() { login.PasswordChangedScreen.register(); login.LocallyManagedUserCreationScreen.register(); login.TermsOfServiceScreen.register(); + login.AppLaunchSplashScreen.register(); cr.ui.Bubble.decorate($('bubble')); login.HeaderBar.decorate($('login-header-bar')); diff --git a/chrome/browser/resources/chromeos/login/login_common.js b/chrome/browser/resources/chromeos/login/login_common.js index 55f831f..386438b 100644 --- a/chrome/browser/resources/chromeos/login/login_common.js +++ b/chrome/browser/resources/chromeos/login/login_common.js @@ -19,6 +19,7 @@ <include src="oobe_screen_terms_of_service.js"></include> <include src="oobe_screen_user_image.js"></include> <include src="screen_account_picker.js"></include> +<include src="screen_app_launch_splash.js"></include> <include src="screen_error_message.js"></include> <include src="screen_gaia_signin.js"></include> <include src="screen_locally_managed_user_creation.js"></include> diff --git a/chrome/browser/resources/chromeos/login/login_resources.html b/chrome/browser/resources/chromeos/login/login_resources.html index bbff064..6f4395b 100644 --- a/chrome/browser/resources/chromeos/login/login_resources.html +++ b/chrome/browser/resources/chromeos/login/login_resources.html @@ -20,6 +20,7 @@ <link rel="stylesheet" href="oobe_screen_terms_of_service.css"> <link rel="stylesheet" href="oobe_screen_update.css"> <link rel="stylesheet" href="oobe_screen_user_image.css"> +<link rel="stylesheet" href="screen_app_launch_splash.css"> <link rel="stylesheet" href="screen_container.css"> <link rel="stylesheet" href="screen_account_picker.css"> <link rel="stylesheet" href="screen_gaia_signin.css"> diff --git a/chrome/browser/resources/chromeos/login/login_screens.html b/chrome/browser/resources/chromeos/login/login_screens.html index 481b039..6e13b61 100644 --- a/chrome/browser/resources/chromeos/login/login_screens.html +++ b/chrome/browser/resources/chromeos/login/login_screens.html @@ -10,3 +10,4 @@ <include src="screen_password_changed.html"> <include src="screen_tpm_error.html"> <include src="screen_wrong_hwid.html"> +<include src="screen_app_launch_splash.html"> diff --git a/chrome/browser/resources/chromeos/login/oobe.js b/chrome/browser/resources/chromeos/login/oobe.js index 7ad87e6..8af44f0 100644 --- a/chrome/browser/resources/chromeos/login/oobe.js +++ b/chrome/browser/resources/chromeos/login/oobe.js @@ -68,6 +68,7 @@ cr.define('cr.ui.Oobe', function() { login.PasswordChangedScreen.register(); login.LocallyManagedUserCreationScreen.register(); login.TermsOfServiceScreen.register(); + login.AppLaunchSplashScreen.register(); cr.ui.Bubble.decorate($('bubble')); login.HeaderBar.decorate($('login-header-bar')); diff --git a/chrome/browser/resources/chromeos/login/oobe_screen.css b/chrome/browser/resources/chromeos/login/oobe_screen.css index 0872b5c..a06f8de 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen.css +++ b/chrome/browser/resources/chromeos/login/oobe_screen.css @@ -34,6 +34,14 @@ -webkit-transform: translateX(-50px) } +.step.fullscreen { + height: 100%; + left: 0; + right: 0; + top: 0; + width: 100%; +} + .step-controls { -webkit-box-pack: end; -webkit-padding-end: 34px; /* Double the padding of .step */ diff --git a/chrome/browser/resources/chromeos/login/oobe_screens.html b/chrome/browser/resources/chromeos/login/oobe_screens.html index 51845fa..f189bf6 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screens.html +++ b/chrome/browser/resources/chromeos/login/oobe_screens.html @@ -13,3 +13,4 @@ <include src="screen_password_changed.html"> <include src="screen_tpm_error.html"> <include src="screen_wrong_hwid.html"> +<include src="screen_app_launch_splash.html"> diff --git a/chrome/browser/resources/chromeos/app_launch/app_launch.css b/chrome/browser/resources/chromeos/login/screen_app_launch_splash.css index 92a6b0d..535dc08 100644 --- a/chrome/browser/resources/chromeos/app_launch/app_launch.css +++ b/chrome/browser/resources/chromeos/login/screen_app_launch_splash.css @@ -1,31 +1,16 @@ -/* Copyright (c) 2013 The Chromium Authors. All rights reserved. +/* Copyright 2013 The Chromium Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -html, -body { - height: 100%; - margin: 0; - overflow: hidden; - padding: 0; - width: 100%; -} - -#page { +#app-launch-splash { -webkit-box-align: center; -webkit-box-pack: center; - /* Delay the login screen for 2 seconds then fade it in. */ - -webkit-transition: opacity 1s; background: white; display: -webkit-box; - height: 100%; - opacity: 0; - position: absolute; - width: 100%; } -#content { +#splash-content { -webkit-box-align: center; -webkit-box-orient: vertical; -webkit-box-pack: center; @@ -33,7 +18,7 @@ body { position: relative; } -#header { +#splash-header { -webkit-padding-start: 108px; background: left center no-repeat; background-size: 96px; @@ -44,19 +29,19 @@ body { line-height: 96px; } -#launch-text { +#splash-launch-text { color: #666; font-size: 18px; padding-bottom: 50px; padding-top: 50px; } -#spinner { +#splash-spinner { height: 32px; width: 32px; } -#shortcut-info { +#splash-shortcut-info { bottom: 50px; color: gray; left: 0; diff --git a/chrome/browser/resources/chromeos/login/screen_app_launch_splash.html b/chrome/browser/resources/chromeos/login/screen_app_launch_splash.html new file mode 100644 index 0000000..634301d --- /dev/null +++ b/chrome/browser/resources/chromeos/login/screen_app_launch_splash.html @@ -0,0 +1,8 @@ +<div id="app-launch-splash" class="step hidden step-no-logo fullscreen"> + <div id="splash-content"> + <div id="splash-header" i18n-content="productName"></div> + <div id="splash-launch-text" i18n-content="appStartMessage"></div> + <div id="splash-spinner" class="spinner"></div> + </div> + <p id="splash-shortcut-info" i18n-content="shortcutInfo"></p> +</div> diff --git a/chrome/browser/resources/chromeos/login/screen_app_launch_splash.js b/chrome/browser/resources/chromeos/login/screen_app_launch_splash.js new file mode 100644 index 0000000..dfe4c2e --- /dev/null +++ b/chrome/browser/resources/chromeos/login/screen_app_launch_splash.js @@ -0,0 +1,60 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview App install/launch splash screen implementation. + */ + +login.createScreen('AppLaunchSplashScreen', 'app-launch-splash', function() { + return { + EXTERNAL_API: [ + 'toggleNetworkConfig', + 'updateApp', + 'updateMessage', + ], + + /** + * Event handler that is invoked just before the frame is shown. + * @param {string} data Screen init payload. + */ + onBeforeShow: function(data) { + this.updateApp(data['appInfo']); + + $('splash-shortcut-info').hidden = !data['shortcutEnabled']; + + Oobe.getInstance().headerHidden = true; + }, + + /** + * Event handler that is invoked just before the frame is hidden. + */ + onBeforeHide: function() { + }, + + /** + * Toggles visibility of the network configuration option. + * @param {boolean} visible Whether to show the option. + */ + toggleNetworkConfig: function(visible) { + // TODO(tengs): Implement network configuration in app launch. + }, + + /** + * Updates the app name and icon. + * @param {Object} app Details of app being launched. + */ + updateApp: function(app) { + $('splash-header').textContent = app.name; + $('splash-header').style.backgroundImage = 'url(' + app.iconURL + ')'; + }, + + /** + * Updates the message for the current launch state. + * @param {string} message Description for current launch state. + */ + updateMessage: function(message) { + $('splash-launch-text').textContent = message; + } + }; +}); diff --git a/chrome/browser/resources/chromeos/login/screen_container.css b/chrome/browser/resources/chromeos/login/screen_container.css index 33f93a3..5461961 100644 --- a/chrome/browser/resources/chromeos/login/screen_container.css +++ b/chrome/browser/resources/chromeos/login/screen_container.css @@ -134,6 +134,13 @@ body:not(.oobe-display) #progress-dots { display: none; } +#outer-container.fullscreen, +#outer-container.fullscreen #oobe, +#outer-container.fullscreen #oobe #inner-container { + height: 100%; + width: 100%; +} + html[build=chrome] #header-sections { -webkit-margin-start: -48px; } diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc index 513d982..a5226e7 100644 --- a/chrome/browser/ui/startup/startup_browser_creator.cc +++ b/chrome/browser/ui/startup/startup_browser_creator.cc @@ -65,7 +65,7 @@ #include "ui/base/resource/resource_bundle.h" #if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/app_mode/startup_app_launcher.h" +#include "chrome/browser/chromeos/app_mode/app_launch_utils.h" #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" @@ -595,10 +595,9 @@ bool StartupBrowserCreator::ProcessCmdLineImpl( if (chrome::IsRunningInAppMode() && command_line.HasSwitch(switches::kAppId)) { - // StartupAppLauncher deletes itself when done. - (new chromeos::StartupAppLauncher( + chromeos::LaunchAppOrDie( last_used_profile, - command_line.GetSwitchValueASCII(switches::kAppId)))->Start(); + command_line.GetSwitchValueASCII(switches::kAppId)); // Skip browser launch since app mode launches its app window. silent_launch = true; diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index dc367c5..f097d81 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc @@ -92,7 +92,6 @@ #endif #if defined(OS_CHROMEOS) -#include "chrome/browser/ui/webui/chromeos/app_launch_ui.h" #include "chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui.h" #include "chrome/browser/ui/webui/chromeos/choose_mobile_network_ui.h" #include "chrome/browser/ui/webui/chromeos/cryptohome_ui.h" @@ -348,8 +347,6 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, return &NewWebUI<CertificateViewerUI>; #endif #if defined(OS_CHROMEOS) - if (url.host() == chrome::kChromeUIAppLaunchHost) - return &NewWebUI<chromeos::AppLaunchUI>; if (url.host() == chrome::kChromeUIBluetoothPairingHost) return &NewWebUI<chromeos::BluetoothPairingUI>; if (url.host() == chrome::kChromeUIChooseMobileNetworkHost) diff --git a/chrome/browser/ui/webui/chromeos/app_launch_ui.cc b/chrome/browser/ui/webui/chromeos/app_launch_ui.cc deleted file mode 100644 index 587ac63..0000000 --- a/chrome/browser/ui/webui/chromeos/app_launch_ui.cc +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/webui/chromeos/app_launch_ui.h" - -#include "base/values.h" -#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/theme_source.h" -#include "chrome/common/url_constants.h" -#include "content/public/browser/web_ui.h" -#include "content/public/browser/web_ui_data_source.h" -#include "content/public/browser/web_ui_message_handler.h" -#include "grit/browser_resources.h" -#include "grit/chrome_unscaled_resources.h" -#include "grit/chromium_strings.h" -#include "grit/generated_resources.h" -#include "net/base/network_change_notifier.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/webui/web_ui_util.h" - -namespace chromeos { - -namespace { - -content::WebUIDataSource* CreateWebUIDataSource() { - content::WebUIDataSource* source = - content::WebUIDataSource::Create(chrome::kChromeUIAppLaunchHost); - source->SetDefaultResource(IDR_APP_LAUNCH_SPLASH_HTML); - source->SetUseJsonJSFormatV2(); - source->AddLocalizedString("appStartMessage", - net::NetworkChangeNotifier::IsOffline() ? - IDS_APP_START_NETWORK_WAIT_MESSAGE : - IDS_APP_START_APP_WAIT_MESSAGE); - source->AddLocalizedString("productName", IDS_SHORT_PRODUCT_NAME); - - const string16 product_os_name = - l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_OS_NAME); - source->AddString( - "shortcutInfo", - l10n_util::GetStringFUTF16(IDS_APP_START_BAILOUT_SHORTCUT_FORMAT, - product_os_name)); - - source->AddBoolean("shortcutEnabled", - !KioskAppManager::Get()->GetDisableBailoutShortcut()); - - source->SetJsonPath("strings.js"); - source->AddResourcePath("app_launch.js", IDR_APP_LAUNCH_SPLASH_JS); - return source; -} - -} // namespace - -class AppLaunchUI::AppLaunchUIHandler : public content::WebUIMessageHandler { - public: - AppLaunchUIHandler() : initialized_(false) {} - virtual ~AppLaunchUIHandler() {} - - void SetLaunchText(const std::string& text) { - text_ = text; - if (initialized_) - SendLaunchText(); - } - - // content::WebUIMessageHandler overrides: - virtual void RegisterMessages() OVERRIDE { - web_ui()->RegisterMessageCallback("initialize", - base::Bind(&AppLaunchUIHandler::HandleInitialize, - base::Unretained(this))); - } - - private: - void SendAppInfo(const std::string& app_id) { - KioskAppManager::App app; - KioskAppManager::Get()->GetApp(app_id, &app); - - if (app.name.empty()) - app.name = l10n_util::GetStringUTF8(IDS_SHORT_PRODUCT_NAME); - - if (app.icon.isNull()) { - app.icon = *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( - IDR_PRODUCT_LOGO_128); - } - - base::DictionaryValue app_info; - app_info.SetString("name", app.name); - app_info.SetString("iconURL", webui::GetBitmapDataUrl(*app.icon.bitmap())); - - web_ui()->CallJavascriptFunction("updateApp", app_info); - } - - void SendLaunchText() { - web_ui()->CallJavascriptFunction("updateMessage", base::StringValue(text_)); - } - - // JS callbacks. - void HandleInitialize(const base::ListValue* args) { - initialized_ = true; - - std::string app_id; - if (args->GetString(0, &app_id) && !app_id.empty()) - SendAppInfo(app_id); - - SendLaunchText(); - } - - bool initialized_; - std::string text_; - - DISALLOW_COPY_AND_ASSIGN(AppLaunchUIHandler); -}; - -AppLaunchUI::AppLaunchUI(content::WebUI* web_ui) - : WebUIController(web_ui), - handler_(NULL) { - Profile* profile = Profile::FromWebUI(web_ui); - content::WebUIDataSource::Add(profile, CreateWebUIDataSource()); - - handler_ = new AppLaunchUIHandler; - web_ui->AddMessageHandler(handler_); -} - -void AppLaunchUI::SetLaunchText(const std::string& text) { - handler_->SetLaunchText(text); -} - -} // namespace chromeos diff --git a/chrome/browser/ui/webui/chromeos/app_launch_ui.h b/chrome/browser/ui/webui/chromeos/app_launch_ui.h deleted file mode 100644 index e969c7a7..0000000 --- a/chrome/browser/ui/webui/chromeos/app_launch_ui.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_APP_LAUNCH_UI_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_APP_LAUNCH_UI_H_ - -#include <string> - -#include "content/public/browser/web_ui_controller.h" - -namespace chromeos { - -// A custom WebUI that shows app install/launch splash screen in ChromeOS -// app mode (aka Kiosk). -class AppLaunchUI : public content::WebUIController { - public: - explicit AppLaunchUI(content::WebUI* web_ui); - - void SetLaunchText(const std::string& text); - - private: - class AppLaunchUIHandler; - - AppLaunchUIHandler* handler_; // Owned by WebUI. - - DISALLOW_COPY_AND_ASSIGN(AppLaunchUI); -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_APP_LAUNCH_UI_H_ diff --git a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc new file mode 100644 index 0000000..00646a8 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc @@ -0,0 +1,162 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h" + +#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" +#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" +#include "grit/browser_resources.h" +#include "grit/chrome_unscaled_resources.h" +#include "grit/chromium_strings.h" +#include "grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/webui/web_ui_util.h" + +namespace { + +const char kJsScreenPath[] = "login.AppLaunchSplashScreen"; + +} // namespace + +namespace chromeos { + +AppLaunchSplashScreenHandler::AppLaunchSplashScreenHandler() + : BaseScreenHandler(kJsScreenPath), + delegate_(NULL), + show_on_init_(false), + state_(APP_LAUNCH_STATE_LOADING_AUTH_FILE) { +} + +AppLaunchSplashScreenHandler::~AppLaunchSplashScreenHandler() { +} + +void AppLaunchSplashScreenHandler::DeclareLocalizedValues( + LocalizedValuesBuilder* builder) { + + builder->Add("appStartMessage", IDS_APP_START_NETWORK_WAIT_MESSAGE); + + const string16 product_os_name = + l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_OS_NAME); + builder->Add( + "shortcutInfo", + l10n_util::GetStringFUTF16(IDS_APP_START_BAILOUT_SHORTCUT_FORMAT, + product_os_name)); + + builder->Add( + "productName", + l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_OS_NAME)); +} + +void AppLaunchSplashScreenHandler::Initialize() { + if (show_on_init_) { + show_on_init_ = false; + Show(app_id_); + } +} + +void AppLaunchSplashScreenHandler::Show(const std::string& app_id) { + app_id_ = app_id; + if (!page_is_ready()) { + show_on_init_ = true; + return; + } + + base::DictionaryValue data; + data.SetBoolean("shortcutEnabled", + !KioskAppManager::Get()->GetDisableBailoutShortcut()); + + // |data| will take ownership of |app_info|. + base::DictionaryValue *app_info = new base::DictionaryValue(); + PopulateAppInfo(app_info); + data.Set("appInfo", app_info); + + SetLaunchText(l10n_util::GetStringUTF8(GetProgressMessageFromState(state_))); + ShowScreen(OobeUI::kScreenAppLaunchSplash, &data); +} + +void AppLaunchSplashScreenHandler::RegisterMessages() { + AddCallback("configureNetwork", + &AppLaunchSplashScreenHandler::HandleConfigureNetwork); + AddCallback("cancelAppLaunch", + &AppLaunchSplashScreenHandler::HandleCancelAppLaunch); +} + +void AppLaunchSplashScreenHandler::PrepareToShow() { +} + +void AppLaunchSplashScreenHandler::Hide() { +} + +void AppLaunchSplashScreenHandler::ToggleNetworkConfig(bool visible) { + // TODO(tengs): Implement network configuration in app launch. +} + +void AppLaunchSplashScreenHandler::UpdateAppLaunchState(AppLaunchState state) { + if (state == state_) + return; + + state_ = state; + if (page_is_ready()) { + SetLaunchText( + l10n_util::GetStringUTF8(GetProgressMessageFromState(state_))); + } +} + +void AppLaunchSplashScreenHandler::SetDelegate( + AppLaunchSplashScreenHandler::Delegate* delegate) { + delegate_ = delegate; +} + +void AppLaunchSplashScreenHandler::PopulateAppInfo( + base::DictionaryValue* out_info) { + KioskAppManager::App app; + KioskAppManager::Get()->GetApp(app_id_, &app); + + if (app.name.empty()) + app.name = l10n_util::GetStringUTF8(IDS_SHORT_PRODUCT_NAME); + + if (app.icon.isNull()) { + app.icon = *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( + IDR_PRODUCT_LOGO_128); + } + + out_info->SetString("name", app.name); + out_info->SetString("iconURL", webui::GetBitmapDataUrl(*app.icon.bitmap())); +} + +void AppLaunchSplashScreenHandler::SetLaunchText(const std::string& text) { + CallJS("updateMessage", text); +} + +int AppLaunchSplashScreenHandler::GetProgressMessageFromState( + AppLaunchState state) { + switch (state) { + case APP_LAUNCH_STATE_LOADING_AUTH_FILE: + case APP_LAUNCH_STATE_LOADING_TOKEN_SERVICE: + // TODO(zelidrag): Add better string for this one than "Please wait..." + return IDS_SYNC_SETUP_SPINNER_TITLE; + case APP_LAUNCH_STATE_PREPARING_NETWORK: + return IDS_APP_START_NETWORK_WAIT_MESSAGE; + case APP_LAUNCH_STATE_INSTALLING_APPLICATION: + return IDS_APP_START_APP_WAIT_MESSAGE; + } + return IDS_APP_START_NETWORK_WAIT_MESSAGE; +} + +void AppLaunchSplashScreenHandler::HandleConfigureNetwork() { + if (delegate_) + delegate_->OnConfigureNetwork(); + else + LOG(WARNING) << "No delegate set to handle network configuration."; +} + +void AppLaunchSplashScreenHandler::HandleCancelAppLaunch() { + if (delegate_) + delegate_->OnCancelAppLaunch(); + else + LOG(WARNING) << "No delegate set to handle cancel app launch"; +} + +} // namespace chromeos diff --git a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h new file mode 100644 index 0000000..72cc4b7 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h @@ -0,0 +1,56 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_APP_LAUNCH_SPLASH_SCREEN_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_APP_LAUNCH_SPLASH_SCREEN_HANDLER_H_ + +#include <set> +#include <string> + +#include "chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h" +#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h" + +namespace chromeos { + +// A class that handles the WebUI hooks for the app launch splash screen. +class AppLaunchSplashScreenHandler : public BaseScreenHandler, + public AppLaunchSplashScreenActor { + public: + AppLaunchSplashScreenHandler(); + virtual ~AppLaunchSplashScreenHandler(); + + // BaseScreenHandler implementation: + virtual void DeclareLocalizedValues(LocalizedValuesBuilder* builder) OVERRIDE; + virtual void Initialize() OVERRIDE; + + // WebUIMessageHandler implementation: + virtual void RegisterMessages() OVERRIDE; + + // AppLaunchSplashScreenActor implementation: + virtual void Show(const std::string& app_id) OVERRIDE; + virtual void PrepareToShow() OVERRIDE; + virtual void Hide() OVERRIDE; + virtual void ToggleNetworkConfig(bool visible) OVERRIDE; + virtual void UpdateAppLaunchState(AppLaunchState state) OVERRIDE; + virtual void SetDelegate( + AppLaunchSplashScreenHandler::Delegate* delegate) OVERRIDE; + + private: + void PopulateAppInfo(base::DictionaryValue* out_info); + void SetLaunchText(const std::string& text); + int GetProgressMessageFromState(AppLaunchState state); + void HandleConfigureNetwork(); + void HandleCancelAppLaunch(); + + AppLaunchSplashScreenHandler::Delegate* delegate_; + bool show_on_init_; + std::string app_id_; + AppLaunchState state_; + + DISALLOW_COPY_AND_ASSIGN(AppLaunchSplashScreenHandler); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_APP_LAUNCH_SPLASH_SCREEN_HANDLER_H_ diff --git a/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc b/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc index 7cfea29..bded6ac 100644 --- a/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc @@ -10,7 +10,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_launch_error.h" -#include "chrome/browser/chromeos/app_mode/kiosk_app_launcher.h" #include "chrome/browser/chromeos/login/existing_user_controller.h" #include "chrome/browser/policy/browser_policy_connector.h" #include "chromeos/chromeos_switches.h" @@ -47,9 +46,6 @@ void KioskAppMenuHandler::RegisterMessages() { web_ui()->RegisterMessageCallback("kioskAppsLoaded", base::Bind(&KioskAppMenuHandler::HandleKioskAppsLoaded, base::Unretained(this))); - web_ui()->RegisterMessageCallback("launchKioskApp", - base::Bind(&KioskAppMenuHandler::HandleLaunchKioskApps, - base::Unretained(this))); web_ui()->RegisterMessageCallback("checkKioskAppLaunchError", base::Bind(&KioskAppMenuHandler::HandleCheckKioskAppLaunchError, base::Unretained(this))); @@ -111,19 +107,6 @@ void KioskAppMenuHandler::HandleKioskAppsLoaded( content::NotificationService::NoDetails()); } -void KioskAppMenuHandler::HandleLaunchKioskApps(const base::ListValue* args) { - std::string app_id; - CHECK(args->GetString(0, &app_id)); - - KioskAppManager::App app_data; - CHECK(KioskAppManager::Get()->GetApp(app_id, &app_data)); - - ExistingUserController::current_controller()->PrepareKioskAppLaunch(); - - // KioskAppLauncher deletes itself when done. - (new KioskAppLauncher(KioskAppManager::Get(), app_id))->Start(); -} - void KioskAppMenuHandler::HandleCheckKioskAppLaunchError( const base::ListValue* args) { KioskAppLaunchError::Error error = KioskAppLaunchError::Get(); diff --git a/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.h b/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.h index 9da4f99..3646058 100644 --- a/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.h @@ -37,7 +37,6 @@ class KioskAppMenuHandler : public content::WebUIMessageHandler, // JS callbacks. void HandleInitializeKioskApps(const base::ListValue* args); void HandleKioskAppsLoaded(const base::ListValue* args); - void HandleLaunchKioskApps(const base::ListValue* args); void HandleCheckKioskAppLaunchError(const base::ListValue* args); // KioskAppManagerObserver overrides: diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc index eabd42f..57a46e7 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc +++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc @@ -19,6 +19,7 @@ #include "chrome/browser/chromeos/system/input_device_settings.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/about_ui.h" +#include "chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h" @@ -58,12 +59,14 @@ const char kOobeDisplay[] = "oobe"; const char kLoginDisplay[] = "login"; const char kLockDisplay[] = "lock"; const char kUserAddingDisplay[] = "user-adding"; +const char kAppLaunchSplashDisplay[] = "app-launch-splash"; const char* kKnownDisplayTypes[] = { kOobeDisplay, kLoginDisplay, kLockDisplay, - kUserAddingDisplay + kUserAddingDisplay, + kAppLaunchSplashDisplay }; const char kStringsJSPath[] = "strings.js"; @@ -158,6 +161,7 @@ const char OobeUI::kScreenManagedUserCreationFlow[] = "managed-user-creation"; const char OobeUI::kScreenTermsOfService[] = "terms-of-service"; const char OobeUI::kScreenWrongHWID[] = "wrong-hwid"; +const char OobeUI::kScreenAppLaunchSplash[] = "app-launch-splash"; OobeUI::OobeUI(content::WebUI* web_ui, const GURL& url) : WebUIController(web_ui), @@ -255,6 +259,11 @@ OobeUI::OobeUI(content::WebUI* web_ui, const GURL& url) core_handler_); AddScreenHandler(signin_screen_handler_); + AppLaunchSplashScreenHandler* app_launch_splash_screen_handler = + new AppLaunchSplashScreenHandler(); + AddScreenHandler(app_launch_splash_screen_handler); + app_launch_splash_screen_actor_ = app_launch_splash_screen_handler; + // Initialize KioskAppMenuHandler. Note that it is NOT a screen handler. kiosk_app_menu_handler_ = new KioskAppMenuHandler; web_ui->AddMessageHandler(kiosk_app_menu_handler_); @@ -345,6 +354,11 @@ LocallyManagedUserCreationScreenHandler* return locally_managed_user_creation_screen_actor_; } +AppLaunchSplashScreenActor* + OobeUI::GetAppLaunchSplashScreenActor() { + return app_launch_splash_screen_actor_; +} + void OobeUI::GetLocalizedStrings(base::DictionaryValue* localized_strings) { // Note, handlers_[0] is a GenericHandler used by the WebUI. for (size_t i = 0; i < handlers_.size(); ++i) @@ -397,6 +411,7 @@ void OobeUI::InitializeScreenMaps() { kScreenManagedUserCreationFlow; screen_names_[SCREEN_TERMS_OF_SERVICE] = kScreenTermsOfService; screen_names_[SCREEN_WRONG_HWID] = kScreenWrongHWID; + screen_names_[SCREEN_APP_LAUNCH_SPLASH] = kScreenAppLaunchSplash; screen_ids_.clear(); for (size_t i = 0; i < screen_names_.size(); ++i) diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h index 9daff23..6c92fda 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h +++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h @@ -20,6 +20,7 @@ class DictionaryValue; } // namespace base namespace chromeos { +class AppLaunchSplashScreenActor; class BaseScreenHandler; class CoreOobeHandler; class ErrorScreenHandler; @@ -56,6 +57,7 @@ class OobeUI : public OobeDisplay, static const char kScreenManagedUserCreationFlow[]; static const char kScreenTermsOfService[]; static const char kScreenWrongHWID[]; + static const char kScreenAppLaunchSplash[]; OobeUI(content::WebUI* web_ui, const GURL& url); virtual ~OobeUI(); @@ -77,6 +79,8 @@ class OobeUI : public OobeDisplay, virtual WrongHWIDScreenActor* GetWrongHWIDScreenActor() OVERRIDE; virtual LocallyManagedUserCreationScreenHandler* GetLocallyManagedUserCreationScreenActor() OVERRIDE; + virtual AppLaunchSplashScreenActor* + GetAppLaunchSplashScreenActor() OVERRIDE; virtual bool IsJSReady(const base::Closure& display_is_ready_callback) OVERRIDE; @@ -98,6 +102,9 @@ class OobeUI : public OobeDisplay, void ShowSigninScreen(SigninScreenHandlerDelegate* delegate, NativeWindowDelegate* native_window_delegate); + // Shows the kiosk splash screen. + void ShowAppLaunchSplashScreen(); + // Resets the delegate set in ShowSigninScreen. void ResetSigninScreenHandlerDelegate(); @@ -139,6 +146,7 @@ class OobeUI : public OobeDisplay, WrongHWIDScreenActor* wrong_hwid_screen_actor_; LocallyManagedUserCreationScreenHandler* locally_managed_user_creation_screen_actor_; + AppLaunchSplashScreenActor* app_launch_splash_screen_actor_; // Reference to ErrorScreenHandler that handles error screen // requests and forward calls from native code to JS side. diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc index 40b2eef..6192c72 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc @@ -852,6 +852,10 @@ void SigninScreenHandler::RegisterMessages() { AddCallback("updateOfflineLogin", &SigninScreenHandler::HandleUpdateOfflineLogin); AddCallback("focusPod", &SigninScreenHandler::HandleFocusPod); + + // This message is sent by the kiosk app menu, but is handled here + // so we can tell the delegate to launch the app. + AddCallback("launchKioskApp", &SigninScreenHandler::HandleLaunchKioskApp); } void SigninScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) { @@ -1626,6 +1630,10 @@ void SigninScreenHandler::HandleFocusPod(const std::string& user_id) { SetUserInputMethod(user_id); } +void SigninScreenHandler::HandleLaunchKioskApp(const std::string& app_id) { + delegate_->LoginAsKioskApp(app_id); +} + void SigninScreenHandler::StartClearingDnsCache() { if (dns_clear_task_running_ || !g_browser_process->io_thread()) return; diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h index a82f621..33d8915 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h @@ -157,6 +157,9 @@ class SigninScreenHandlerDelegate { // Signs out if the screen is currently locked. virtual void Signout() = 0; + // Login to kiosk mode for app with |app_id|. + virtual void LoginAsKioskApp(const std::string& app_id) = 0; + protected: virtual ~SigninScreenHandlerDelegate() {} }; @@ -327,6 +330,7 @@ class SigninScreenHandler void HandleUpdateOfflineLogin(bool offline_login_active); void HandleShowLocallyManagedUserCreationScreen(); void HandleFocusPod(const std::string& user_id); + void HandleLaunchKioskApp(const std::string& app_id); // Fills |user_dict| with information about |user|. static void FillUserDictionary(User* user, diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi index 6bc44d2..c8a5b42 100644 --- a/chrome/chrome_browser_chromeos.gypi +++ b/chrome/chrome_browser_chromeos.gypi @@ -123,11 +123,11 @@ 'browser/chromeos/accessibility/magnification_manager.h', 'browser/chromeos/app_mode/app_session_lifetime.cc', 'browser/chromeos/app_mode/app_session_lifetime.h', + 'browser/chromeos/app_mode/app_launch_utils.cc', + 'browser/chromeos/app_mode/app_launch_utils.h', 'browser/chromeos/app_mode/kiosk_app_data.cc', 'browser/chromeos/app_mode/kiosk_app_data.h', 'browser/chromeos/app_mode/kiosk_app_data_delegate.h', - 'browser/chromeos/app_mode/kiosk_app_launcher.cc', - 'browser/chromeos/app_mode/kiosk_app_launcher.h', 'browser/chromeos/app_mode/kiosk_app_launch_error.cc', 'browser/chromeos/app_mode/kiosk_app_launch_error.h', 'browser/chromeos/app_mode/kiosk_app_manager.cc', @@ -135,6 +135,8 @@ 'browser/chromeos/app_mode/kiosk_app_manager_observer.h', 'browser/chromeos/app_mode/kiosk_app_update_service.cc', 'browser/chromeos/app_mode/kiosk_app_update_service.h', + 'browser/chromeos/app_mode/kiosk_profile_loader.cc', + 'browser/chromeos/app_mode/kiosk_profile_loader.h', 'browser/chromeos/app_mode/startup_app_launcher.cc', 'browser/chromeos/app_mode/startup_app_launcher.h', 'browser/chromeos/attestation/attestation_ca_client.cc', @@ -417,6 +419,8 @@ 'browser/chromeos/language_preferences.h', 'browser/chromeos/locale_change_guard.cc', 'browser/chromeos/locale_change_guard.h', + 'browser/chromeos/login/app_launch_controller.cc', + 'browser/chromeos/login/app_launch_controller.h', 'browser/chromeos/login/auth_attempt_state.cc', 'browser/chromeos/login/auth_attempt_state.h', 'browser/chromeos/login/auth_attempt_state_resolver.cc', @@ -804,8 +808,6 @@ 'browser/chromeos/system_logs/system_logs_fetcher_base.h', 'browser/chromeos/system_logs/touch_log_source.cc', 'browser/chromeos/system_logs/touch_log_source.h', - 'browser/chromeos/ui/app_launch_view.cc', - 'browser/chromeos/ui/app_launch_view.h', 'browser/chromeos/ui/echo_dialog_listener.h', 'browser/chromeos/ui/echo_dialog_view.cc', 'browser/chromeos/ui/echo_dialog_view.h', diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index f3922f3..6a7a03f 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -1990,8 +1990,6 @@ 'browser/ui/webui/chrome_web_contents_handler.h', 'browser/ui/webui/chrome_web_ui_controller_factory.cc', 'browser/ui/webui/chrome_web_ui_controller_factory.h', - 'browser/ui/webui/chromeos/app_launch_ui.cc', - 'browser/ui/webui/chromeos/app_launch_ui.h', 'browser/ui/webui/chromeos/bluetooth_pairing_ui.cc', 'browser/ui/webui/chromeos/bluetooth_pairing_ui.h', 'browser/ui/webui/chromeos/choose_mobile_network_ui.cc', @@ -2008,6 +2006,8 @@ 'browser/ui/webui/chromeos/imageburner/imageburner_ui.h', 'browser/ui/webui/chromeos/keyboard_overlay_ui.cc', 'browser/ui/webui/chromeos/keyboard_overlay_ui.h', + 'browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc', + 'browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h', 'browser/ui/webui/chromeos/login/base_screen_handler.cc', 'browser/ui/webui/chromeos/login/base_screen_handler.h', 'browser/ui/webui/chromeos/login/base_screen_handler_utils.h', diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index 1147b84..0981b61 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc @@ -92,7 +92,6 @@ const char kChromeUIWelcomeURL[] = "chrome://welcome/"; #if defined(OS_CHROMEOS) const char kChromeUIActivationMessage[] = "chrome://activationmessage/"; -const char kChromeUIAppLaunchURL[] = "chrome://app-launch/"; const char kChromeUIBluetoothPairingURL[] = "chrome://bluetooth-pairing/"; const char kChromeUIChooseMobileNetworkURL[] = "chrome://choose-mobile-network/"; diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index 9a74456..b046aa7 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h @@ -87,7 +87,6 @@ extern const char kChromeUIWelcomeURL[]; #if defined(OS_CHROMEOS) extern const char kChromeUIActivationMessage[]; -extern const char kChromeUIAppLaunchURL[]; extern const char kChromeUIBluetoothPairingURL[]; extern const char kChromeUIChooseMobileNetworkURL[]; extern const char kChromeUIDiagnosticsURL[]; |