| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/app_mode/kiosk_app_launcher.h" | 5 #include "chrome/browser/chromeos/app_mode/kiosk_profile_loader.h" |
| 6 | 6 |
| 7 #include "base/chromeos/chromeos_version.h" | 7 #include "base/chromeos/chromeos_version.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/memory/weak_ptr.h" | 9 #include "base/memory/weak_ptr.h" |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| 11 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" | 11 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" |
| 12 #include "chrome/browser/chromeos/app_mode/startup_app_launcher.h" | |
| 13 #include "chrome/browser/chromeos/login/login_display_host_impl.h" | 12 #include "chrome/browser/chromeos/login/login_display_host_impl.h" |
| 14 #include "chrome/browser/chromeos/login/login_utils.h" | 13 #include "chrome/browser/chromeos/login/login_utils.h" |
| 15 #include "chrome/browser/chromeos/login/user_manager.h" | 14 #include "chrome/browser/chromeos/login/user_manager.h" |
| 16 #include "chrome/browser/chromeos/settings/cros_settings.h" | 15 #include "chrome/browser/chromeos/settings/cros_settings.h" |
| 17 #include "chrome/browser/chromeos/ui/app_launch_view.h" | |
| 18 #include "chrome/browser/lifetime/application_lifetime.h" | 16 #include "chrome/browser/lifetime/application_lifetime.h" |
| 19 #include "chromeos/cryptohome/async_method_caller.h" | 17 #include "chromeos/cryptohome/async_method_caller.h" |
| 20 #include "chromeos/cryptohome/cryptohome_library.h" | 18 #include "chromeos/cryptohome/cryptohome_library.h" |
| 21 #include "chromeos/dbus/cryptohome_client.h" | 19 #include "chromeos/dbus/cryptohome_client.h" |
| 22 #include "chromeos/dbus/dbus_thread_manager.h" | 20 #include "chromeos/dbus/dbus_thread_manager.h" |
| 23 #include "content/public/browser/browser_thread.h" | 21 #include "content/public/browser/browser_thread.h" |
| 24 | 22 |
| 25 using content::BrowserThread; | 23 using content::BrowserThread; |
| 26 | 24 |
| 27 namespace chromeos { | 25 namespace chromeos { |
| 28 | 26 |
| 29 namespace { | 27 namespace { |
| 30 | 28 |
| 31 void IgnoreResult(bool mount_success, cryptohome::MountError mount_error) {} | 29 void IgnoreResult(bool mount_success, cryptohome::MountError mount_error) {} |
| 32 | 30 |
| 33 } // namespace | 31 } // namespace |
| 34 | 32 |
| 35 // static | |
| 36 KioskAppLauncher* KioskAppLauncher::running_instance_ = NULL; | |
| 37 | |
| 38 //////////////////////////////////////////////////////////////////////////////// | 33 //////////////////////////////////////////////////////////////////////////////// |
| 39 // KioskAppLauncher::CryptohomedChecker ensures cryptohome daemon is up | 34 // KioskProfileLoader::CryptohomedChecker ensures cryptohome daemon is up |
| 40 // and running by issuing an IsMounted call. If the call does not go through | 35 // and running by issuing an IsMounted call. If the call does not go through |
| 41 // and chromeos::DBUS_METHOD_CALL_SUCCESS is not returned, it will retry after | 36 // and chromeos::DBUS_METHOD_CALL_SUCCESS is not returned, it will retry after |
| 42 // some time out and at the maximum five times before it gives up. Upon | 37 // some time out and at the maximum five times before it gives up. Upon |
| 43 // success, it resumes the launch by calling KioskAppLauncher::StartMount. | 38 // success, it resumes the launch by calling KioskProfileLoader::StartMount. |
| 44 | 39 |
| 45 class KioskAppLauncher::CryptohomedChecker | 40 class KioskProfileLoader::CryptohomedChecker |
| 46 : public base::SupportsWeakPtr<CryptohomedChecker> { | 41 : public base::SupportsWeakPtr<CryptohomedChecker> { |
| 47 public: | 42 public: |
| 48 explicit CryptohomedChecker(KioskAppLauncher* launcher) | 43 explicit CryptohomedChecker(KioskProfileLoader* loader) |
| 49 : launcher_(launcher), | 44 : loader_(loader), |
| 50 retry_count_(0) { | 45 retry_count_(0) { |
| 51 } | 46 } |
| 52 ~CryptohomedChecker() {} | 47 ~CryptohomedChecker() {} |
| 53 | 48 |
| 54 void StartCheck() { | 49 void StartCheck() { |
| 55 chromeos::DBusThreadManager::Get()->GetCryptohomeClient()->IsMounted( | 50 chromeos::DBusThreadManager::Get()->GetCryptohomeClient()->IsMounted( |
| 56 base::Bind(&CryptohomedChecker::OnCryptohomeIsMounted, | 51 base::Bind(&CryptohomedChecker::OnCryptohomeIsMounted, |
| 57 AsWeakPtr())); | 52 AsWeakPtr())); |
| 58 } | 53 } |
| 59 | 54 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 82 | 77 |
| 83 // Proceed only when cryptohome is not mounded or running on dev box. | 78 // Proceed only when cryptohome is not mounded or running on dev box. |
| 84 if (!is_mounted || !base::chromeos::IsRunningOnChromeOS()) | 79 if (!is_mounted || !base::chromeos::IsRunningOnChromeOS()) |
| 85 ReportCheckResult(KioskAppLaunchError::NONE); | 80 ReportCheckResult(KioskAppLaunchError::NONE); |
| 86 else | 81 else |
| 87 ReportCheckResult(KioskAppLaunchError::ALREADY_MOUNTED); | 82 ReportCheckResult(KioskAppLaunchError::ALREADY_MOUNTED); |
| 88 } | 83 } |
| 89 | 84 |
| 90 void ReportCheckResult(KioskAppLaunchError::Error error) { | 85 void ReportCheckResult(KioskAppLaunchError::Error error) { |
| 91 if (error == KioskAppLaunchError::NONE) | 86 if (error == KioskAppLaunchError::NONE) |
| 92 launcher_->StartMount(); | 87 loader_->StartMount(); |
| 93 else | 88 else |
| 94 launcher_->ReportLaunchResult(error); | 89 loader_->ReportLaunchResult(error); |
| 95 } | 90 } |
| 96 | 91 |
| 97 KioskAppLauncher* launcher_; | 92 KioskProfileLoader* loader_; |
| 98 int retry_count_; | 93 int retry_count_; |
| 99 | 94 |
| 100 DISALLOW_COPY_AND_ASSIGN(CryptohomedChecker); | 95 DISALLOW_COPY_AND_ASSIGN(CryptohomedChecker); |
| 101 }; | 96 }; |
| 102 | 97 |
| 103 //////////////////////////////////////////////////////////////////////////////// | 98 //////////////////////////////////////////////////////////////////////////////// |
| 104 // KioskAppLauncher::ProfileLoader creates or loads the app profile. | 99 // KioskProfileLoader::ProfileLoader actually creates or loads the app profile. |
| 105 | 100 |
| 106 class KioskAppLauncher::ProfileLoader : public LoginUtils::Delegate { | 101 class KioskProfileLoader::ProfileLoader : public LoginUtils::Delegate { |
| 107 public: | 102 public: |
| 108 ProfileLoader(KioskAppManager* kiosk_app_manager, | 103 ProfileLoader(KioskAppManager* kiosk_app_manager, |
| 109 KioskAppLauncher* kiosk_app_launcher) | 104 KioskProfileLoader* kiosk_profile_loader) |
| 110 : kiosk_app_launcher_(kiosk_app_launcher), | 105 : kiosk_profile_loader_(kiosk_profile_loader), |
| 111 user_id_(kiosk_app_launcher->user_id_) { | 106 user_id_(kiosk_profile_loader->user_id_) { |
| 112 CHECK(!user_id_.empty()); | 107 CHECK(!user_id_.empty()); |
| 113 } | 108 } |
| 114 | 109 |
| 115 virtual ~ProfileLoader() { | 110 virtual ~ProfileLoader() { |
| 116 LoginUtils::Get()->DelegateDeleted(this); | 111 LoginUtils::Get()->DelegateDeleted(this); |
| 117 } | 112 } |
| 118 | 113 |
| 119 void Start() { | 114 void Start() { |
| 120 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername( | 115 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername( |
| 121 user_id_, | 116 user_id_, |
| 122 base::Bind(&ProfileLoader::OnUsernameHashRetrieved, | 117 base::Bind(&ProfileLoader::OnUsernameHashRetrieved, |
| 123 base::Unretained(this))); | 118 base::Unretained(this))); |
| 124 } | 119 } |
| 125 | 120 |
| 126 private: | 121 private: |
| 127 void OnUsernameHashRetrieved(bool success, | 122 void OnUsernameHashRetrieved(bool success, |
| 128 const std::string& username_hash) { | 123 const std::string& username_hash) { |
| 129 if (!success) { | 124 if (!success) { |
| 130 LOG(ERROR) << "Unable to retrieve username hash for user '" << user_id_ | 125 LOG(ERROR) << "Unable to retrieve username hash for user '" << user_id_ |
| 131 << "'."; | 126 << "'."; |
| 132 kiosk_app_launcher_->ReportLaunchResult( | 127 kiosk_profile_loader_->ReportLaunchResult( |
| 133 KioskAppLaunchError::UNABLE_TO_RETRIEVE_HASH); | 128 KioskAppLaunchError::UNABLE_TO_RETRIEVE_HASH); |
| 134 return; | 129 return; |
| 135 } | 130 } |
| 136 LoginUtils::Get()->PrepareProfile( | 131 LoginUtils::Get()->PrepareProfile( |
| 137 UserContext(user_id_, | 132 UserContext(user_id_, |
| 138 std::string(), // password | 133 std::string(), // password |
| 139 std::string(), // auth_code | 134 std::string(), // auth_code |
| 140 username_hash), | 135 username_hash), |
| 141 std::string(), // display email | 136 std::string(), // display email |
| 142 false, // using_oauth | 137 false, // using_oauth |
| 143 false, // has_cookies | 138 false, // has_cookies |
| 144 false, // has_active_session | 139 false, // has_active_session |
| 145 this); | 140 this); |
| 146 } | 141 } |
| 147 | 142 |
| 148 // LoginUtils::Delegate overrides: | 143 // LoginUtils::Delegate overrides: |
| 149 virtual void OnProfilePrepared(Profile* profile) OVERRIDE { | 144 virtual void OnProfilePrepared(Profile* profile) OVERRIDE { |
| 150 kiosk_app_launcher_->OnProfilePrepared(profile); | 145 kiosk_profile_loader_->OnProfilePrepared(profile); |
| 151 } | 146 } |
| 152 | 147 |
| 153 KioskAppLauncher* kiosk_app_launcher_; | 148 KioskProfileLoader* kiosk_profile_loader_; |
| 154 std::string user_id_; | 149 std::string user_id_; |
| 155 | 150 |
| 156 DISALLOW_COPY_AND_ASSIGN(ProfileLoader); | 151 DISALLOW_COPY_AND_ASSIGN(ProfileLoader); |
| 157 }; | 152 }; |
| 158 | 153 |
| 159 //////////////////////////////////////////////////////////////////////////////// | 154 //////////////////////////////////////////////////////////////////////////////// |
| 160 // KioskAppLauncher | 155 // KioskProfileLoader |
| 161 | 156 |
| 162 KioskAppLauncher::KioskAppLauncher(KioskAppManager* kiosk_app_manager, | 157 KioskProfileLoader::KioskProfileLoader(KioskAppManager* kiosk_app_manager, |
| 163 const std::string& app_id) | 158 const std::string& app_id, |
| 159 Delegate* delegate) |
| 164 : kiosk_app_manager_(kiosk_app_manager), | 160 : kiosk_app_manager_(kiosk_app_manager), |
| 165 app_id_(app_id), | 161 app_id_(app_id), |
| 162 delegate_(delegate), |
| 166 remove_attempted_(false) { | 163 remove_attempted_(false) { |
| 167 KioskAppManager::App app; | 164 KioskAppManager::App app; |
| 168 CHECK(kiosk_app_manager_->GetApp(app_id_, &app)); | 165 CHECK(kiosk_app_manager_->GetApp(app_id_, &app)); |
| 169 user_id_ = app.user_id; | 166 user_id_ = app.user_id; |
| 170 } | 167 } |
| 171 | 168 |
| 172 KioskAppLauncher::~KioskAppLauncher() {} | 169 KioskProfileLoader::~KioskProfileLoader() {} |
| 173 | 170 |
| 174 void KioskAppLauncher::Start() { | 171 void KioskProfileLoader::Start() { |
| 175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 176 | 173 |
| 177 if (running_instance_) { | |
| 178 LOG(WARNING) << "Unable to launch " << app_id_ << "with a pending launch."; | |
| 179 ReportLaunchResult(KioskAppLaunchError::HAS_PENDING_LAUNCH); | |
| 180 return; | |
| 181 } | |
| 182 | |
| 183 running_instance_ = this; // Reset in ReportLaunchResult. | |
| 184 | |
| 185 // Show app launch splash. The spash is removed either after a successful | |
| 186 // launch or chrome exit because of launch failure. | |
| 187 chromeos::ShowAppLaunchSplashScreen(app_id_); | |
| 188 | |
| 189 // Check cryptohomed. If all goes good, flow goes to StartMount. Otherwise | 174 // Check cryptohomed. If all goes good, flow goes to StartMount. Otherwise |
| 190 // it goes to ReportLaunchResult with failure. | 175 // it goes to ReportLaunchResult with failure. |
| 191 crytohomed_checker.reset(new CryptohomedChecker(this)); | 176 crytohomed_checker.reset(new CryptohomedChecker(this)); |
| 192 crytohomed_checker->StartCheck(); | 177 crytohomed_checker->StartCheck(); |
| 193 } | 178 } |
| 194 | 179 |
| 195 void KioskAppLauncher::ReportLaunchResult(KioskAppLaunchError::Error error) { | 180 void KioskProfileLoader::ReportLaunchResult(KioskAppLaunchError::Error error) { |
| 196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 197 | 182 |
| 198 running_instance_ = NULL; | |
| 199 | |
| 200 if (error != KioskAppLaunchError::NONE) { | 183 if (error != KioskAppLaunchError::NONE) { |
| 201 // Saves the error and ends the session to go back to login screen. | 184 delegate_->OnProfileLoadFailed(error); |
| 202 KioskAppLaunchError::Save(error); | |
| 203 chrome::AttemptUserExit(); | |
| 204 } | 185 } |
| 205 | |
| 206 delete this; | |
| 207 } | 186 } |
| 208 | 187 |
| 209 void KioskAppLauncher::StartMount() { | 188 void KioskProfileLoader::StartMount() { |
| 210 // Nuke old home that uses |app_id_| as cryptohome user id. | 189 // Nuke old home that uses |app_id_| as cryptohome user id. |
| 211 // TODO(xiyuan): Remove this after all clients migrated to new home. | 190 // TODO(xiyuan): Remove this after all clients migrated to new home. |
| 212 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove( | 191 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove( |
| 213 app_id_, | 192 app_id_, |
| 214 base::Bind(&IgnoreResult)); | 193 base::Bind(&IgnoreResult)); |
| 215 | 194 |
| 216 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountPublic( | 195 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountPublic( |
| 217 user_id_, | 196 user_id_, |
| 218 cryptohome::CREATE_IF_MISSING, | 197 cryptohome::CREATE_IF_MISSING, |
| 219 base::Bind(&KioskAppLauncher::MountCallback, | 198 base::Bind(&KioskProfileLoader::MountCallback, |
| 220 base::Unretained(this))); | 199 base::Unretained(this))); |
| 221 } | 200 } |
| 222 | 201 |
| 223 void KioskAppLauncher::MountCallback(bool mount_success, | 202 void KioskProfileLoader::MountCallback(bool mount_success, |
| 224 cryptohome::MountError mount_error) { | 203 cryptohome::MountError mount_error) { |
| 225 if (mount_success) { | 204 if (mount_success) { |
| 226 profile_loader_.reset(new ProfileLoader(kiosk_app_manager_, this)); | 205 profile_loader_.reset(new ProfileLoader(kiosk_app_manager_, this)); |
| 227 profile_loader_->Start(); | 206 profile_loader_->Start(); |
| 228 return; | 207 return; |
| 229 } | 208 } |
| 230 | 209 |
| 231 if (!remove_attempted_) { | 210 if (!remove_attempted_) { |
| 232 LOG(ERROR) << "Attempt to remove app cryptohome because of mount failure" | 211 LOG(ERROR) << "Attempt to remove app cryptohome because of mount failure" |
| 233 << ", mount error=" << mount_error; | 212 << ", mount error=" << mount_error; |
| 234 | 213 |
| 235 remove_attempted_ = true; | 214 remove_attempted_ = true; |
| 236 AttemptRemove(); | 215 AttemptRemove(); |
| 237 return; | 216 return; |
| 238 } | 217 } |
| 239 | 218 |
| 240 LOG(ERROR) << "Failed to mount app cryptohome, error=" << mount_error; | 219 LOG(ERROR) << "Failed to mount app cryptohome, error=" << mount_error; |
| 241 ReportLaunchResult(KioskAppLaunchError::UNABLE_TO_MOUNT); | 220 ReportLaunchResult(KioskAppLaunchError::UNABLE_TO_MOUNT); |
| 242 } | 221 } |
| 243 | 222 |
| 244 void KioskAppLauncher::AttemptRemove() { | 223 void KioskProfileLoader::AttemptRemove() { |
| 245 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove( | 224 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove( |
| 246 user_id_, | 225 user_id_, |
| 247 base::Bind(&KioskAppLauncher::RemoveCallback, | 226 base::Bind(&KioskProfileLoader::RemoveCallback, |
| 248 base::Unretained(this))); | 227 base::Unretained(this))); |
| 249 } | 228 } |
| 250 | 229 |
| 251 void KioskAppLauncher::RemoveCallback(bool success, | 230 void KioskProfileLoader::RemoveCallback(bool success, |
| 252 cryptohome::MountError return_code) { | 231 cryptohome::MountError return_code) { |
| 253 if (success) { | 232 if (success) { |
| 254 StartMount(); | 233 StartMount(); |
| 255 return; | 234 return; |
| 256 } | 235 } |
| 257 | 236 |
| 258 LOG(ERROR) << "Failed to remove app cryptohome, erro=" << return_code; | 237 LOG(ERROR) << "Failed to remove app cryptohome, error=" << return_code; |
| 259 ReportLaunchResult(KioskAppLaunchError::UNABLE_TO_REMOVE); | 238 ReportLaunchResult(KioskAppLaunchError::UNABLE_TO_REMOVE); |
| 260 } | 239 } |
| 261 | 240 |
| 262 void KioskAppLauncher::OnProfilePrepared(Profile* profile) { | 241 void KioskProfileLoader::OnProfilePrepared(Profile* profile) { |
| 263 // StartupAppLauncher deletes itself when done. | |
| 264 (new chromeos::StartupAppLauncher(profile, app_id_))->Start(); | |
| 265 | |
| 266 if (LoginDisplayHostImpl::default_host()) | |
| 267 LoginDisplayHostImpl::default_host()->Finalize(); | |
| 268 UserManager::Get()->SessionStarted(); | 242 UserManager::Get()->SessionStarted(); |
| 269 | 243 delegate_->OnProfileLoaded(profile); |
| 270 ReportLaunchResult(KioskAppLaunchError::NONE); | 244 ReportLaunchResult(KioskAppLaunchError::NONE); |
| 271 } | 245 } |
| 272 | 246 |
| 273 } // namespace chromeos | 247 } // namespace chromeos |
| OLD | NEW |