kiosk_app_manager.cc revision 010d83a9304c5a91596085d917d248abff47903a
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"
11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/files/file_path.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/path_service.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/prefs/pref_service.h"
161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/sys_info.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/browser_process.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/app_mode/kiosk_app_data.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/login/user_manager.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/chromeos/policy/device_local_account.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/settings/cros_settings.h"
267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chrome/browser/chromeos/settings/owner_key_util.h"
27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/browser/extensions/external_provider_impl.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_paths.h"
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/common/extensions/extension_constants.h"
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chromeos/chromeos_paths.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/cryptohome/async_method_caller.h"
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/settings/cros_settings_names.h"
337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos {
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Domain that is used for kiosk-app account IDs.
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kKioskAppAccountDomain[] = "kiosk-apps";
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string GenerateKioskAppAccountId(const std::string& app_id) {
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return app_id + '@' + kKioskAppAccountDomain;
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OnRemoveAppCryptohomeComplete(const std::string& app,
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   bool success,
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   cryptohome::MountError return_code) {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!success) {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Remove cryptohome for " << app
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        << " failed, return code: " << return_code;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Check for presence of machine owner public key file.
567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void CheckOwnerFilePresence(bool *present) {
577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<OwnerKeyUtil> util = OwnerKeyUtil::Create();
587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  *present = util->IsPublicKeyPresent();
597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)scoped_refptr<base::SequencedTaskRunner> GetBackgroundTaskRunner() {
62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CHECK(pool);
64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return pool->GetSequencedTaskRunnerWithShutdownBehavior(
65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      pool->GetSequenceToken(), base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char KioskAppManager::kKioskDictionaryName[] = "kiosk";
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char KioskAppManager::kKeyApps[] = "apps";
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char KioskAppManager::kKeyAutoLoginState[] = "auto_login_state";
74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char KioskAppManager::kIconCacheDir[] = "kiosk/icon";
75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char KioskAppManager::kCrxCacheDir[] = "kiosk/crx";
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static base::LazyInstance<KioskAppManager> instance = LAZY_INSTANCE_INITIALIZER;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KioskAppManager* KioskAppManager::Get() {
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return instance.Pointer();
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void KioskAppManager::Shutdown() {
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (instance == NULL)
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  instance.Pointer()->CleanUp();
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::RegisterPrefs(PrefRegistrySimple* registry) {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  registry->RegisterDictionaryPref(kKioskDictionaryName);
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)KioskAppManager::App::App(const KioskAppData& data, bool is_extension_pending)
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : app_id(data.app_id()),
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      user_id(data.user_id()),
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      name(data.name()),
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      icon(data.icon()),
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      is_loading(data.IsLoading() || is_extension_pending) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KioskAppManager::App::App() : is_loading(false) {}
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KioskAppManager::App::~App() {}
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string KioskAppManager::GetAutoLaunchApp() const {
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return auto_launch_app_id_;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::SetAutoLaunchApp(const std::string& app_id) {
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SetAutoLoginState(AUTOLOGIN_REQUESTED);
11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Clean first, so the proper change callbacks are triggered even
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // if we are only changing AutoLoginState here.
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!auto_launch_app_id_.empty()) {
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    CrosSettings::Get()->SetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   std::string());
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CrosSettings::Get()->SetString(
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kAccountsPrefDeviceLocalAccountAutoLoginId,
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      app_id.empty() ? std::string() : GenerateKioskAppAccountId(app_id));
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CrosSettings::Get()->SetInteger(
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kAccountsPrefDeviceLocalAccountAutoLoginDelay, 0);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void KioskAppManager::EnableConsumerKioskAutoLaunch(
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const KioskAppManager::EnableKioskAutoLaunchCallback& callback) {
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy::BrowserPolicyConnectorChromeOS* connector =
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      g_browser_process->platform_part()->browser_policy_connector_chromeos();
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  connector->GetInstallAttributes()->LockDevice(
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::string(),  // user
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH,
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::string(),  // device_id
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &KioskAppManager::OnLockDevice, base::Unretained(this), callback));
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void KioskAppManager::GetConsumerKioskAutoLaunchStatus(
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback& callback) {
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy::BrowserPolicyConnectorChromeOS* connector =
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      g_browser_process->platform_part()->browser_policy_connector_chromeos();
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  connector->GetInstallAttributes()->ReadImmutableAttributes(
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&KioskAppManager::OnReadImmutableAttributes,
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Unretained(this),
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 callback));
1477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool KioskAppManager::IsConsumerKioskDeviceWithAutoLaunch() {
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  policy::BrowserPolicyConnectorChromeOS* connector =
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      g_browser_process->platform_part()->browser_policy_connector_chromeos();
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return connector->GetInstallAttributes() &&
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)         connector->GetInstallAttributes()
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             ->IsConsumerKioskDeviceWithAutoLaunch();
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void KioskAppManager::OnLockDevice(
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const KioskAppManager::EnableKioskAutoLaunchCallback& callback,
1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    policy::EnterpriseInstallAttributes::LockResult result) {
1607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (callback.is_null())
1617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  callback.Run(result == policy::EnterpriseInstallAttributes::LOCK_SUCCESS);
1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void KioskAppManager::OnOwnerFileChecked(
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback& callback,
168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    bool* owner_present) {
1697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ownership_established_ = *owner_present;
1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (callback.is_null())
1727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // If we have owner already established on the machine, don't let
1757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // consumer kiosk to be enabled.
1767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (ownership_established_)
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback.Run(CONSUMER_KIOSK_AUTO_LAUNCH_DISABLED);
1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  else
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback.Run(CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE);
1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void KioskAppManager::OnReadImmutableAttributes(
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback&
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        callback) {
1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (callback.is_null())
1867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ConsumerKioskAutoLaunchStatus status =
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CONSUMER_KIOSK_AUTO_LAUNCH_DISABLED;
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy::BrowserPolicyConnectorChromeOS* connector =
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      g_browser_process->platform_part()->browser_policy_connector_chromeos();
1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  policy::EnterpriseInstallAttributes* attributes =
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      connector->GetInstallAttributes();
1947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  switch (attributes->GetMode()) {
1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case policy::DEVICE_MODE_NOT_SET: {
1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (!base::SysInfo::IsRunningOnChromeOS()) {
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        status = CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE;
1987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      } else if (!ownership_established_) {
1997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        bool* owner_present = new bool(false);
2007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        content::BrowserThread::PostBlockingPoolTaskAndReply(
2017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            FROM_HERE,
2027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            base::Bind(&CheckOwnerFilePresence,
2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       owner_present),
2047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            base::Bind(&KioskAppManager::OnOwnerFileChecked,
2057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       base::Unretained(this),
2067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       callback,
2077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       base::Owned(owner_present)));
2087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return;
2097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
2107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      break;
2117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH:
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      status = CONSUMER_KIOSK_AUTO_LAUNCH_ENABLED;
2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      break;
2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    default:
2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      break;
2177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  callback.Run(status);
2207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void KioskAppManager::SetEnableAutoLaunch(bool value) {
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SetAutoLoginState(value ? AUTOLOGIN_APPROVED : AUTOLOGIN_REJECTED);
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool KioskAppManager::IsAutoLaunchRequested() const {
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (GetAutoLaunchApp().empty())
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Apps that were installed by the policy don't require machine owner
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // consent through UI.
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy::BrowserPolicyConnectorChromeOS* connector =
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      g_browser_process->platform_part()->browser_policy_connector_chromeos();
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (connector->IsEnterpriseManaged())
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return GetAutoLoginState() == AUTOLOGIN_REQUESTED;
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool KioskAppManager::IsAutoLaunchEnabled() const {
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (GetAutoLaunchApp().empty())
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Apps that were installed by the policy don't require machine owner
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // consent through UI.
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy::BrowserPolicyConnectorChromeOS* connector =
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      g_browser_process->platform_part()->browser_policy_connector_chromeos();
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (connector->IsEnterpriseManaged())
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return true;
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return GetAutoLoginState() == AUTOLOGIN_APPROVED;
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::AddApp(const std::string& app_id) {
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<policy::DeviceLocalAccount> device_local_accounts =
25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      policy::GetDeviceLocalAccounts(CrosSettings::Get());
25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Don't insert the app if it's already in the list.
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (std::vector<policy::DeviceLocalAccount>::const_iterator
26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           it = device_local_accounts.begin();
26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       it != device_local_accounts.end(); ++it) {
26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP &&
26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        it->kiosk_app_id == app_id) {
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return;
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Add the new account.
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  device_local_accounts.push_back(policy::DeviceLocalAccount(
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      policy::DeviceLocalAccount::TYPE_KIOSK_APP,
27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      GenerateKioskAppAccountId(app_id),
272d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      app_id));
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts);
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::RemoveApp(const std::string& app_id) {
278d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Resets auto launch app if it is the removed app.
279d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (auto_launch_app_id_ == app_id)
280d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    SetAutoLaunchApp(std::string());
281d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<policy::DeviceLocalAccount> device_local_accounts =
28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      policy::GetDeviceLocalAccounts(CrosSettings::Get());
28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (device_local_accounts.empty())
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Remove entries that match |app_id|.
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (std::vector<policy::DeviceLocalAccount>::iterator
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           it = device_local_accounts.begin();
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       it != device_local_accounts.end(); ++it) {
29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP &&
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        it->kiosk_app_id == app_id) {
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      device_local_accounts.erase(it);
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts);
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::GetApps(Apps* apps) const {
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  apps->clear();
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  apps->reserve(apps_.size());
304effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  for (size_t i = 0; i < apps_.size(); ++i) {
305effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const KioskAppData& app_data = *apps_[i];
306effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (app_data.status() != KioskAppData::STATUS_ERROR)
307010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      apps->push_back(App(
308010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          app_data, external_cache_->IsExtensionPending(app_data.app_id())));
309effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool KioskAppManager::GetApp(const std::string& app_id, App* app) const {
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const KioskAppData* data = GetAppData(app_id);
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!data)
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
317010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  *app = App(*data, external_cache_->IsExtensionPending(app_id));
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::RefCountedString* KioskAppManager::GetAppRawIcon(
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& app_id) const {
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const KioskAppData* data = GetAppData(app_id);
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!data)
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return data->raw_icon();
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool KioskAppManager::GetDisableBailoutShortcut() const {
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool enable;
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (CrosSettings::Get()->GetBoolean(
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled, &enable)) {
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return !enable;
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void KioskAppManager::ClearAppData(const std::string& app_id) {
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  KioskAppData* app_data = GetAppDataMutable(app_id);
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!app_data)
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  app_data->ClearCache();
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void KioskAppManager::UpdateAppDataFromProfile(
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& app_id,
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Profile* profile,
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const extensions::Extension* app) {
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  KioskAppData* app_data = GetAppDataMutable(app_id);
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!app_data)
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  app_data->LoadFromInstalledApp(profile, app);
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::AddObserver(KioskAppManagerObserver* observer) {
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.AddObserver(observer);
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::RemoveObserver(KioskAppManagerObserver* observer) {
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.RemoveObserver(observer);
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)KioskAppManager::KioskAppManager() : ownership_established_(false) {
368010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::FilePath cache_dir;
369010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  GetKioskAppCrxCacheDir(&cache_dir);
370010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  external_cache_.reset(
371010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      new ExternalCache(cache_dir,
372010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                        g_browser_process->system_request_context(),
373010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                        GetBackgroundTaskRunner(),
374010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                        this,
375010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                        true /* always_check_updates */,
376010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                        false /* wait_for_cache_initialization */));
377010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateAppData();
37968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  local_accounts_subscription_ =
38068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      CrosSettings::Get()->AddSettingsObserver(
38168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          kAccountsPrefDeviceLocalAccounts,
38268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          base::Bind(&KioskAppManager::UpdateAppData, base::Unretained(this)));
38368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  local_account_auto_login_id_subscription_ =
38468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      CrosSettings::Get()->AddSettingsObserver(
38568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          kAccountsPrefDeviceLocalAccountAutoLoginId,
38668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          base::Bind(&KioskAppManager::UpdateAppData, base::Unretained(this)));
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)KioskAppManager::~KioskAppManager() {}
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void KioskAppManager::CleanUp() {
39268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  local_accounts_subscription_.reset();
39368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  local_account_auto_login_id_subscription_.reset();
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  apps_.clear();
395010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  external_cache_.reset();
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const KioskAppData* KioskAppManager::GetAppData(
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& app_id) const {
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < apps_.size(); ++i) {
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const KioskAppData* data = apps_[i];
40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (data->app_id() == app_id)
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return data;
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return NULL;
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)KioskAppData* KioskAppManager::GetAppDataMutable(const std::string& app_id) {
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return const_cast<KioskAppData*>(GetAppData(app_id));
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::UpdateAppData() {
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Gets app id to data mapping for existing apps.
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::map<std::string, KioskAppData*> old_apps;
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < apps_.size(); ++i)
41790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    old_apps[apps_[i]->app_id()] = apps_[i];
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  apps_.weak_clear();  // |old_apps| takes ownership
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  auto_launch_app_id_.clear();
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string auto_login_account_id;
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CrosSettings::Get()->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 &auto_login_account_id);
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Re-populates |apps_| and reuses existing KioskAppData when possible.
42690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const std::vector<policy::DeviceLocalAccount> device_local_accounts =
42790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      policy::GetDeviceLocalAccounts(CrosSettings::Get());
42890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (std::vector<policy::DeviceLocalAccount>::const_iterator
42990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           it = device_local_accounts.begin();
43090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       it != device_local_accounts.end(); ++it) {
43190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (it->type != policy::DeviceLocalAccount::TYPE_KIOSK_APP)
43290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      continue;
43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
43490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (it->account_id == auto_login_account_id)
43590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      auto_launch_app_id_ = it->kiosk_app_id;
43690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
43790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // TODO(mnissler): Support non-CWS update URLs.
43890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
43990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::map<std::string, KioskAppData*>::iterator old_it =
44090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        old_apps.find(it->kiosk_app_id);
44190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (old_it != old_apps.end()) {
44290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      apps_.push_back(old_it->second);
44390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      old_apps.erase(old_it);
44490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
44590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      KioskAppData* new_app =
44690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          new KioskAppData(this, it->kiosk_app_id, it->user_id);
44790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      apps_.push_back(new_app);  // Takes ownership of |new_app|.
44890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      new_app->Load();
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Clears cache and deletes the remaining old data.
453010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::vector<std::string> apps_to_remove;
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::map<std::string, KioskAppData*>::iterator it = old_apps.begin();
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != old_apps.end(); ++it) {
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    it->second->ClearCache();
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        it->second->user_id(),
459a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        base::Bind(&OnRemoveAppCryptohomeComplete, it->first));
460010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    apps_to_remove.push_back(it->second->app_id());
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteValues(&old_apps);
463010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  external_cache_->RemoveExtensions(apps_to_remove);
464010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
465010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Request external_cache_ to download new apps and update the existing
466010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // apps.
467010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> prefs(new base::DictionaryValue);
468010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (size_t i = 0; i < apps_.size(); ++i)
469010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    prefs->Set(apps_[i]->app_id(), new base::DictionaryValue);
470010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  external_cache_->UpdateExtensionsList(prefs.Pass());
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FOR_EACH_OBSERVER(KioskAppManagerObserver, observers_,
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    OnKioskAppsSettingsChanged());
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::GetKioskAppIconCacheDir(base::FilePath* cache_dir) {
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath user_data_dir;
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *cache_dir = user_data_dir.AppendASCII(kIconCacheDir);
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::OnKioskAppDataChanged(const std::string& app_id) {
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(KioskAppManagerObserver,
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    observers_,
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    OnKioskAppDataChanged(app_id));
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KioskAppManager::OnKioskAppDataLoadFailure(const std::string& app_id) {
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(KioskAppManagerObserver,
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    observers_,
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    OnKioskAppDataLoadFailure(app_id));
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
494010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void KioskAppManager::OnExtensionListsUpdated(
495010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const base::DictionaryValue* prefs) {
496010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
497010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
498010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void KioskAppManager::OnExtensionLoadedInCache(const std::string& id) {
499010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  KioskAppData* app_data = GetAppDataMutable(id);
500010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!app_data)
501010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
502010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  OnKioskAppDataChanged(id);
503010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
504010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
505010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void KioskAppManager::OnExtensionDownloadFailed(
506010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::string& id,
507010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    extensions::ExtensionDownloaderDelegate::Error error) {
508010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  KioskAppData* app_data = GetAppDataMutable(id);
509010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!app_data)
510010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
511010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  OnKioskAppDataLoadFailure(id);
512010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
513010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)KioskAppManager::AutoLoginState KioskAppManager::GetAutoLoginState() const {
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PrefService* prefs = g_browser_process->local_state();
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::DictionaryValue* dict =
517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      prefs->GetDictionary(KioskAppManager::kKioskDictionaryName);
518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int value;
519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!dict->GetInteger(kKeyAutoLoginState, &value))
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return AUTOLOGIN_NONE;
521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return static_cast<AutoLoginState>(value);
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void KioskAppManager::SetAutoLoginState(AutoLoginState state) {
526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PrefService* prefs = g_browser_process->local_state();
527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DictionaryPrefUpdate dict_update(prefs,
528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   KioskAppManager::kKioskDictionaryName);
529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  dict_update->SetInteger(kKeyAutoLoginState, state);
530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  prefs->CommitPendingWrite();
531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
533010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void KioskAppManager::GetKioskAppCrxCacheDir(base::FilePath* cache_dir) {
534010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::FilePath user_data_dir;
535010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
536010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  *cache_dir = user_data_dir.AppendASCII(kCrxCacheDir);
537010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
538010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace chromeos
540