kiosk_app_manager.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/path_service.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/app_mode/kiosk_app_data.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/app_mode/kiosk_app_prefs_local_state.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_paths.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/cryptohome/async_method_caller.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos {
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OnRemoveAppCryptohomeComplete(const std::string& app,
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   bool success,
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   cryptohome::MountError return_code) {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!success) {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Remove cryptohome for " << app
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        << " failed, return code: " << return_code;
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char KioskAppManager::kKioskDictionaryName[] = "kiosk";
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char KioskAppManager::kKeyApps[] = "apps";
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char KioskAppManager::kIconCacheDir[] = "kiosk";
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static base::LazyInstance<KioskAppManager> instance = LAZY_INSTANCE_INITIALIZER;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KioskAppManager* KioskAppManager::Get() {
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return instance.Pointer();
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::RegisterPrefs(PrefRegistrySimple* registry) {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  registry->RegisterDictionaryPref(kKioskDictionaryName);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KioskAppManager::App::App(const KioskAppData& data)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : id(data.id()),
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      name(data.name()),
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      icon(data.icon()),
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      is_loading(data.IsLoading()) {
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KioskAppManager::App::App() : is_loading(false) {}
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KioskAppManager::App::~App() {}
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string KioskAppManager::GetAutoLaunchApp() const {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return prefs_->GetAutoLaunchApp();
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::SetAutoLaunchApp(const std::string& app_id) {
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prefs_->SetAutoLaunchApp(app_id);
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::AddApp(const std::string& app_id) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prefs_->AddApp(app_id);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::RemoveApp(const std::string& app_id) {
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prefs_->RemoveApp(app_id);
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::GetApps(Apps* apps) const {
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  apps->reserve(apps_.size());
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < apps_.size(); ++i)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    apps->push_back(App(*apps_[i]));
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool KioskAppManager::GetApp(const std::string& app_id, App* app) const {
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const KioskAppData* data = GetAppData(app_id);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!data)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *app = App(*data);
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::RefCountedString* KioskAppManager::GetAppRawIcon(
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& app_id) const {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const KioskAppData* data = GetAppData(app_id);
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!data)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return data->raw_icon();
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::AddObserver(KioskAppManagerObserver* observer) {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.AddObserver(observer);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::RemoveObserver(KioskAppManagerObserver* observer) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.RemoveObserver(observer);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KioskAppManager::KioskAppManager()
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : prefs_(new KioskAppPrefsLocalState) {
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateAppData();
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prefs_->AddObserver(this);
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KioskAppManager::~KioskAppManager() {
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prefs_->RemoveObserver(this);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const KioskAppData* KioskAppManager::GetAppData(
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& app_id) const {
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < apps_.size(); ++i) {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const KioskAppData* data = apps_[i];
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (data->id() == app_id)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return data;
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return NULL;
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::UpdateAppData() {
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Gets app id to data mapping for existing apps.
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::map<std::string, KioskAppData*> old_apps;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < apps_.size(); ++i)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    old_apps[apps_[i]->id()] = apps_[i];
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  apps_.weak_clear();  // |old_apps| takes ownership
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Re-populates |apps_| and reuses existing KioskAppData when possible.
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  KioskAppPrefs::AppIds app_ids;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prefs_->GetApps(&app_ids);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < app_ids.size(); ++i) {
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& id = app_ids[i];
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::map<std::string, KioskAppData*>::iterator it = old_apps.find(id);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it != old_apps.end()) {
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      apps_.push_back(it->second);
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      old_apps.erase(it);
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      KioskAppData* new_app = new KioskAppData(this, id);
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      apps_.push_back(new_app);  // Takes ownership of |new_app|.
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new_app->Load();
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Clears cache and deletes the remaining old data.
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::map<std::string, KioskAppData*>::iterator it = old_apps.begin();
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != old_apps.end(); ++it) {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    it->second->ClearCache();
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        it->first, base::Bind(&OnRemoveAppCryptohomeComplete, it->first));
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteValues(&old_apps);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::OnKioskAutoLaunchAppChanged()  {
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(KioskAppManagerObserver,
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    observers_,
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    OnKioskAutoLaunchAppChanged());
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::OnKioskAppsChanged() {
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateAppData();
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(KioskAppManagerObserver,
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    observers_,
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    OnKioskAppsChanged());
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::GetKioskAppIconCacheDir(base::FilePath* cache_dir) {
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath user_data_dir;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *cache_dir = user_data_dir.AppendASCII(kIconCacheDir);
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::OnKioskAppDataChanged(const std::string& app_id) {
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(KioskAppManagerObserver,
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    observers_,
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    OnKioskAppDataChanged(app_id));
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::OnKioskAppDataLoadFailure(const std::string& app_id) {
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(KioskAppManagerObserver,
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    observers_,
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    OnKioskAppDataLoadFailure(app_id));
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RemoveApp(app_id);
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace chromeos
196