kiosk_app_manager.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <map> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <set> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/path_service.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/prefs/pref_service.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h" 16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/stl_util.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/sys_info.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/browser_process.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/app_mode/kiosk_app_data.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/login/user_manager.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/policy/device_local_account.h" 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/settings/cros_settings.h" 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/settings/owner_key_util.h" 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/chrome_paths.h" 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/cryptohome/async_method_caller.h" 28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chromeos/settings/cros_settings_names.h" 29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace chromeos { 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Domain that is used for kiosk-app account IDs. 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kKioskAppAccountDomain[] = "kiosk-apps"; 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string GenerateKioskAppAccountId(const std::string& app_id) { 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return app_id + '@' + kKioskAppAccountDomain; 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void OnRemoveAppCryptohomeComplete(const std::string& app, 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool success, 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome::MountError return_code) { 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!success) { 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Remove cryptohome for " << app 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << " failed, return code: " << return_code; 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Check for presence of machine owner public key file. 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CheckOwnerFilePresence(bool *present) { 53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_refptr<OwnerKeyUtil> util = OwnerKeyUtil::Create(); 54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) *present = util->IsPublicKeyPresent(); 55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char KioskAppManager::kKioskDictionaryName[] = "kiosk"; 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char KioskAppManager::kKeyApps[] = "apps"; 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char KioskAppManager::kKeyAutoLoginState[] = "auto_login_state"; 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char KioskAppManager::kIconCacheDir[] = "kiosk"; 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static base::LazyInstance<KioskAppManager> instance = LAZY_INSTANCE_INITIALIZER; 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)KioskAppManager* KioskAppManager::Get() { 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return instance.Pointer(); 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void KioskAppManager::Shutdown() { 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (instance == NULL) 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance.Pointer()->CleanUp(); 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::RegisterPrefs(PrefRegistrySimple* registry) { 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registry->RegisterDictionaryPref(kKioskDictionaryName); 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)KioskAppManager::App::App(const KioskAppData& data) 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : app_id(data.app_id()), 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_id(data.user_id()), 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) name(data.name()), 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) icon(data.icon()), 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_loading(data.IsLoading()) { 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)KioskAppManager::App::App() : is_loading(false) {} 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)KioskAppManager::App::~App() {} 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string KioskAppManager::GetAutoLaunchApp() const { 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return auto_launch_app_id_; 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void KioskAppManager::SetAutoLaunchApp(const std::string& app_id) { 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SetAutoLoginState(AUTOLOGIN_REQUESTED); 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Clean first, so the proper change callbacks are triggered even 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // if we are only changing AutoLoginState here. 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!auto_launch_app_id_.empty()) { 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CrosSettings::Get()->SetString(kAccountsPrefDeviceLocalAccountAutoLoginId, 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string()); 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CrosSettings::Get()->SetString( 109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) kAccountsPrefDeviceLocalAccountAutoLoginId, 110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) app_id.empty() ? std::string() : GenerateKioskAppAccountId(app_id)); 111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CrosSettings::Get()->SetInteger( 112d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) kAccountsPrefDeviceLocalAccountAutoLoginDelay, 0); 113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void KioskAppManager::EnableConsumerKioskAutoLaunch( 116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const KioskAppManager::EnableKioskAutoLaunchCallback& callback) { 117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) policy::BrowserPolicyConnectorChromeOS* connector = 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_browser_process->platform_part()->browser_policy_connector_chromeos(); 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connector->GetInstallAttributes()->LockDevice( 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string(), // user 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH, 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(), // device_id 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind( 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &KioskAppManager::OnLockDevice, base::Unretained(this), callback)); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::GetConsumerKioskAutoLaunchStatus( 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback& callback) { 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) policy::BrowserPolicyConnectorChromeOS* connector = 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_browser_process->platform_part()->browser_policy_connector_chromeos(); 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connector->GetInstallAttributes()->ReadImmutableAttributes( 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&KioskAppManager::OnReadImmutableAttributes, 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this), 134 callback)); 135} 136 137bool KioskAppManager::IsConsumerKioskDeviceWithAutoLaunch() { 138 policy::BrowserPolicyConnectorChromeOS* connector = 139 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 140 return connector->GetInstallAttributes() && 141 connector->GetInstallAttributes() 142 ->IsConsumerKioskDeviceWithAutoLaunch(); 143} 144 145void KioskAppManager::OnLockDevice( 146 const KioskAppManager::EnableKioskAutoLaunchCallback& callback, 147 policy::EnterpriseInstallAttributes::LockResult result) { 148 if (callback.is_null()) 149 return; 150 151 callback.Run(result == policy::EnterpriseInstallAttributes::LOCK_SUCCESS); 152} 153 154void KioskAppManager::OnOwnerFileChecked( 155 const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback& callback, 156 bool* owner_present) { 157 ownership_established_ = *owner_present; 158 159 if (callback.is_null()) 160 return; 161 162 // If we have owner already established on the machine, don't let 163 // consumer kiosk to be enabled. 164 if (ownership_established_) 165 callback.Run(CONSUMER_KIOSK_AUTO_LAUNCH_DISABLED); 166 else 167 callback.Run(CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE); 168} 169 170void KioskAppManager::OnReadImmutableAttributes( 171 const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback& 172 callback) { 173 if (callback.is_null()) 174 return; 175 176 ConsumerKioskAutoLaunchStatus status = 177 CONSUMER_KIOSK_AUTO_LAUNCH_DISABLED; 178 policy::BrowserPolicyConnectorChromeOS* connector = 179 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 180 policy::EnterpriseInstallAttributes* attributes = 181 connector->GetInstallAttributes(); 182 switch (attributes->GetMode()) { 183 case policy::DEVICE_MODE_NOT_SET: { 184 if (!base::SysInfo::IsRunningOnChromeOS()) { 185 status = CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE; 186 } else if (!ownership_established_) { 187 bool* owner_present = new bool(false); 188 content::BrowserThread::PostBlockingPoolTaskAndReply( 189 FROM_HERE, 190 base::Bind(&CheckOwnerFilePresence, 191 owner_present), 192 base::Bind(&KioskAppManager::OnOwnerFileChecked, 193 base::Unretained(this), 194 callback, 195 base::Owned(owner_present))); 196 return; 197 } 198 break; 199 } 200 case policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH: 201 status = CONSUMER_KIOSK_AUTO_LAUNCH_ENABLED; 202 break; 203 default: 204 break; 205 } 206 207 callback.Run(status); 208} 209 210void KioskAppManager::SetEnableAutoLaunch(bool value) { 211 SetAutoLoginState(value ? AUTOLOGIN_APPROVED : AUTOLOGIN_REJECTED); 212} 213 214bool KioskAppManager::IsAutoLaunchRequested() const { 215 if (GetAutoLaunchApp().empty()) 216 return false; 217 218 // Apps that were installed by the policy don't require machine owner 219 // consent through UI. 220 policy::BrowserPolicyConnectorChromeOS* connector = 221 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 222 if (connector->IsEnterpriseManaged()) 223 return false; 224 225 return GetAutoLoginState() == AUTOLOGIN_REQUESTED; 226} 227 228bool KioskAppManager::IsAutoLaunchEnabled() const { 229 if (GetAutoLaunchApp().empty()) 230 return false; 231 232 // Apps that were installed by the policy don't require machine owner 233 // consent through UI. 234 policy::BrowserPolicyConnectorChromeOS* connector = 235 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 236 if (connector->IsEnterpriseManaged()) 237 return true; 238 239 return GetAutoLoginState() == AUTOLOGIN_APPROVED; 240} 241 242void KioskAppManager::AddApp(const std::string& app_id) { 243 std::vector<policy::DeviceLocalAccount> device_local_accounts = 244 policy::GetDeviceLocalAccounts(CrosSettings::Get()); 245 246 // Don't insert the app if it's already in the list. 247 for (std::vector<policy::DeviceLocalAccount>::const_iterator 248 it = device_local_accounts.begin(); 249 it != device_local_accounts.end(); ++it) { 250 if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP && 251 it->kiosk_app_id == app_id) { 252 return; 253 } 254 } 255 256 // Add the new account. 257 device_local_accounts.push_back(policy::DeviceLocalAccount( 258 policy::DeviceLocalAccount::TYPE_KIOSK_APP, 259 GenerateKioskAppAccountId(app_id), 260 app_id)); 261 262 policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts); 263} 264 265void KioskAppManager::RemoveApp(const std::string& app_id) { 266 // Resets auto launch app if it is the removed app. 267 if (auto_launch_app_id_ == app_id) 268 SetAutoLaunchApp(std::string()); 269 270 std::vector<policy::DeviceLocalAccount> device_local_accounts = 271 policy::GetDeviceLocalAccounts(CrosSettings::Get()); 272 if (device_local_accounts.empty()) 273 return; 274 275 // Remove entries that match |app_id|. 276 for (std::vector<policy::DeviceLocalAccount>::iterator 277 it = device_local_accounts.begin(); 278 it != device_local_accounts.end(); ++it) { 279 if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP && 280 it->kiosk_app_id == app_id) { 281 device_local_accounts.erase(it); 282 break; 283 } 284 } 285 286 policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts); 287} 288 289void KioskAppManager::GetApps(Apps* apps) const { 290 apps->clear(); 291 apps->reserve(apps_.size()); 292 for (size_t i = 0; i < apps_.size(); ++i) { 293 const KioskAppData& app_data = *apps_[i]; 294 if (app_data.status() != KioskAppData::STATUS_ERROR) 295 apps->push_back(App(app_data)); 296 } 297} 298 299bool KioskAppManager::GetApp(const std::string& app_id, App* app) const { 300 const KioskAppData* data = GetAppData(app_id); 301 if (!data) 302 return false; 303 304 *app = App(*data); 305 return true; 306} 307 308const base::RefCountedString* KioskAppManager::GetAppRawIcon( 309 const std::string& app_id) const { 310 const KioskAppData* data = GetAppData(app_id); 311 if (!data) 312 return NULL; 313 314 return data->raw_icon(); 315} 316 317bool KioskAppManager::GetDisableBailoutShortcut() const { 318 bool enable; 319 if (CrosSettings::Get()->GetBoolean( 320 kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled, &enable)) { 321 return !enable; 322 } 323 324 return false; 325} 326 327void KioskAppManager::ClearAppData(const std::string& app_id) { 328 KioskAppData* app_data = GetAppDataMutable(app_id); 329 if (!app_data) 330 return; 331 332 app_data->ClearCache(); 333} 334 335void KioskAppManager::UpdateAppDataFromProfile( 336 const std::string& app_id, 337 Profile* profile, 338 const extensions::Extension* app) { 339 KioskAppData* app_data = GetAppDataMutable(app_id); 340 if (!app_data) 341 return; 342 343 app_data->LoadFromInstalledApp(profile, app); 344} 345 346void KioskAppManager::AddObserver(KioskAppManagerObserver* observer) { 347 observers_.AddObserver(observer); 348} 349 350void KioskAppManager::RemoveObserver(KioskAppManagerObserver* observer) { 351 observers_.RemoveObserver(observer); 352} 353 354KioskAppManager::KioskAppManager() : ownership_established_(false) { 355 UpdateAppData(); 356 local_accounts_subscription_ = 357 CrosSettings::Get()->AddSettingsObserver( 358 kAccountsPrefDeviceLocalAccounts, 359 base::Bind(&KioskAppManager::UpdateAppData, base::Unretained(this))); 360 local_account_auto_login_id_subscription_ = 361 CrosSettings::Get()->AddSettingsObserver( 362 kAccountsPrefDeviceLocalAccountAutoLoginId, 363 base::Bind(&KioskAppManager::UpdateAppData, base::Unretained(this))); 364} 365 366KioskAppManager::~KioskAppManager() {} 367 368void KioskAppManager::CleanUp() { 369 local_accounts_subscription_.reset(); 370 local_account_auto_login_id_subscription_.reset(); 371 apps_.clear(); 372} 373 374const KioskAppData* KioskAppManager::GetAppData( 375 const std::string& app_id) const { 376 for (size_t i = 0; i < apps_.size(); ++i) { 377 const KioskAppData* data = apps_[i]; 378 if (data->app_id() == app_id) 379 return data; 380 } 381 382 return NULL; 383} 384 385KioskAppData* KioskAppManager::GetAppDataMutable(const std::string& app_id) { 386 return const_cast<KioskAppData*>(GetAppData(app_id)); 387} 388 389void KioskAppManager::UpdateAppData() { 390 // Gets app id to data mapping for existing apps. 391 std::map<std::string, KioskAppData*> old_apps; 392 for (size_t i = 0; i < apps_.size(); ++i) 393 old_apps[apps_[i]->app_id()] = apps_[i]; 394 apps_.weak_clear(); // |old_apps| takes ownership 395 396 auto_launch_app_id_.clear(); 397 std::string auto_login_account_id; 398 CrosSettings::Get()->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId, 399 &auto_login_account_id); 400 401 // Re-populates |apps_| and reuses existing KioskAppData when possible. 402 const std::vector<policy::DeviceLocalAccount> device_local_accounts = 403 policy::GetDeviceLocalAccounts(CrosSettings::Get()); 404 for (std::vector<policy::DeviceLocalAccount>::const_iterator 405 it = device_local_accounts.begin(); 406 it != device_local_accounts.end(); ++it) { 407 if (it->type != policy::DeviceLocalAccount::TYPE_KIOSK_APP) 408 continue; 409 410 if (it->account_id == auto_login_account_id) 411 auto_launch_app_id_ = it->kiosk_app_id; 412 413 // TODO(mnissler): Support non-CWS update URLs. 414 415 std::map<std::string, KioskAppData*>::iterator old_it = 416 old_apps.find(it->kiosk_app_id); 417 if (old_it != old_apps.end()) { 418 apps_.push_back(old_it->second); 419 old_apps.erase(old_it); 420 } else { 421 KioskAppData* new_app = 422 new KioskAppData(this, it->kiosk_app_id, it->user_id); 423 apps_.push_back(new_app); // Takes ownership of |new_app|. 424 new_app->Load(); 425 } 426 } 427 428 // Clears cache and deletes the remaining old data. 429 for (std::map<std::string, KioskAppData*>::iterator it = old_apps.begin(); 430 it != old_apps.end(); ++it) { 431 it->second->ClearCache(); 432 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove( 433 it->second->user_id(), 434 base::Bind(&OnRemoveAppCryptohomeComplete, it->first)); 435 } 436 STLDeleteValues(&old_apps); 437 438 FOR_EACH_OBSERVER(KioskAppManagerObserver, observers_, 439 OnKioskAppsSettingsChanged()); 440} 441 442void KioskAppManager::GetKioskAppIconCacheDir(base::FilePath* cache_dir) { 443 base::FilePath user_data_dir; 444 CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)); 445 *cache_dir = user_data_dir.AppendASCII(kIconCacheDir); 446} 447 448void KioskAppManager::OnKioskAppDataChanged(const std::string& app_id) { 449 FOR_EACH_OBSERVER(KioskAppManagerObserver, 450 observers_, 451 OnKioskAppDataChanged(app_id)); 452} 453 454void KioskAppManager::OnKioskAppDataLoadFailure(const std::string& app_id) { 455 FOR_EACH_OBSERVER(KioskAppManagerObserver, 456 observers_, 457 OnKioskAppDataLoadFailure(app_id)); 458} 459 460KioskAppManager::AutoLoginState KioskAppManager::GetAutoLoginState() const { 461 PrefService* prefs = g_browser_process->local_state(); 462 const base::DictionaryValue* dict = 463 prefs->GetDictionary(KioskAppManager::kKioskDictionaryName); 464 int value; 465 if (!dict->GetInteger(kKeyAutoLoginState, &value)) 466 return AUTOLOGIN_NONE; 467 468 return static_cast<AutoLoginState>(value); 469} 470 471void KioskAppManager::SetAutoLoginState(AutoLoginState state) { 472 PrefService* prefs = g_browser_process->local_state(); 473 DictionaryPrefUpdate dict_update(prefs, 474 KioskAppManager::kKioskDictionaryName); 475 dict_update->SetInteger(kKeyAutoLoginState, state); 476 prefs->CommitPendingWrite(); 477} 478 479} // namespace chromeos 480