• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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