kiosk_app_manager.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
1bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// Copyright 2013 The Chromium Authors. All rights reserved. 2bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// Use of this source code is governed by a BSD-style license that can be 3f5256e16dfc425c1d466f6308d4026d529ce9e0bHoward Hinnant// found in the LICENSE file. 4bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 5bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" 6bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 7bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include <map> 8bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include <set> 9bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 10bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "base/bind.h" 11bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "base/chromeos/chromeos_version.h" 12bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "base/logging.h" 13bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "base/path_service.h" 14bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "base/prefs/pref_registry_simple.h" 15bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "base/prefs/pref_service.h" 16bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "base/stl_util.h" 17bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "chrome/browser/browser_process.h" 18bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "chrome/browser/chrome_notification_types.h" 19bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "chrome/browser/chromeos/app_mode/kiosk_app_data.h" 20bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h" 21bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "chrome/browser/chromeos/login/user_manager.h" 22bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "chrome/browser/chromeos/policy/device_local_account.h" 23bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "chrome/browser/chromeos/settings/cros_settings.h" 24bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "chrome/browser/chromeos/settings/cros_settings_names.h" 25bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "chrome/browser/chromeos/settings/owner_key_util.h" 26bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "chrome/browser/policy/browser_policy_connector.h" 27bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "chrome/browser/prefs/scoped_user_pref_update.h" 28bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "chrome/common/chrome_paths.h" 29bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "chromeos/cryptohome/async_method_caller.h" 30bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "chromeos/cryptohome/cryptohome_library.h" 31bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "content/public/browser/browser_thread.h" 32bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 33bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantnamespace chromeos { 34bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 35bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantnamespace { 36bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 37bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// Domain that is used for kiosk-app account IDs. 38bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantconst char kKioskAppAccountDomain[] = "kiosk-apps"; 39bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 40bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantstd::string GenerateKioskAppAccountId(const std::string& app_id) { 41bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant return app_id + '@' + kKioskAppAccountDomain; 42bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 43bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 44bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid OnRemoveAppCryptohomeComplete(const std::string& app, 45bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant bool success, 46bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant cryptohome::MountError return_code) { 47bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant if (!success) { 48bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant LOG(ERROR) << "Remove cryptohome for " << app 49bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant << " failed, return code: " << return_code; 50bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant } 51bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 52bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 53bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// Check for presence of machine owner public key file. 54bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid CheckOwnerFilePresence(bool *present) { 55bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant scoped_refptr<OwnerKeyUtil> util = OwnerKeyUtil::Create(); 56bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant *present = util->IsPublicKeyPresent(); 57bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 58bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 59bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} // namespace 60bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 61bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// static 62bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantconst char KioskAppManager::kKioskDictionaryName[] = "kiosk"; 63bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantconst char KioskAppManager::kKeyApps[] = "apps"; 64bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantconst char KioskAppManager::kKeyAutoLoginState[] = "auto_login_state"; 65bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantconst char KioskAppManager::kIconCacheDir[] = "kiosk"; 66bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 67bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// static 68bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantstatic base::LazyInstance<KioskAppManager> instance = LAZY_INSTANCE_INITIALIZER; 69bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard HinnantKioskAppManager* KioskAppManager::Get() { 70bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant return instance.Pointer(); 71bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 72bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 73bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// static 74bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid KioskAppManager::Shutdown() { 75bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant if (instance == NULL) 76bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant return; 77bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 78bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant instance.Pointer()->CleanUp(); 79bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 80bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 81bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// static 82bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid KioskAppManager::RegisterPrefs(PrefRegistrySimple* registry) { 83bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant registry->RegisterDictionaryPref(kKioskDictionaryName); 84bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 85bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 86bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard HinnantKioskAppManager::App::App(const KioskAppData& data) 87bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant : app_id(data.app_id()), 88bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant user_id(data.user_id()), 89bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant name(data.name()), 90bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant icon(data.icon()), 91bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant is_loading(data.IsLoading()) { 92bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 93bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 94bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard HinnantKioskAppManager::App::App() : is_loading(false) {} 95bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard HinnantKioskAppManager::App::~App() {} 96bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 97bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantstd::string KioskAppManager::GetAutoLaunchApp() const { 98bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant return auto_launch_app_id_; 99bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 100bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 101bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid KioskAppManager::SetAutoLaunchApp(const std::string& app_id) { 102bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant SetAutoLoginState(AUTOLOGIN_REQUESTED); 103bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant // Clean first, so the proper change notifications are triggered even 104bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant // if we are only changing AutoLoginState here. 105bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant if (!auto_launch_app_id_.empty()) { 106bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant CrosSettings::Get()->SetString(kAccountsPrefDeviceLocalAccountAutoLoginId, 107bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant std::string()); 108bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant } 109bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 110bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant CrosSettings::Get()->SetString( 111bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant kAccountsPrefDeviceLocalAccountAutoLoginId, 112bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant app_id.empty() ? std::string() : GenerateKioskAppAccountId(app_id)); 113bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant CrosSettings::Get()->SetInteger( 114bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant kAccountsPrefDeviceLocalAccountAutoLoginDelay, 0); 115bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 116bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 117bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid KioskAppManager::EnableConsumerModeKiosk( 118bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant const KioskAppManager::EnableKioskModeCallback& callback) { 119bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant g_browser_process->browser_policy_connector()->GetInstallAttributes()-> 120bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant LockDevice(std::string(), // user 121bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant policy::DEVICE_MODE_CONSUMER_KIOSK, 122bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant std::string(), // device_id 123bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant base::Bind(&KioskAppManager::OnLockDevice, 124bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant base::Unretained(this), 125bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant callback)); 126bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 127bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 128bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid KioskAppManager::GetConsumerKioskModeStatus( 129bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant const KioskAppManager::GetConsumerKioskModeStatusCallback& callback) { 130bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant g_browser_process->browser_policy_connector()->GetInstallAttributes()-> 131bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant ReadImmutableAttributes( 132bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant base::Bind(&KioskAppManager::OnReadImmutableAttributes, 133bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant base::Unretained(this), 134bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant callback)); 135bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 136bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 137bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid KioskAppManager::OnLockDevice( 138bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant const KioskAppManager::EnableKioskModeCallback& callback, 139bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant policy::EnterpriseInstallAttributes::LockResult result) { 140bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant if (callback.is_null()) 141bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant return; 142bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 143bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant callback.Run(result == policy::EnterpriseInstallAttributes::LOCK_SUCCESS); 144bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 145bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 146bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid KioskAppManager::OnOwnerFileChecked( 147bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant const KioskAppManager::GetConsumerKioskModeStatusCallback& callback, 148bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant bool* owner_present) { 149bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant ownership_established_ = *owner_present; 150bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 151bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant if (callback.is_null()) 152bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant return; 153bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 154bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant // If we have owner already established on the machine, don't let 155bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant // consumer kiosk to be enabled. 156bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant if (ownership_established_) 157bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant callback.Run(CONSUMER_KIOSK_MODE_DISABLED); 158bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant else 159bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant callback.Run(CONSUMER_KIOSK_MODE_CONFIGURABLE); 160bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 161bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 162bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid KioskAppManager::OnReadImmutableAttributes( 163bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant const KioskAppManager::GetConsumerKioskModeStatusCallback& callback) { 164bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant if (callback.is_null()) 165bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant return; 166bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 167bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant ConsumerKioskModeStatus status = CONSUMER_KIOSK_MODE_DISABLED; 168bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant policy::EnterpriseInstallAttributes* attributes = 169bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant g_browser_process->browser_policy_connector()->GetInstallAttributes(); 170bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant switch (attributes->GetMode()) { 171bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant case policy::DEVICE_MODE_NOT_SET: { 172bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant if (!base::chromeos::IsRunningOnChromeOS()) { 173bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant status = CONSUMER_KIOSK_MODE_CONFIGURABLE; 174bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant } else if (!ownership_established_) { 175bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant bool* owner_present = new bool(false); 176bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant content::BrowserThread::PostBlockingPoolTaskAndReply( 177bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant FROM_HERE, 178bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant base::Bind(&CheckOwnerFilePresence, 179bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant owner_present), 180bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant base::Bind(&KioskAppManager::OnOwnerFileChecked, 181bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant base::Unretained(this), 182bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant callback, 183bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant base::Owned(owner_present))); 184bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant return; 185bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant } 186bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant break; 187bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant } 188bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant case policy::DEVICE_MODE_CONSUMER_KIOSK: 189bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant status = CONSUMER_KIOSK_MODE_ENABLED; 190bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant break; 191bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant default: 192bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant break; 193bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant } 194bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 195bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant callback.Run(status); 196bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 197bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 198bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid KioskAppManager::SetEnableAutoLaunch(bool value) { 199bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant SetAutoLoginState(value ? AUTOLOGIN_APPROVED : AUTOLOGIN_REJECTED); 200} 201 202bool KioskAppManager::IsAutoLaunchRequested() const { 203 if (GetAutoLaunchApp().empty()) 204 return false; 205 206 // Apps that were installed by the policy don't require machine owner 207 // consent through UI. 208 if (g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) 209 return false; 210 211 return GetAutoLoginState() == AUTOLOGIN_REQUESTED; 212} 213 214bool KioskAppManager::IsAutoLaunchEnabled() const { 215 if (GetAutoLaunchApp().empty()) 216 return false; 217 218 // Apps that were installed by the policy don't require machine owner 219 // consent through UI. 220 if (g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) 221 return true; 222 223 return GetAutoLoginState() == AUTOLOGIN_APPROVED; 224} 225 226void KioskAppManager::AddApp(const std::string& app_id) { 227 std::vector<policy::DeviceLocalAccount> device_local_accounts = 228 policy::GetDeviceLocalAccounts(CrosSettings::Get()); 229 230 // Don't insert the app if it's already in the list. 231 for (std::vector<policy::DeviceLocalAccount>::const_iterator 232 it = device_local_accounts.begin(); 233 it != device_local_accounts.end(); ++it) { 234 if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP && 235 it->kiosk_app_id == app_id) { 236 return; 237 } 238 } 239 240 // Add the new account. 241 device_local_accounts.push_back(policy::DeviceLocalAccount( 242 policy::DeviceLocalAccount::TYPE_KIOSK_APP, 243 GenerateKioskAppAccountId(app_id), 244 app_id)); 245 246 policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts); 247} 248 249void KioskAppManager::RemoveApp(const std::string& app_id) { 250 // Resets auto launch app if it is the removed app. 251 if (auto_launch_app_id_ == app_id) 252 SetAutoLaunchApp(std::string()); 253 254 std::vector<policy::DeviceLocalAccount> device_local_accounts = 255 policy::GetDeviceLocalAccounts(CrosSettings::Get()); 256 if (device_local_accounts.empty()) 257 return; 258 259 // Remove entries that match |app_id|. 260 for (std::vector<policy::DeviceLocalAccount>::iterator 261 it = device_local_accounts.begin(); 262 it != device_local_accounts.end(); ++it) { 263 if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP && 264 it->kiosk_app_id == app_id) { 265 device_local_accounts.erase(it); 266 break; 267 } 268 } 269 270 policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts); 271} 272 273void KioskAppManager::GetApps(Apps* apps) const { 274 apps->reserve(apps_.size()); 275 for (size_t i = 0; i < apps_.size(); ++i) 276 apps->push_back(App(*apps_[i])); 277} 278 279bool KioskAppManager::GetApp(const std::string& app_id, App* app) const { 280 const KioskAppData* data = GetAppData(app_id); 281 if (!data) 282 return false; 283 284 *app = App(*data); 285 return true; 286} 287 288const base::RefCountedString* KioskAppManager::GetAppRawIcon( 289 const std::string& app_id) const { 290 const KioskAppData* data = GetAppData(app_id); 291 if (!data) 292 return NULL; 293 294 return data->raw_icon(); 295} 296 297bool KioskAppManager::GetDisableBailoutShortcut() const { 298 bool enable; 299 if (CrosSettings::Get()->GetBoolean( 300 kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled, &enable)) { 301 return !enable; 302 } 303 304 return false; 305} 306 307void KioskAppManager::AddObserver(KioskAppManagerObserver* observer) { 308 observers_.AddObserver(observer); 309} 310 311void KioskAppManager::RemoveObserver(KioskAppManagerObserver* observer) { 312 observers_.RemoveObserver(observer); 313} 314 315KioskAppManager::KioskAppManager() : ownership_established_(false) { 316 UpdateAppData(); 317 CrosSettings::Get()->AddSettingsObserver( 318 kAccountsPrefDeviceLocalAccounts, this); 319 CrosSettings::Get()->AddSettingsObserver( 320 kAccountsPrefDeviceLocalAccountAutoLoginId, this); 321} 322 323KioskAppManager::~KioskAppManager() {} 324 325void KioskAppManager::CleanUp() { 326 CrosSettings::Get()->RemoveSettingsObserver( 327 kAccountsPrefDeviceLocalAccounts, this); 328 CrosSettings::Get()->RemoveSettingsObserver( 329 kAccountsPrefDeviceLocalAccountAutoLoginId, this); 330 apps_.clear(); 331} 332 333const KioskAppData* KioskAppManager::GetAppData( 334 const std::string& app_id) const { 335 for (size_t i = 0; i < apps_.size(); ++i) { 336 const KioskAppData* data = apps_[i]; 337 if (data->app_id() == app_id) 338 return data; 339 } 340 341 return NULL; 342} 343 344void KioskAppManager::UpdateAppData() { 345 // Gets app id to data mapping for existing apps. 346 std::map<std::string, KioskAppData*> old_apps; 347 for (size_t i = 0; i < apps_.size(); ++i) 348 old_apps[apps_[i]->app_id()] = apps_[i]; 349 apps_.weak_clear(); // |old_apps| takes ownership 350 351 auto_launch_app_id_.clear(); 352 std::string auto_login_account_id; 353 CrosSettings::Get()->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId, 354 &auto_login_account_id); 355 356 // Re-populates |apps_| and reuses existing KioskAppData when possible. 357 const std::vector<policy::DeviceLocalAccount> device_local_accounts = 358 policy::GetDeviceLocalAccounts(CrosSettings::Get()); 359 for (std::vector<policy::DeviceLocalAccount>::const_iterator 360 it = device_local_accounts.begin(); 361 it != device_local_accounts.end(); ++it) { 362 if (it->type != policy::DeviceLocalAccount::TYPE_KIOSK_APP) 363 continue; 364 365 if (it->account_id == auto_login_account_id) 366 auto_launch_app_id_ = it->kiosk_app_id; 367 368 // TODO(mnissler): Support non-CWS update URLs. 369 370 std::map<std::string, KioskAppData*>::iterator old_it = 371 old_apps.find(it->kiosk_app_id); 372 if (old_it != old_apps.end()) { 373 apps_.push_back(old_it->second); 374 old_apps.erase(old_it); 375 } else { 376 KioskAppData* new_app = 377 new KioskAppData(this, it->kiosk_app_id, it->user_id); 378 apps_.push_back(new_app); // Takes ownership of |new_app|. 379 new_app->Load(); 380 } 381 } 382 383 // Clears cache and deletes the remaining old data. 384 for (std::map<std::string, KioskAppData*>::iterator it = old_apps.begin(); 385 it != old_apps.end(); ++it) { 386 it->second->ClearCache(); 387 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove( 388 it->second->user_id(), 389 base::Bind(&OnRemoveAppCryptohomeComplete, it->first)); 390 } 391 STLDeleteValues(&old_apps); 392 393 FOR_EACH_OBSERVER(KioskAppManagerObserver, observers_, 394 OnKioskAppsSettingsChanged()); 395} 396 397void KioskAppManager::Observe(int type, 398 const content::NotificationSource& source, 399 const content::NotificationDetails& details) { 400 DCHECK_EQ(chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED, type); 401 UpdateAppData(); 402} 403 404void KioskAppManager::GetKioskAppIconCacheDir(base::FilePath* cache_dir) { 405 base::FilePath user_data_dir; 406 CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)); 407 *cache_dir = user_data_dir.AppendASCII(kIconCacheDir); 408} 409 410void KioskAppManager::OnKioskAppDataChanged(const std::string& app_id) { 411 FOR_EACH_OBSERVER(KioskAppManagerObserver, 412 observers_, 413 OnKioskAppDataChanged(app_id)); 414} 415 416void KioskAppManager::OnKioskAppDataLoadFailure(const std::string& app_id) { 417 FOR_EACH_OBSERVER(KioskAppManagerObserver, 418 observers_, 419 OnKioskAppDataLoadFailure(app_id)); 420 RemoveApp(app_id); 421} 422 423KioskAppManager::AutoLoginState KioskAppManager::GetAutoLoginState() const { 424 PrefService* prefs = g_browser_process->local_state(); 425 const base::DictionaryValue* dict = 426 prefs->GetDictionary(KioskAppManager::kKioskDictionaryName); 427 int value; 428 if (!dict->GetInteger(kKeyAutoLoginState, &value)) 429 return AUTOLOGIN_NONE; 430 431 return static_cast<AutoLoginState>(value); 432} 433 434void KioskAppManager::SetAutoLoginState(AutoLoginState state) { 435 PrefService* prefs = g_browser_process->local_state(); 436 DictionaryPrefUpdate dict_update(prefs, 437 KioskAppManager::kKioskDictionaryName); 438 dict_update->SetInteger(kKeyAutoLoginState, state); 439 prefs->CommitPendingWrite(); 440} 441 442} // namespace chromeos 443