kiosk_app_manager.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <set>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/path_service.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/prefs/pref_service.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/browser_process.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/app_mode/kiosk_app_data.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/user_manager.h"
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/chromeos/policy/device_local_account.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/settings/cros_settings.h"
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/chromeos/settings/cros_settings_names.h"
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/policy/browser_policy_connector.h"
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/prefs/scoped_user_pref_update.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/chrome_notification_types.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_paths.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/cryptohome/async_method_caller.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Domain that is used for kiosk-app account IDs.
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kKioskAppAccountDomain[] = "kiosk-apps";
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string GenerateKioskAppAccountId(const std::string& app_id) {
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return app_id + '@' + kKioskAppAccountDomain;
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OnRemoveAppCryptohomeComplete(const std::string& app,
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   bool success,
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   cryptohome::MountError return_code) {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!success) {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Remove cryptohome for " << app
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        << " failed, return code: " << return_code;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char KioskAppManager::kKioskDictionaryName[] = "kiosk";
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char KioskAppManager::kKeyApps[] = "apps";
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char KioskAppManager::kKeyAutoLoginState[] = "auto_login_state";
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char KioskAppManager::kIconCacheDir[] = "kiosk";
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static base::LazyInstance<KioskAppManager> instance = LAZY_INSTANCE_INITIALIZER;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KioskAppManager* KioskAppManager::Get() {
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return instance.Pointer();
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void KioskAppManager::Shutdown() {
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (instance == NULL)
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  instance.Pointer()->CleanUp();
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::RegisterPrefs(PrefRegistrySimple* registry) {
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  registry->RegisterDictionaryPref(kKioskDictionaryName);
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KioskAppManager::App::App(const KioskAppData& data)
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : app_id(data.app_id()),
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      user_id(data.user_id()),
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      name(data.name()),
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      icon(data.icon()),
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      is_loading(data.IsLoading()) {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KioskAppManager::App::App() : is_loading(false) {}
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KioskAppManager::App::~App() {}
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string KioskAppManager::GetAutoLaunchApp() const {
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return auto_launch_app_id_;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::SetAutoLaunchApp(const std::string& app_id) {
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SetAutoLoginState(AUTOLOGIN_REQUESTED);
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Clean first, so the proper change notifications are triggered even
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // if we are only changing AutoLoginState here.
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!auto_launch_app_id_.empty()) {
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    CrosSettings::Get()->SetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   std::string());
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CrosSettings::Get()->SetString(
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kAccountsPrefDeviceLocalAccountAutoLoginId,
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      app_id.empty() ? std::string() : GenerateKioskAppAccountId(app_id));
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CrosSettings::Get()->SetInteger(
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kAccountsPrefDeviceLocalAccountAutoLoginDelay, 0);
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void KioskAppManager::SetEnableAutoLaunch(bool value) {
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SetAutoLoginState(value ? AUTOLOGIN_APPROVED : AUTOLOGIN_REJECTED);
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool KioskAppManager::IsAutoLaunchRequested() const {
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (GetAutoLaunchApp().empty())
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Apps that were installed by the policy don't require machine owner
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // consent through UI.
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (g_browser_process->browser_policy_connector()->IsEnterpriseManaged())
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return GetAutoLoginState() == AUTOLOGIN_REQUESTED;
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool KioskAppManager::IsAutoLaunchEnabled() const {
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (GetAutoLaunchApp().empty())
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Apps that were installed by the policy don't require machine owner
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // consent through UI.
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (g_browser_process->browser_policy_connector()->IsEnterpriseManaged())
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return true;
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return GetAutoLoginState() == AUTOLOGIN_APPROVED;
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::AddApp(const std::string& app_id) {
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<policy::DeviceLocalAccount> device_local_accounts =
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      policy::GetDeviceLocalAccounts(CrosSettings::Get());
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Don't insert the app if it's already in the list.
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (std::vector<policy::DeviceLocalAccount>::const_iterator
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           it = device_local_accounts.begin();
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       it != device_local_accounts.end(); ++it) {
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP &&
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        it->kiosk_app_id == app_id) {
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return;
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Add the new account.
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  device_local_accounts.push_back(policy::DeviceLocalAccount(
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      policy::DeviceLocalAccount::TYPE_KIOSK_APP,
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      GenerateKioskAppAccountId(app_id),
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      app_id,
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      std::string()));
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::RemoveApp(const std::string& app_id) {
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<policy::DeviceLocalAccount> device_local_accounts =
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      policy::GetDeviceLocalAccounts(CrosSettings::Get());
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (device_local_accounts.empty())
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Remove entries that match |app_id|.
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (std::vector<policy::DeviceLocalAccount>::iterator
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           it = device_local_accounts.begin();
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       it != device_local_accounts.end(); ++it) {
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP &&
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        it->kiosk_app_id == app_id) {
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      device_local_accounts.erase(it);
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts);
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::GetApps(Apps* apps) const {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  apps->reserve(apps_.size());
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < apps_.size(); ++i)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    apps->push_back(App(*apps_[i]));
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool KioskAppManager::GetApp(const std::string& app_id, App* app) const {
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const KioskAppData* data = GetAppData(app_id);
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!data)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *app = App(*data);
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::RefCountedString* KioskAppManager::GetAppRawIcon(
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& app_id) const {
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const KioskAppData* data = GetAppData(app_id);
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!data)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return data->raw_icon();
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool KioskAppManager::GetDisableBailoutShortcut() const {
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool enable;
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (CrosSettings::Get()->GetBoolean(
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled, &enable)) {
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return !enable;
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::AddObserver(KioskAppManagerObserver* observer) {
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.AddObserver(observer);
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::RemoveObserver(KioskAppManagerObserver* observer) {
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.RemoveObserver(observer);
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)KioskAppManager::KioskAppManager() {
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateAppData();
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CrosSettings::Get()->AddSettingsObserver(
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kAccountsPrefDeviceLocalAccounts, this);
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CrosSettings::Get()->AddSettingsObserver(
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kAccountsPrefDeviceLocalAccountAutoLoginId, this);
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)KioskAppManager::~KioskAppManager() {}
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void KioskAppManager::CleanUp() {
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CrosSettings::Get()->RemoveSettingsObserver(
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kAccountsPrefDeviceLocalAccounts, this);
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CrosSettings::Get()->RemoveSettingsObserver(
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kAccountsPrefDeviceLocalAccountAutoLoginId, this);
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  apps_.clear();
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const KioskAppData* KioskAppManager::GetAppData(
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& app_id) const {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < apps_.size(); ++i) {
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const KioskAppData* data = apps_[i];
24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (data->app_id() == app_id)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return data;
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return NULL;
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::UpdateAppData() {
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Gets app id to data mapping for existing apps.
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::map<std::string, KioskAppData*> old_apps;
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < apps_.size(); ++i)
25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    old_apps[apps_[i]->app_id()] = apps_[i];
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  apps_.weak_clear();  // |old_apps| takes ownership
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  auto_launch_app_id_.clear();
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string auto_login_account_id;
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CrosSettings::Get()->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 &auto_login_account_id);
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Re-populates |apps_| and reuses existing KioskAppData when possible.
26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const std::vector<policy::DeviceLocalAccount> device_local_accounts =
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      policy::GetDeviceLocalAccounts(CrosSettings::Get());
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (std::vector<policy::DeviceLocalAccount>::const_iterator
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           it = device_local_accounts.begin();
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       it != device_local_accounts.end(); ++it) {
26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (it->type != policy::DeviceLocalAccount::TYPE_KIOSK_APP)
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      continue;
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (it->account_id == auto_login_account_id)
27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      auto_launch_app_id_ = it->kiosk_app_id;
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // TODO(mnissler): Support non-CWS update URLs.
27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::map<std::string, KioskAppData*>::iterator old_it =
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        old_apps.find(it->kiosk_app_id);
27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (old_it != old_apps.end()) {
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      apps_.push_back(old_it->second);
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      old_apps.erase(old_it);
28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      KioskAppData* new_app =
28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          new KioskAppData(this, it->kiosk_app_id, it->user_id);
28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      apps_.push_back(new_app);  // Takes ownership of |new_app|.
28590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      new_app->Load();
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Clears cache and deletes the remaining old data.
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::map<std::string, KioskAppData*>::iterator it = old_apps.begin();
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != old_apps.end(); ++it) {
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    it->second->ClearCache();
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        it->first, base::Bind(&OnRemoveAppCryptohomeComplete, it->first));
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteValues(&old_apps);
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FOR_EACH_OBSERVER(KioskAppManagerObserver, observers_,
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    OnKioskAppsSettingsChanged());
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void KioskAppManager::Observe(int type,
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              const content::NotificationSource& source,
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              const content::NotificationDetails& details) {
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED, type);
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateAppData();
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::GetKioskAppIconCacheDir(base::FilePath* cache_dir) {
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath user_data_dir;
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *cache_dir = user_data_dir.AppendASCII(kIconCacheDir);
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::OnKioskAppDataChanged(const std::string& app_id) {
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(KioskAppManagerObserver,
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    observers_,
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    OnKioskAppDataChanged(app_id));
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::OnKioskAppDataLoadFailure(const std::string& app_id) {
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(KioskAppManagerObserver,
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    observers_,
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    OnKioskAppDataLoadFailure(app_id));
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RemoveApp(app_id);
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)KioskAppManager::AutoLoginState KioskAppManager::GetAutoLoginState() const {
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PrefService* prefs = g_browser_process->local_state();
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::DictionaryValue* dict =
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      prefs->GetDictionary(KioskAppManager::kKioskDictionaryName);
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int value;
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!dict->GetInteger(kKeyAutoLoginState, &value))
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return AUTOLOGIN_NONE;
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return static_cast<AutoLoginState>(value);
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void KioskAppManager::SetAutoLoginState(AutoLoginState state) {
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PrefService* prefs = g_browser_process->local_state();
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DictionaryPrefUpdate dict_update(prefs,
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   KioskAppManager::kKioskDictionaryName);
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  dict_update->SetInteger(kKeyAutoLoginState, state);
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  prefs->CommitPendingWrite();
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace chromeos
348