[Android] Allow multiple --install in bb_device_steps.py.
[chromium-blink-merge.git] / chrome / browser / chromeos / app_mode / kiosk_app_manager.cc
blob87f423246c863bf6b96c61474d3abe743c0edab7
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
7 #include <map>
8 #include <set>
10 #include "base/bind.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/logging.h"
14 #include "base/path_service.h"
15 #include "base/prefs/pref_registry_simple.h"
16 #include "base/prefs/pref_service.h"
17 #include "base/prefs/scoped_user_pref_update.h"
18 #include "base/stl_util.h"
19 #include "base/sys_info.h"
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/chromeos/app_mode/kiosk_app_data.h"
22 #include "chrome/browser/chromeos/app_mode/kiosk_app_external_loader.h"
23 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h"
24 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
25 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
26 #include "chrome/browser/chromeos/policy/device_local_account.h"
27 #include "chrome/browser/chromeos/settings/cros_settings.h"
28 #include "chrome/browser/extensions/external_loader.h"
29 #include "chrome/browser/extensions/external_provider_impl.h"
30 #include "chrome/common/chrome_paths.h"
31 #include "chrome/common/extensions/extension_constants.h"
32 #include "chromeos/chromeos_paths.h"
33 #include "chromeos/cryptohome/async_method_caller.h"
34 #include "chromeos/settings/cros_settings_names.h"
35 #include "components/ownership/owner_key_util.h"
36 #include "content/public/browser/browser_thread.h"
37 #include "extensions/common/extension_urls.h"
39 #if !defined(USE_ATHENA)
40 #include "chrome/browser/chromeos/app_mode/kiosk_external_updater.h"
41 #endif
43 namespace chromeos {
45 namespace {
47 // Domain that is used for kiosk-app account IDs.
48 const char kKioskAppAccountDomain[] = "kiosk-apps";
50 std::string GenerateKioskAppAccountId(const std::string& app_id) {
51 return app_id + '@' + kKioskAppAccountDomain;
54 void OnRemoveAppCryptohomeComplete(const std::string& app,
55 bool success,
56 cryptohome::MountError return_code) {
57 if (!success) {
58 LOG(ERROR) << "Remove cryptohome for " << app
59 << " failed, return code: " << return_code;
63 // Check for presence of machine owner public key file.
64 void CheckOwnerFilePresence(bool *present) {
65 scoped_refptr<ownership::OwnerKeyUtil> util =
66 OwnerSettingsServiceChromeOSFactory::GetInstance()->GetOwnerKeyUtil();
67 *present = util.get() && util->IsPublicKeyPresent();
70 scoped_refptr<base::SequencedTaskRunner> GetBackgroundTaskRunner() {
71 base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
72 CHECK(pool);
73 return pool->GetSequencedTaskRunnerWithShutdownBehavior(
74 pool->GetSequenceToken(), base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
77 } // namespace
79 // static
80 const char KioskAppManager::kKioskDictionaryName[] = "kiosk";
81 const char KioskAppManager::kKeyApps[] = "apps";
82 const char KioskAppManager::kKeyAutoLoginState[] = "auto_login_state";
83 const char KioskAppManager::kIconCacheDir[] = "kiosk/icon";
84 const char KioskAppManager::kCrxCacheDir[] = "kiosk/crx";
85 const char KioskAppManager::kCrxUnpackDir[] = "kiosk_unpack";
87 // static
88 static base::LazyInstance<KioskAppManager> instance = LAZY_INSTANCE_INITIALIZER;
89 KioskAppManager* KioskAppManager::Get() {
90 return instance.Pointer();
93 // static
94 void KioskAppManager::Shutdown() {
95 if (instance == NULL)
96 return;
98 instance.Pointer()->CleanUp();
101 // static
102 void KioskAppManager::RegisterPrefs(PrefRegistrySimple* registry) {
103 registry->RegisterDictionaryPref(kKioskDictionaryName);
106 KioskAppManager::App::App(const KioskAppData& data, bool is_extension_pending)
107 : app_id(data.app_id()),
108 user_id(data.user_id()),
109 name(data.name()),
110 icon(data.icon()),
111 is_loading(data.IsLoading() || is_extension_pending) {
114 KioskAppManager::App::App() : is_loading(false) {}
115 KioskAppManager::App::~App() {}
117 std::string KioskAppManager::GetAutoLaunchApp() const {
118 return auto_launch_app_id_;
121 void KioskAppManager::SetAutoLaunchApp(const std::string& app_id) {
122 SetAutoLoginState(AUTOLOGIN_REQUESTED);
123 // Clean first, so the proper change callbacks are triggered even
124 // if we are only changing AutoLoginState here.
125 if (!auto_launch_app_id_.empty()) {
126 CrosSettings::Get()->SetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
127 std::string());
130 CrosSettings::Get()->SetString(
131 kAccountsPrefDeviceLocalAccountAutoLoginId,
132 app_id.empty() ? std::string() : GenerateKioskAppAccountId(app_id));
133 CrosSettings::Get()->SetInteger(
134 kAccountsPrefDeviceLocalAccountAutoLoginDelay, 0);
137 void KioskAppManager::EnableConsumerKioskAutoLaunch(
138 const KioskAppManager::EnableKioskAutoLaunchCallback& callback) {
139 policy::BrowserPolicyConnectorChromeOS* connector =
140 g_browser_process->platform_part()->browser_policy_connector_chromeos();
141 connector->GetInstallAttributes()->LockDevice(
142 std::string(), // user
143 policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH,
144 std::string(), // device_id
145 base::Bind(
146 &KioskAppManager::OnLockDevice, base::Unretained(this), callback));
149 void KioskAppManager::GetConsumerKioskAutoLaunchStatus(
150 const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback& callback) {
151 policy::BrowserPolicyConnectorChromeOS* connector =
152 g_browser_process->platform_part()->browser_policy_connector_chromeos();
153 connector->GetInstallAttributes()->ReadImmutableAttributes(
154 base::Bind(&KioskAppManager::OnReadImmutableAttributes,
155 base::Unretained(this),
156 callback));
159 bool KioskAppManager::IsConsumerKioskDeviceWithAutoLaunch() {
160 policy::BrowserPolicyConnectorChromeOS* connector =
161 g_browser_process->platform_part()->browser_policy_connector_chromeos();
162 return connector->GetInstallAttributes() &&
163 connector->GetInstallAttributes()
164 ->IsConsumerKioskDeviceWithAutoLaunch();
167 void KioskAppManager::OnLockDevice(
168 const KioskAppManager::EnableKioskAutoLaunchCallback& callback,
169 policy::EnterpriseInstallAttributes::LockResult result) {
170 if (callback.is_null())
171 return;
173 callback.Run(result == policy::EnterpriseInstallAttributes::LOCK_SUCCESS);
176 void KioskAppManager::OnOwnerFileChecked(
177 const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback& callback,
178 bool* owner_present) {
179 ownership_established_ = *owner_present;
181 if (callback.is_null())
182 return;
184 // If we have owner already established on the machine, don't let
185 // consumer kiosk to be enabled.
186 if (ownership_established_)
187 callback.Run(CONSUMER_KIOSK_AUTO_LAUNCH_DISABLED);
188 else
189 callback.Run(CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE);
192 void KioskAppManager::OnReadImmutableAttributes(
193 const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback&
194 callback) {
195 if (callback.is_null())
196 return;
198 ConsumerKioskAutoLaunchStatus status =
199 CONSUMER_KIOSK_AUTO_LAUNCH_DISABLED;
200 policy::BrowserPolicyConnectorChromeOS* connector =
201 g_browser_process->platform_part()->browser_policy_connector_chromeos();
202 policy::EnterpriseInstallAttributes* attributes =
203 connector->GetInstallAttributes();
204 switch (attributes->GetMode()) {
205 case policy::DEVICE_MODE_NOT_SET: {
206 if (!base::SysInfo::IsRunningOnChromeOS()) {
207 status = CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE;
208 } else if (!ownership_established_) {
209 bool* owner_present = new bool(false);
210 content::BrowserThread::PostBlockingPoolTaskAndReply(
211 FROM_HERE,
212 base::Bind(&CheckOwnerFilePresence,
213 owner_present),
214 base::Bind(&KioskAppManager::OnOwnerFileChecked,
215 base::Unretained(this),
216 callback,
217 base::Owned(owner_present)));
218 return;
220 break;
222 case policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH:
223 status = CONSUMER_KIOSK_AUTO_LAUNCH_ENABLED;
224 break;
225 default:
226 break;
229 callback.Run(status);
232 void KioskAppManager::SetEnableAutoLaunch(bool value) {
233 SetAutoLoginState(value ? AUTOLOGIN_APPROVED : AUTOLOGIN_REJECTED);
236 bool KioskAppManager::IsAutoLaunchRequested() const {
237 if (GetAutoLaunchApp().empty())
238 return false;
240 // Apps that were installed by the policy don't require machine owner
241 // consent through UI.
242 policy::BrowserPolicyConnectorChromeOS* connector =
243 g_browser_process->platform_part()->browser_policy_connector_chromeos();
244 if (connector->IsEnterpriseManaged())
245 return false;
247 return GetAutoLoginState() == AUTOLOGIN_REQUESTED;
250 bool KioskAppManager::IsAutoLaunchEnabled() const {
251 if (GetAutoLaunchApp().empty())
252 return false;
254 // Apps that were installed by the policy don't require machine owner
255 // consent through UI.
256 policy::BrowserPolicyConnectorChromeOS* connector =
257 g_browser_process->platform_part()->browser_policy_connector_chromeos();
258 if (connector->IsEnterpriseManaged())
259 return true;
261 return GetAutoLoginState() == AUTOLOGIN_APPROVED;
264 void KioskAppManager::AddApp(const std::string& app_id) {
265 std::vector<policy::DeviceLocalAccount> device_local_accounts =
266 policy::GetDeviceLocalAccounts(CrosSettings::Get());
268 // Don't insert the app if it's already in the list.
269 for (std::vector<policy::DeviceLocalAccount>::const_iterator
270 it = device_local_accounts.begin();
271 it != device_local_accounts.end(); ++it) {
272 if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP &&
273 it->kiosk_app_id == app_id) {
274 return;
278 // Add the new account.
279 device_local_accounts.push_back(policy::DeviceLocalAccount(
280 policy::DeviceLocalAccount::TYPE_KIOSK_APP,
281 GenerateKioskAppAccountId(app_id),
282 app_id,
283 std::string()));
285 policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts);
288 void KioskAppManager::RemoveApp(const std::string& app_id) {
289 // Resets auto launch app if it is the removed app.
290 if (auto_launch_app_id_ == app_id)
291 SetAutoLaunchApp(std::string());
293 std::vector<policy::DeviceLocalAccount> device_local_accounts =
294 policy::GetDeviceLocalAccounts(CrosSettings::Get());
295 if (device_local_accounts.empty())
296 return;
298 // Remove entries that match |app_id|.
299 for (std::vector<policy::DeviceLocalAccount>::iterator
300 it = device_local_accounts.begin();
301 it != device_local_accounts.end(); ++it) {
302 if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP &&
303 it->kiosk_app_id == app_id) {
304 device_local_accounts.erase(it);
305 break;
309 policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts);
312 void KioskAppManager::GetApps(Apps* apps) const {
313 apps->clear();
314 apps->reserve(apps_.size());
315 for (size_t i = 0; i < apps_.size(); ++i) {
316 const KioskAppData& app_data = *apps_[i];
317 if (app_data.status() != KioskAppData::STATUS_ERROR)
318 apps->push_back(App(
319 app_data, external_cache_->IsExtensionPending(app_data.app_id())));
323 bool KioskAppManager::GetApp(const std::string& app_id, App* app) const {
324 const KioskAppData* data = GetAppData(app_id);
325 if (!data)
326 return false;
328 *app = App(*data, external_cache_->IsExtensionPending(app_id));
329 return true;
332 const base::RefCountedString* KioskAppManager::GetAppRawIcon(
333 const std::string& app_id) const {
334 const KioskAppData* data = GetAppData(app_id);
335 if (!data)
336 return NULL;
338 return data->raw_icon();
341 bool KioskAppManager::GetDisableBailoutShortcut() const {
342 bool enable;
343 if (CrosSettings::Get()->GetBoolean(
344 kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled, &enable)) {
345 return !enable;
348 return false;
351 void KioskAppManager::ClearAppData(const std::string& app_id) {
352 KioskAppData* app_data = GetAppDataMutable(app_id);
353 if (!app_data)
354 return;
356 app_data->ClearCache();
359 void KioskAppManager::UpdateAppDataFromProfile(
360 const std::string& app_id,
361 Profile* profile,
362 const extensions::Extension* app) {
363 KioskAppData* app_data = GetAppDataMutable(app_id);
364 if (!app_data)
365 return;
367 app_data->LoadFromInstalledApp(profile, app);
370 void KioskAppManager::RetryFailedAppDataFetch() {
371 for (size_t i = 0; i < apps_.size(); ++i) {
372 if (apps_[i]->status() == KioskAppData::STATUS_ERROR)
373 apps_[i]->Load();
377 bool KioskAppManager::HasCachedCrx(const std::string& app_id) const {
378 base::FilePath crx_path;
379 std::string version;
380 return GetCachedCrx(app_id, &crx_path, &version);
383 bool KioskAppManager::GetCachedCrx(const std::string& app_id,
384 base::FilePath* file_path,
385 std::string* version) const {
386 return external_cache_->GetExtension(app_id, file_path, version);
389 void KioskAppManager::AddObserver(KioskAppManagerObserver* observer) {
390 observers_.AddObserver(observer);
393 void KioskAppManager::RemoveObserver(KioskAppManagerObserver* observer) {
394 observers_.RemoveObserver(observer);
397 extensions::ExternalLoader* KioskAppManager::CreateExternalLoader() {
398 if (external_loader_created_) {
399 NOTREACHED();
400 return NULL;
402 external_loader_created_ = true;
403 KioskAppExternalLoader* loader = new KioskAppExternalLoader();
404 external_loader_ = loader->AsWeakPtr();
406 return loader;
409 void KioskAppManager::InstallFromCache(const std::string& id) {
410 const base::DictionaryValue* extension = NULL;
411 if (external_cache_->cached_extensions()->GetDictionary(id, &extension)) {
412 scoped_ptr<base::DictionaryValue> prefs(new base::DictionaryValue);
413 base::DictionaryValue* extension_copy = extension->DeepCopy();
414 prefs->Set(id, extension_copy);
415 external_loader_->SetCurrentAppExtensions(prefs.Pass());
416 } else {
417 LOG(ERROR) << "Can't find app in the cached externsions"
418 << " id = " << id;
422 void KioskAppManager::UpdateExternalCache() {
423 UpdateAppData();
426 void KioskAppManager::OnKioskAppCacheUpdated(const std::string& app_id) {
427 FOR_EACH_OBSERVER(
428 KioskAppManagerObserver, observers_, OnKioskAppCacheUpdated(app_id));
431 void KioskAppManager::OnKioskAppExternalUpdateComplete(bool success) {
432 FOR_EACH_OBSERVER(KioskAppManagerObserver,
433 observers_,
434 OnKioskAppExternalUpdateComplete(success));
437 void KioskAppManager::PutValidatedExternalExtension(
438 const std::string& app_id,
439 const base::FilePath& crx_path,
440 const std::string& version,
441 const ExternalCache::PutExternalExtensionCallback& callback) {
442 external_cache_->PutExternalExtension(app_id, crx_path, version, callback);
445 KioskAppManager::KioskAppManager()
446 : ownership_established_(false), external_loader_created_(false) {
447 base::FilePath cache_dir;
448 GetCrxCacheDir(&cache_dir);
449 external_cache_.reset(
450 new ExternalCache(cache_dir,
451 g_browser_process->system_request_context(),
452 GetBackgroundTaskRunner(),
453 this,
454 true /* always_check_updates */,
455 false /* wait_for_cache_initialization */));
456 UpdateAppData();
457 local_accounts_subscription_ =
458 CrosSettings::Get()->AddSettingsObserver(
459 kAccountsPrefDeviceLocalAccounts,
460 base::Bind(&KioskAppManager::UpdateAppData, base::Unretained(this)));
461 local_account_auto_login_id_subscription_ =
462 CrosSettings::Get()->AddSettingsObserver(
463 kAccountsPrefDeviceLocalAccountAutoLoginId,
464 base::Bind(&KioskAppManager::UpdateAppData, base::Unretained(this)));
467 KioskAppManager::~KioskAppManager() {}
469 void KioskAppManager::MonitorKioskExternalUpdate() {
470 #if !defined(USE_ATHENA)
471 base::FilePath cache_dir;
472 GetCrxCacheDir(&cache_dir);
473 base::FilePath unpack_dir;
474 GetCrxUnpackDir(&unpack_dir);
475 usb_stick_updater_.reset(new KioskExternalUpdater(
476 GetBackgroundTaskRunner(), cache_dir, unpack_dir));
477 #endif
480 void KioskAppManager::CleanUp() {
481 local_accounts_subscription_.reset();
482 local_account_auto_login_id_subscription_.reset();
483 apps_.clear();
484 #if !defined(USE_ATHENA)
485 usb_stick_updater_.reset();
486 #endif
487 external_cache_.reset();
490 const KioskAppData* KioskAppManager::GetAppData(
491 const std::string& app_id) const {
492 for (size_t i = 0; i < apps_.size(); ++i) {
493 const KioskAppData* data = apps_[i];
494 if (data->app_id() == app_id)
495 return data;
498 return NULL;
501 KioskAppData* KioskAppManager::GetAppDataMutable(const std::string& app_id) {
502 return const_cast<KioskAppData*>(GetAppData(app_id));
505 void KioskAppManager::UpdateAppData() {
506 // Gets app id to data mapping for existing apps.
507 std::map<std::string, KioskAppData*> old_apps;
508 for (size_t i = 0; i < apps_.size(); ++i)
509 old_apps[apps_[i]->app_id()] = apps_[i];
510 apps_.weak_clear(); // |old_apps| takes ownership
512 auto_launch_app_id_.clear();
513 std::string auto_login_account_id;
514 CrosSettings::Get()->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
515 &auto_login_account_id);
517 // Re-populates |apps_| and reuses existing KioskAppData when possible.
518 const std::vector<policy::DeviceLocalAccount> device_local_accounts =
519 policy::GetDeviceLocalAccounts(CrosSettings::Get());
520 for (std::vector<policy::DeviceLocalAccount>::const_iterator
521 it = device_local_accounts.begin();
522 it != device_local_accounts.end(); ++it) {
523 if (it->type != policy::DeviceLocalAccount::TYPE_KIOSK_APP)
524 continue;
526 if (it->account_id == auto_login_account_id)
527 auto_launch_app_id_ = it->kiosk_app_id;
529 std::map<std::string, KioskAppData*>::iterator old_it =
530 old_apps.find(it->kiosk_app_id);
531 if (old_it != old_apps.end()) {
532 apps_.push_back(old_it->second);
533 old_apps.erase(old_it);
534 } else {
535 KioskAppData* new_app = new KioskAppData(
536 this, it->kiosk_app_id, it->user_id, GURL(it->kiosk_app_update_url));
537 apps_.push_back(new_app); // Takes ownership of |new_app|.
538 new_app->Load();
542 // Clears cache and deletes the remaining old data.
543 std::vector<std::string> apps_to_remove;
544 for (std::map<std::string, KioskAppData*>::iterator it = old_apps.begin();
545 it != old_apps.end(); ++it) {
546 it->second->ClearCache();
547 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
548 it->second->user_id(),
549 base::Bind(&OnRemoveAppCryptohomeComplete, it->first));
550 apps_to_remove.push_back(it->second->app_id());
552 STLDeleteValues(&old_apps);
553 external_cache_->RemoveExtensions(apps_to_remove);
555 // Request external_cache_ to download new apps and update the existing
556 // apps.
557 scoped_ptr<base::DictionaryValue> prefs(new base::DictionaryValue);
558 for (size_t i = 0; i < apps_.size(); ++i) {
559 scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue);
561 if (apps_[i]->update_url().is_valid()) {
562 entry->SetString(extensions::ExternalProviderImpl::kExternalUpdateUrl,
563 apps_[i]->update_url().spec());
564 } else {
565 entry->SetString(extensions::ExternalProviderImpl::kExternalUpdateUrl,
566 extension_urls::GetWebstoreUpdateUrl().spec());
569 prefs->Set(apps_[i]->app_id(), entry.release());
571 external_cache_->UpdateExtensionsList(prefs.Pass());
573 RetryFailedAppDataFetch();
575 FOR_EACH_OBSERVER(KioskAppManagerObserver, observers_,
576 OnKioskAppsSettingsChanged());
579 void KioskAppManager::GetKioskAppIconCacheDir(base::FilePath* cache_dir) {
580 base::FilePath user_data_dir;
581 CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
582 *cache_dir = user_data_dir.AppendASCII(kIconCacheDir);
585 void KioskAppManager::OnKioskAppDataChanged(const std::string& app_id) {
586 FOR_EACH_OBSERVER(KioskAppManagerObserver,
587 observers_,
588 OnKioskAppDataChanged(app_id));
591 void KioskAppManager::OnKioskAppDataLoadFailure(const std::string& app_id) {
592 FOR_EACH_OBSERVER(KioskAppManagerObserver,
593 observers_,
594 OnKioskAppDataLoadFailure(app_id));
597 void KioskAppManager::OnExtensionListsUpdated(
598 const base::DictionaryValue* prefs) {
601 void KioskAppManager::OnExtensionLoadedInCache(const std::string& id) {
602 KioskAppData* app_data = GetAppDataMutable(id);
603 if (!app_data)
604 return;
605 FOR_EACH_OBSERVER(KioskAppManagerObserver,
606 observers_,
607 OnKioskExtensionLoadedInCache(id));
611 void KioskAppManager::OnExtensionDownloadFailed(
612 const std::string& id,
613 extensions::ExtensionDownloaderDelegate::Error error) {
614 KioskAppData* app_data = GetAppDataMutable(id);
615 if (!app_data)
616 return;
617 FOR_EACH_OBSERVER(KioskAppManagerObserver,
618 observers_,
619 OnKioskExtensionDownloadFailed(id));
622 KioskAppManager::AutoLoginState KioskAppManager::GetAutoLoginState() const {
623 PrefService* prefs = g_browser_process->local_state();
624 const base::DictionaryValue* dict =
625 prefs->GetDictionary(KioskAppManager::kKioskDictionaryName);
626 int value;
627 if (!dict->GetInteger(kKeyAutoLoginState, &value))
628 return AUTOLOGIN_NONE;
630 return static_cast<AutoLoginState>(value);
633 void KioskAppManager::SetAutoLoginState(AutoLoginState state) {
634 PrefService* prefs = g_browser_process->local_state();
635 DictionaryPrefUpdate dict_update(prefs,
636 KioskAppManager::kKioskDictionaryName);
637 dict_update->SetInteger(kKeyAutoLoginState, state);
638 prefs->CommitPendingWrite();
641 void KioskAppManager::GetCrxCacheDir(base::FilePath* cache_dir) {
642 base::FilePath user_data_dir;
643 CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
644 *cache_dir = user_data_dir.AppendASCII(kCrxCacheDir);
647 void KioskAppManager::GetCrxUnpackDir(base::FilePath* unpack_dir) {
648 base::FilePath temp_dir;
649 base::GetTempDir(&temp_dir);
650 *unpack_dir = temp_dir.AppendASCII(kCrxUnpackDir);
653 } // namespace chromeos