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