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.
4
5 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
6
7 #include <map>
8 #include <set>
9
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/app_mode/kiosk_external_updater.h"
25 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
26 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
27 #include "chrome/browser/chromeos/policy/device_local_account.h"
28 #include "chrome/browser/chromeos/settings/cros_settings.h"
29 #include "chrome/browser/extensions/external_loader.h"
30 #include "chrome/browser/extensions/external_provider_impl.h"
31 #include "chrome/common/chrome_paths.h"
32 #include "chrome/common/extensions/extension_constants.h"
33 #include "chromeos/chromeos_paths.h"
34 #include "chromeos/cryptohome/async_method_caller.h"
35 #include "chromeos/settings/cros_settings_names.h"
36 #include "components/ownership/owner_key_util.h"
37 #include "content/public/browser/browser_thread.h"
38
39 namespace chromeos {
40
41 namespace {
42
43 // Domain that is used for kiosk-app account IDs.
44 const char kKioskAppAccountDomain[] = "kiosk-apps";
45
GenerateKioskAppAccountId(const std::string & app_id)46 std::string GenerateKioskAppAccountId(const std::string& app_id) {
47 return app_id + '@' + kKioskAppAccountDomain;
48 }
49
OnRemoveAppCryptohomeComplete(const std::string & app,bool success,cryptohome::MountError return_code)50 void OnRemoveAppCryptohomeComplete(const std::string& app,
51 bool success,
52 cryptohome::MountError return_code) {
53 if (!success) {
54 LOG(ERROR) << "Remove cryptohome for " << app
55 << " failed, return code: " << return_code;
56 }
57 }
58
59 // Check for presence of machine owner public key file.
CheckOwnerFilePresence(bool * present)60 void CheckOwnerFilePresence(bool *present) {
61 scoped_refptr<ownership::OwnerKeyUtil> util =
62 OwnerSettingsServiceChromeOSFactory::GetInstance()->GetOwnerKeyUtil();
63 *present = util.get() && util->IsPublicKeyPresent();
64 }
65
GetBackgroundTaskRunner()66 scoped_refptr<base::SequencedTaskRunner> GetBackgroundTaskRunner() {
67 base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
68 CHECK(pool);
69 return pool->GetSequencedTaskRunnerWithShutdownBehavior(
70 pool->GetSequenceToken(), base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
71 }
72
73 } // namespace
74
75 // static
76 const char KioskAppManager::kKioskDictionaryName[] = "kiosk";
77 const char KioskAppManager::kKeyApps[] = "apps";
78 const char KioskAppManager::kKeyAutoLoginState[] = "auto_login_state";
79 const char KioskAppManager::kIconCacheDir[] = "kiosk/icon";
80 const char KioskAppManager::kCrxCacheDir[] = "kiosk/crx";
81 const char KioskAppManager::kCrxUnpackDir[] = "kiosk_unpack";
82
83 // static
84 static base::LazyInstance<KioskAppManager> instance = LAZY_INSTANCE_INITIALIZER;
Get()85 KioskAppManager* KioskAppManager::Get() {
86 return instance.Pointer();
87 }
88
89 // static
Shutdown()90 void KioskAppManager::Shutdown() {
91 if (instance == NULL)
92 return;
93
94 instance.Pointer()->CleanUp();
95 }
96
97 // static
RegisterPrefs(PrefRegistrySimple * registry)98 void KioskAppManager::RegisterPrefs(PrefRegistrySimple* registry) {
99 registry->RegisterDictionaryPref(kKioskDictionaryName);
100 }
101
App(const KioskAppData & data,bool is_extension_pending)102 KioskAppManager::App::App(const KioskAppData& data, bool is_extension_pending)
103 : app_id(data.app_id()),
104 user_id(data.user_id()),
105 name(data.name()),
106 icon(data.icon()),
107 is_loading(data.IsLoading() || is_extension_pending) {
108 }
109
App()110 KioskAppManager::App::App() : is_loading(false) {}
~App()111 KioskAppManager::App::~App() {}
112
GetAutoLaunchApp() const113 std::string KioskAppManager::GetAutoLaunchApp() const {
114 return auto_launch_app_id_;
115 }
116
SetAutoLaunchApp(const std::string & app_id)117 void KioskAppManager::SetAutoLaunchApp(const std::string& app_id) {
118 SetAutoLoginState(AUTOLOGIN_REQUESTED);
119 // Clean first, so the proper change callbacks are triggered even
120 // if we are only changing AutoLoginState here.
121 if (!auto_launch_app_id_.empty()) {
122 CrosSettings::Get()->SetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
123 std::string());
124 }
125
126 CrosSettings::Get()->SetString(
127 kAccountsPrefDeviceLocalAccountAutoLoginId,
128 app_id.empty() ? std::string() : GenerateKioskAppAccountId(app_id));
129 CrosSettings::Get()->SetInteger(
130 kAccountsPrefDeviceLocalAccountAutoLoginDelay, 0);
131 }
132
EnableConsumerKioskAutoLaunch(const KioskAppManager::EnableKioskAutoLaunchCallback & callback)133 void KioskAppManager::EnableConsumerKioskAutoLaunch(
134 const KioskAppManager::EnableKioskAutoLaunchCallback& callback) {
135 policy::BrowserPolicyConnectorChromeOS* connector =
136 g_browser_process->platform_part()->browser_policy_connector_chromeos();
137 connector->GetInstallAttributes()->LockDevice(
138 std::string(), // user
139 policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH,
140 std::string(), // device_id
141 base::Bind(
142 &KioskAppManager::OnLockDevice, base::Unretained(this), callback));
143 }
144
GetConsumerKioskAutoLaunchStatus(const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback & callback)145 void KioskAppManager::GetConsumerKioskAutoLaunchStatus(
146 const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback& callback) {
147 policy::BrowserPolicyConnectorChromeOS* connector =
148 g_browser_process->platform_part()->browser_policy_connector_chromeos();
149 connector->GetInstallAttributes()->ReadImmutableAttributes(
150 base::Bind(&KioskAppManager::OnReadImmutableAttributes,
151 base::Unretained(this),
152 callback));
153 }
154
IsConsumerKioskDeviceWithAutoLaunch()155 bool KioskAppManager::IsConsumerKioskDeviceWithAutoLaunch() {
156 policy::BrowserPolicyConnectorChromeOS* connector =
157 g_browser_process->platform_part()->browser_policy_connector_chromeos();
158 return connector->GetInstallAttributes() &&
159 connector->GetInstallAttributes()
160 ->IsConsumerKioskDeviceWithAutoLaunch();
161 }
162
OnLockDevice(const KioskAppManager::EnableKioskAutoLaunchCallback & callback,policy::EnterpriseInstallAttributes::LockResult result)163 void KioskAppManager::OnLockDevice(
164 const KioskAppManager::EnableKioskAutoLaunchCallback& callback,
165 policy::EnterpriseInstallAttributes::LockResult result) {
166 if (callback.is_null())
167 return;
168
169 callback.Run(result == policy::EnterpriseInstallAttributes::LOCK_SUCCESS);
170 }
171
OnOwnerFileChecked(const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback & callback,bool * owner_present)172 void KioskAppManager::OnOwnerFileChecked(
173 const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback& callback,
174 bool* owner_present) {
175 ownership_established_ = *owner_present;
176
177 if (callback.is_null())
178 return;
179
180 // If we have owner already established on the machine, don't let
181 // consumer kiosk to be enabled.
182 if (ownership_established_)
183 callback.Run(CONSUMER_KIOSK_AUTO_LAUNCH_DISABLED);
184 else
185 callback.Run(CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE);
186 }
187
OnReadImmutableAttributes(const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback & callback)188 void KioskAppManager::OnReadImmutableAttributes(
189 const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback&
190 callback) {
191 if (callback.is_null())
192 return;
193
194 ConsumerKioskAutoLaunchStatus status =
195 CONSUMER_KIOSK_AUTO_LAUNCH_DISABLED;
196 policy::BrowserPolicyConnectorChromeOS* connector =
197 g_browser_process->platform_part()->browser_policy_connector_chromeos();
198 policy::EnterpriseInstallAttributes* attributes =
199 connector->GetInstallAttributes();
200 switch (attributes->GetMode()) {
201 case policy::DEVICE_MODE_NOT_SET: {
202 if (!base::SysInfo::IsRunningOnChromeOS()) {
203 status = CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE;
204 } else if (!ownership_established_) {
205 bool* owner_present = new bool(false);
206 content::BrowserThread::PostBlockingPoolTaskAndReply(
207 FROM_HERE,
208 base::Bind(&CheckOwnerFilePresence,
209 owner_present),
210 base::Bind(&KioskAppManager::OnOwnerFileChecked,
211 base::Unretained(this),
212 callback,
213 base::Owned(owner_present)));
214 return;
215 }
216 break;
217 }
218 case policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH:
219 status = CONSUMER_KIOSK_AUTO_LAUNCH_ENABLED;
220 break;
221 default:
222 break;
223 }
224
225 callback.Run(status);
226 }
227
SetEnableAutoLaunch(bool value)228 void KioskAppManager::SetEnableAutoLaunch(bool value) {
229 SetAutoLoginState(value ? AUTOLOGIN_APPROVED : AUTOLOGIN_REJECTED);
230 }
231
IsAutoLaunchRequested() const232 bool KioskAppManager::IsAutoLaunchRequested() const {
233 if (GetAutoLaunchApp().empty())
234 return false;
235
236 // Apps that were installed by the policy don't require machine owner
237 // consent through UI.
238 policy::BrowserPolicyConnectorChromeOS* connector =
239 g_browser_process->platform_part()->browser_policy_connector_chromeos();
240 if (connector->IsEnterpriseManaged())
241 return false;
242
243 return GetAutoLoginState() == AUTOLOGIN_REQUESTED;
244 }
245
IsAutoLaunchEnabled() const246 bool KioskAppManager::IsAutoLaunchEnabled() const {
247 if (GetAutoLaunchApp().empty())
248 return false;
249
250 // Apps that were installed by the policy don't require machine owner
251 // consent through UI.
252 policy::BrowserPolicyConnectorChromeOS* connector =
253 g_browser_process->platform_part()->browser_policy_connector_chromeos();
254 if (connector->IsEnterpriseManaged())
255 return true;
256
257 return GetAutoLoginState() == AUTOLOGIN_APPROVED;
258 }
259
AddApp(const std::string & app_id)260 void KioskAppManager::AddApp(const std::string& app_id) {
261 std::vector<policy::DeviceLocalAccount> device_local_accounts =
262 policy::GetDeviceLocalAccounts(CrosSettings::Get());
263
264 // Don't insert the app if it's already in the list.
265 for (std::vector<policy::DeviceLocalAccount>::const_iterator
266 it = device_local_accounts.begin();
267 it != device_local_accounts.end(); ++it) {
268 if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP &&
269 it->kiosk_app_id == app_id) {
270 return;
271 }
272 }
273
274 // Add the new account.
275 device_local_accounts.push_back(policy::DeviceLocalAccount(
276 policy::DeviceLocalAccount::TYPE_KIOSK_APP,
277 GenerateKioskAppAccountId(app_id),
278 app_id));
279
280 policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts);
281 }
282
RemoveApp(const std::string & app_id)283 void KioskAppManager::RemoveApp(const std::string& app_id) {
284 // Resets auto launch app if it is the removed app.
285 if (auto_launch_app_id_ == app_id)
286 SetAutoLaunchApp(std::string());
287
288 std::vector<policy::DeviceLocalAccount> device_local_accounts =
289 policy::GetDeviceLocalAccounts(CrosSettings::Get());
290 if (device_local_accounts.empty())
291 return;
292
293 // Remove entries that match |app_id|.
294 for (std::vector<policy::DeviceLocalAccount>::iterator
295 it = device_local_accounts.begin();
296 it != device_local_accounts.end(); ++it) {
297 if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP &&
298 it->kiosk_app_id == app_id) {
299 device_local_accounts.erase(it);
300 break;
301 }
302 }
303
304 policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts);
305 }
306
GetApps(Apps * apps) const307 void KioskAppManager::GetApps(Apps* apps) const {
308 apps->clear();
309 apps->reserve(apps_.size());
310 for (size_t i = 0; i < apps_.size(); ++i) {
311 const KioskAppData& app_data = *apps_[i];
312 if (app_data.status() != KioskAppData::STATUS_ERROR)
313 apps->push_back(App(
314 app_data, external_cache_->IsExtensionPending(app_data.app_id())));
315 }
316 }
317
GetApp(const std::string & app_id,App * app) const318 bool KioskAppManager::GetApp(const std::string& app_id, App* app) const {
319 const KioskAppData* data = GetAppData(app_id);
320 if (!data)
321 return false;
322
323 *app = App(*data, external_cache_->IsExtensionPending(app_id));
324 return true;
325 }
326
GetAppRawIcon(const std::string & app_id) const327 const base::RefCountedString* KioskAppManager::GetAppRawIcon(
328 const std::string& app_id) const {
329 const KioskAppData* data = GetAppData(app_id);
330 if (!data)
331 return NULL;
332
333 return data->raw_icon();
334 }
335
GetDisableBailoutShortcut() const336 bool KioskAppManager::GetDisableBailoutShortcut() const {
337 bool enable;
338 if (CrosSettings::Get()->GetBoolean(
339 kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled, &enable)) {
340 return !enable;
341 }
342
343 return false;
344 }
345
ClearAppData(const std::string & app_id)346 void KioskAppManager::ClearAppData(const std::string& app_id) {
347 KioskAppData* app_data = GetAppDataMutable(app_id);
348 if (!app_data)
349 return;
350
351 app_data->ClearCache();
352 }
353
UpdateAppDataFromProfile(const std::string & app_id,Profile * profile,const extensions::Extension * app)354 void KioskAppManager::UpdateAppDataFromProfile(
355 const std::string& app_id,
356 Profile* profile,
357 const extensions::Extension* app) {
358 KioskAppData* app_data = GetAppDataMutable(app_id);
359 if (!app_data)
360 return;
361
362 app_data->LoadFromInstalledApp(profile, app);
363 }
364
RetryFailedAppDataFetch()365 void KioskAppManager::RetryFailedAppDataFetch() {
366 for (size_t i = 0; i < apps_.size(); ++i) {
367 if (apps_[i]->status() == KioskAppData::STATUS_ERROR)
368 apps_[i]->Load();
369 }
370 }
371
HasCachedCrx(const std::string & app_id) const372 bool KioskAppManager::HasCachedCrx(const std::string& app_id) const {
373 base::FilePath crx_path;
374 std::string version;
375 return GetCachedCrx(app_id, &crx_path, &version);
376 }
377
GetCachedCrx(const std::string & app_id,base::FilePath * file_path,std::string * version) const378 bool KioskAppManager::GetCachedCrx(const std::string& app_id,
379 base::FilePath* file_path,
380 std::string* version) const {
381 return external_cache_->GetExtension(app_id, file_path, version);
382 }
383
AddObserver(KioskAppManagerObserver * observer)384 void KioskAppManager::AddObserver(KioskAppManagerObserver* observer) {
385 observers_.AddObserver(observer);
386 }
387
RemoveObserver(KioskAppManagerObserver * observer)388 void KioskAppManager::RemoveObserver(KioskAppManagerObserver* observer) {
389 observers_.RemoveObserver(observer);
390 }
391
CreateExternalLoader()392 extensions::ExternalLoader* KioskAppManager::CreateExternalLoader() {
393 if (external_loader_created_) {
394 NOTREACHED();
395 return NULL;
396 }
397 external_loader_created_ = true;
398 KioskAppExternalLoader* loader = new KioskAppExternalLoader();
399 external_loader_ = loader->AsWeakPtr();
400
401 return loader;
402 }
403
InstallFromCache(const std::string & id)404 void KioskAppManager::InstallFromCache(const std::string& id) {
405 const base::DictionaryValue* extension = NULL;
406 if (external_cache_->cached_extensions()->GetDictionary(id, &extension)) {
407 scoped_ptr<base::DictionaryValue> prefs(new base::DictionaryValue);
408 base::DictionaryValue* extension_copy = extension->DeepCopy();
409 prefs->Set(id, extension_copy);
410 external_loader_->SetCurrentAppExtensions(prefs.Pass());
411 } else {
412 LOG(ERROR) << "Can't find app in the cached externsions"
413 << " id = " << id;
414 }
415 }
416
UpdateExternalCache()417 void KioskAppManager::UpdateExternalCache() {
418 UpdateAppData();
419 }
420
OnKioskAppCacheUpdated(const std::string & app_id)421 void KioskAppManager::OnKioskAppCacheUpdated(const std::string& app_id) {
422 FOR_EACH_OBSERVER(
423 KioskAppManagerObserver, observers_, OnKioskAppCacheUpdated(app_id));
424 }
425
OnKioskAppExternalUpdateComplete(bool success)426 void KioskAppManager::OnKioskAppExternalUpdateComplete(bool success) {
427 FOR_EACH_OBSERVER(KioskAppManagerObserver,
428 observers_,
429 OnKioskAppExternalUpdateComplete(success));
430 }
431
PutValidatedExternalExtension(const std::string & app_id,const base::FilePath & crx_path,const std::string & version,const ExternalCache::PutExternalExtensionCallback & callback)432 void KioskAppManager::PutValidatedExternalExtension(
433 const std::string& app_id,
434 const base::FilePath& crx_path,
435 const std::string& version,
436 const ExternalCache::PutExternalExtensionCallback& callback) {
437 external_cache_->PutExternalExtension(app_id, crx_path, version, callback);
438 }
439
KioskAppManager()440 KioskAppManager::KioskAppManager()
441 : ownership_established_(false), external_loader_created_(false) {
442 base::FilePath cache_dir;
443 GetCrxCacheDir(&cache_dir);
444 external_cache_.reset(
445 new ExternalCache(cache_dir,
446 g_browser_process->system_request_context(),
447 GetBackgroundTaskRunner(),
448 this,
449 true /* always_check_updates */,
450 false /* wait_for_cache_initialization */));
451 UpdateAppData();
452 local_accounts_subscription_ =
453 CrosSettings::Get()->AddSettingsObserver(
454 kAccountsPrefDeviceLocalAccounts,
455 base::Bind(&KioskAppManager::UpdateAppData, base::Unretained(this)));
456 local_account_auto_login_id_subscription_ =
457 CrosSettings::Get()->AddSettingsObserver(
458 kAccountsPrefDeviceLocalAccountAutoLoginId,
459 base::Bind(&KioskAppManager::UpdateAppData, base::Unretained(this)));
460 }
461
~KioskAppManager()462 KioskAppManager::~KioskAppManager() {}
463
MonitorKioskExternalUpdate()464 void KioskAppManager::MonitorKioskExternalUpdate() {
465 base::FilePath cache_dir;
466 GetCrxCacheDir(&cache_dir);
467 base::FilePath unpack_dir;
468 GetCrxUnpackDir(&unpack_dir);
469 usb_stick_updater_.reset(new KioskExternalUpdater(
470 GetBackgroundTaskRunner(), cache_dir, unpack_dir));
471 }
472
CleanUp()473 void KioskAppManager::CleanUp() {
474 local_accounts_subscription_.reset();
475 local_account_auto_login_id_subscription_.reset();
476 apps_.clear();
477 usb_stick_updater_.reset();
478 external_cache_.reset();
479 }
480
GetAppData(const std::string & app_id) const481 const KioskAppData* KioskAppManager::GetAppData(
482 const std::string& app_id) const {
483 for (size_t i = 0; i < apps_.size(); ++i) {
484 const KioskAppData* data = apps_[i];
485 if (data->app_id() == app_id)
486 return data;
487 }
488
489 return NULL;
490 }
491
GetAppDataMutable(const std::string & app_id)492 KioskAppData* KioskAppManager::GetAppDataMutable(const std::string& app_id) {
493 return const_cast<KioskAppData*>(GetAppData(app_id));
494 }
495
UpdateAppData()496 void KioskAppManager::UpdateAppData() {
497 // Gets app id to data mapping for existing apps.
498 std::map<std::string, KioskAppData*> old_apps;
499 for (size_t i = 0; i < apps_.size(); ++i)
500 old_apps[apps_[i]->app_id()] = apps_[i];
501 apps_.weak_clear(); // |old_apps| takes ownership
502
503 auto_launch_app_id_.clear();
504 std::string auto_login_account_id;
505 CrosSettings::Get()->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
506 &auto_login_account_id);
507
508 // Re-populates |apps_| and reuses existing KioskAppData when possible.
509 const std::vector<policy::DeviceLocalAccount> device_local_accounts =
510 policy::GetDeviceLocalAccounts(CrosSettings::Get());
511 for (std::vector<policy::DeviceLocalAccount>::const_iterator
512 it = device_local_accounts.begin();
513 it != device_local_accounts.end(); ++it) {
514 if (it->type != policy::DeviceLocalAccount::TYPE_KIOSK_APP)
515 continue;
516
517 if (it->account_id == auto_login_account_id)
518 auto_launch_app_id_ = it->kiosk_app_id;
519
520 // TODO(mnissler): Support non-CWS update URLs.
521
522 std::map<std::string, KioskAppData*>::iterator old_it =
523 old_apps.find(it->kiosk_app_id);
524 if (old_it != old_apps.end()) {
525 apps_.push_back(old_it->second);
526 old_apps.erase(old_it);
527 } else {
528 KioskAppData* new_app =
529 new KioskAppData(this, it->kiosk_app_id, it->user_id);
530 apps_.push_back(new_app); // Takes ownership of |new_app|.
531 new_app->Load();
532 }
533 }
534
535 // Clears cache and deletes the remaining old data.
536 std::vector<std::string> apps_to_remove;
537 for (std::map<std::string, KioskAppData*>::iterator it = old_apps.begin();
538 it != old_apps.end(); ++it) {
539 it->second->ClearCache();
540 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
541 it->second->user_id(),
542 base::Bind(&OnRemoveAppCryptohomeComplete, it->first));
543 apps_to_remove.push_back(it->second->app_id());
544 }
545 STLDeleteValues(&old_apps);
546 external_cache_->RemoveExtensions(apps_to_remove);
547
548 // Request external_cache_ to download new apps and update the existing
549 // apps.
550 scoped_ptr<base::DictionaryValue> prefs(new base::DictionaryValue);
551 for (size_t i = 0; i < apps_.size(); ++i) {
552 scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue);
553 entry->SetBoolean(extensions::ExternalProviderImpl::kIsFromWebstore, true);
554 prefs->Set(apps_[i]->app_id(), entry.release());
555 }
556 external_cache_->UpdateExtensionsList(prefs.Pass());
557
558 RetryFailedAppDataFetch();
559
560 FOR_EACH_OBSERVER(KioskAppManagerObserver, observers_,
561 OnKioskAppsSettingsChanged());
562 }
563
GetKioskAppIconCacheDir(base::FilePath * cache_dir)564 void KioskAppManager::GetKioskAppIconCacheDir(base::FilePath* cache_dir) {
565 base::FilePath user_data_dir;
566 CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
567 *cache_dir = user_data_dir.AppendASCII(kIconCacheDir);
568 }
569
OnKioskAppDataChanged(const std::string & app_id)570 void KioskAppManager::OnKioskAppDataChanged(const std::string& app_id) {
571 FOR_EACH_OBSERVER(KioskAppManagerObserver,
572 observers_,
573 OnKioskAppDataChanged(app_id));
574 }
575
OnKioskAppDataLoadFailure(const std::string & app_id)576 void KioskAppManager::OnKioskAppDataLoadFailure(const std::string& app_id) {
577 FOR_EACH_OBSERVER(KioskAppManagerObserver,
578 observers_,
579 OnKioskAppDataLoadFailure(app_id));
580 }
581
OnExtensionListsUpdated(const base::DictionaryValue * prefs)582 void KioskAppManager::OnExtensionListsUpdated(
583 const base::DictionaryValue* prefs) {
584 }
585
OnExtensionLoadedInCache(const std::string & id)586 void KioskAppManager::OnExtensionLoadedInCache(const std::string& id) {
587 KioskAppData* app_data = GetAppDataMutable(id);
588 if (!app_data)
589 return;
590 FOR_EACH_OBSERVER(KioskAppManagerObserver,
591 observers_,
592 OnKioskExtensionLoadedInCache(id));
593
594 }
595
OnExtensionDownloadFailed(const std::string & id,extensions::ExtensionDownloaderDelegate::Error error)596 void KioskAppManager::OnExtensionDownloadFailed(
597 const std::string& id,
598 extensions::ExtensionDownloaderDelegate::Error error) {
599 KioskAppData* app_data = GetAppDataMutable(id);
600 if (!app_data)
601 return;
602 FOR_EACH_OBSERVER(KioskAppManagerObserver,
603 observers_,
604 OnKioskExtensionDownloadFailed(id));
605 }
606
GetAutoLoginState() const607 KioskAppManager::AutoLoginState KioskAppManager::GetAutoLoginState() const {
608 PrefService* prefs = g_browser_process->local_state();
609 const base::DictionaryValue* dict =
610 prefs->GetDictionary(KioskAppManager::kKioskDictionaryName);
611 int value;
612 if (!dict->GetInteger(kKeyAutoLoginState, &value))
613 return AUTOLOGIN_NONE;
614
615 return static_cast<AutoLoginState>(value);
616 }
617
SetAutoLoginState(AutoLoginState state)618 void KioskAppManager::SetAutoLoginState(AutoLoginState state) {
619 PrefService* prefs = g_browser_process->local_state();
620 DictionaryPrefUpdate dict_update(prefs,
621 KioskAppManager::kKioskDictionaryName);
622 dict_update->SetInteger(kKeyAutoLoginState, state);
623 prefs->CommitPendingWrite();
624 }
625
GetCrxCacheDir(base::FilePath * cache_dir)626 void KioskAppManager::GetCrxCacheDir(base::FilePath* cache_dir) {
627 base::FilePath user_data_dir;
628 CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
629 *cache_dir = user_data_dir.AppendASCII(kCrxCacheDir);
630 }
631
GetCrxUnpackDir(base::FilePath * unpack_dir)632 void KioskAppManager::GetCrxUnpackDir(base::FilePath* unpack_dir) {
633 base::FilePath temp_dir;
634 base::GetTempDir(&temp_dir);
635 *unpack_dir = temp_dir.AppendASCII(kCrxUnpackDir);
636 }
637
638 } // namespace chromeos
639