Index: chrome/browser/chromeos/app_mode/kiosk_app_manager.cc |
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc |
index bd9f0e5ac811fe13cc9cb67b2f431da29d035346..465421589d410e7194678dd403ba9e25e4e86aec 100644 |
--- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc |
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc |
@@ -5,24 +5,31 @@ |
#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" |
#include <map> |
+#include <set> |
#include "base/bind.h" |
+#include "base/logging.h" |
+#include "base/memory/scoped_ptr.h" |
#include "base/path_service.h" |
#include "base/prefs/pref_registry_simple.h" |
#include "base/stl_util.h" |
#include "base/values.h" |
#include "chrome/browser/chromeos/app_mode/kiosk_app_data.h" |
#include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h" |
+#include "chrome/browser/chromeos/login/user_manager.h" |
#include "chrome/browser/chromeos/settings/cros_settings.h" |
#include "chrome/common/chrome_notification_types.h" |
#include "chrome/common/chrome_paths.h" |
#include "chromeos/cryptohome/async_method_caller.h" |
-#include "content/public/browser/notification_details.h" |
namespace chromeos { |
namespace { |
+std::string FormatKioskAppUserId(const std::string& app_id) { |
+ return app_id + '@' + UserManager::kKioskAppUserDomain; |
+} |
+ |
void OnRemoveAppCryptohomeComplete(const std::string& app, |
bool success, |
cryptohome::MountError return_code) { |
@@ -32,6 +39,40 @@ void OnRemoveAppCryptohomeComplete(const std::string& app, |
} |
} |
+// Decodes a device-local account dictionary and extracts the |account_id| and |
+// |app_id| if decoding is successful and the entry refers to a Kiosk App. |
+bool DecodeDeviceLocalAccount(const base::Value* account_spec, |
+ std::string* account_id, |
+ std::string* app_id) { |
+ const base::DictionaryValue* account_dict = NULL; |
+ if (!account_spec->GetAsDictionary(&account_dict)) { |
+ NOTREACHED(); |
+ return false; |
+ } |
+ |
+ if (!account_dict->GetStringWithoutPathExpansion( |
+ kAccountsPrefDeviceLocalAccountsKeyId, account_id)) { |
+ LOG(ERROR) << "Account ID missing"; |
+ return false; |
+ } |
+ |
+ int type; |
+ if (!account_dict->GetIntegerWithoutPathExpansion( |
+ kAccountsPrefDeviceLocalAccountsKeyType, &type) || |
+ type != DEVICE_LOCAL_ACCOUNT_TYPE_KIOSK_APP) { |
+ // Not a kiosk app. |
+ return false; |
+ } |
+ |
+ if (!account_dict->GetStringWithoutPathExpansion( |
+ kAccountsPrefDeviceLocalAccountsKeyKioskAppId, app_id)) { |
+ LOG(ERROR) << "Kiosk app id missing for " << *account_id; |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
} // namespace |
// static |
@@ -69,25 +110,71 @@ KioskAppManager::App::App() : is_loading(false) {} |
KioskAppManager::App::~App() {} |
std::string KioskAppManager::GetAutoLaunchApp() const { |
- std::string app_id; |
- if (CrosSettings::Get()->GetString(kKioskAutoLaunch, &app_id)) |
- return app_id; |
- |
- return std::string(); |
+ return auto_launch_app_id_; |
} |
void KioskAppManager::SetAutoLaunchApp(const std::string& app_id) { |
- CrosSettings::Get()->SetString(kKioskAutoLaunch, app_id); |
+ CrosSettings::Get()->SetString( |
+ kAccountsPrefDeviceLocalAccountAutoLoginId, |
+ app_id.empty() ? std::string() : FormatKioskAppUserId(app_id)); |
+ CrosSettings::Get()->SetInteger( |
+ kAccountsPrefDeviceLocalAccountAutoLoginDelay, 0); |
} |
void KioskAppManager::AddApp(const std::string& app_id) { |
- base::StringValue value(app_id); |
- CrosSettings::Get()->AppendToList(kKioskApps, &value); |
+ CrosSettings* cros_settings = CrosSettings::Get(); |
+ const base::ListValue* accounts_list = NULL; |
+ cros_settings->GetList(kAccountsPrefDeviceLocalAccounts, &accounts_list); |
+ |
+ // Don't insert if the app if it's already in the list. |
+ base::ListValue new_accounts_list; |
+ if (accounts_list) { |
+ for (base::ListValue::const_iterator entry(accounts_list->begin()); |
+ entry != accounts_list->end(); ++entry) { |
+ std::string account_id; |
+ std::string kiosk_app_id; |
+ if (DecodeDeviceLocalAccount(*entry, &account_id, &kiosk_app_id) && |
+ kiosk_app_id == app_id) { |
+ return; |
+ } |
+ new_accounts_list.Append((*entry)->DeepCopy()); |
+ } |
+ } |
+ |
+ // Add the new account. |
+ scoped_ptr<base::DictionaryValue> new_entry(new base::DictionaryValue()); |
+ new_entry->SetStringWithoutPathExpansion( |
+ kAccountsPrefDeviceLocalAccountsKeyId, FormatKioskAppUserId(app_id)); |
+ new_entry->SetIntegerWithoutPathExpansion( |
+ kAccountsPrefDeviceLocalAccountsKeyType, |
+ DEVICE_LOCAL_ACCOUNT_TYPE_KIOSK_APP); |
+ new_entry->SetStringWithoutPathExpansion( |
+ kAccountsPrefDeviceLocalAccountsKeyKioskAppId, app_id); |
+ new_accounts_list.Append(new_entry.release()); |
+ cros_settings->Set(kAccountsPrefDeviceLocalAccounts, new_accounts_list); |
} |
void KioskAppManager::RemoveApp(const std::string& app_id) { |
- base::StringValue value(app_id); |
- CrosSettings::Get()->RemoveFromList(kKioskApps, &value); |
+ CrosSettings* cros_settings = CrosSettings::Get(); |
+ const base::ListValue* accounts_list = NULL; |
+ cros_settings->GetList(kAccountsPrefDeviceLocalAccounts, &accounts_list); |
+ if (!accounts_list) |
+ return; |
+ |
+ // Duplicate the list, filtering out entries that match |app_id|. |
+ base::ListValue new_accounts_list; |
+ for (base::ListValue::const_iterator entry(accounts_list->begin()); |
+ entry != accounts_list->end(); ++entry) { |
+ std::string account_id; |
+ std::string kiosk_app_id; |
+ if (DecodeDeviceLocalAccount(*entry, &account_id, &kiosk_app_id) && |
+ kiosk_app_id == app_id) { |
+ continue; |
+ } |
+ new_accounts_list.Append((*entry)->DeepCopy()); |
+ } |
+ |
+ cros_settings->Set(kAccountsPrefDeviceLocalAccounts, new_accounts_list); |
} |
void KioskAppManager::GetApps(Apps* apps) const { |
@@ -115,9 +202,11 @@ const base::RefCountedString* KioskAppManager::GetAppRawIcon( |
} |
bool KioskAppManager::GetDisableBailoutShortcut() const { |
- bool disable; |
- if (CrosSettings::Get()->GetBoolean(kKioskDisableBailoutShortcut, &disable)) |
- return disable; |
+ bool enable; |
+ if (CrosSettings::Get()->GetBoolean( |
+ kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled, &enable)) { |
+ return !enable; |
+ } |
return false; |
} |
@@ -132,13 +221,19 @@ void KioskAppManager::RemoveObserver(KioskAppManagerObserver* observer) { |
KioskAppManager::KioskAppManager() { |
UpdateAppData(); |
- CrosSettings::Get()->AddSettingsObserver(kKioskApps, this); |
+ CrosSettings::Get()->AddSettingsObserver( |
+ kAccountsPrefDeviceLocalAccounts, this); |
+ CrosSettings::Get()->AddSettingsObserver( |
+ kAccountsPrefDeviceLocalAccountAutoLoginId, this); |
} |
KioskAppManager::~KioskAppManager() {} |
void KioskAppManager::CleanUp() { |
- CrosSettings::Get()->RemoveSettingsObserver(kKioskApps, this); |
+ CrosSettings::Get()->RemoveSettingsObserver( |
+ kAccountsPrefDeviceLocalAccounts, this); |
+ CrosSettings::Get()->RemoveSettingsObserver( |
+ kAccountsPrefDeviceLocalAccountAutoLoginId, this); |
apps_.clear(); |
} |
@@ -160,24 +255,37 @@ void KioskAppManager::UpdateAppData() { |
old_apps[apps_[i]->id()] = apps_[i]; |
apps_.weak_clear(); // |old_apps| takes ownership |
- const base::ListValue* new_apps; |
- CHECK(CrosSettings::Get()->GetList(kKioskApps, &new_apps)); |
- |
- // Re-populates |apps_| and reuses existing KioskAppData when possible. |
- for (base::ListValue::const_iterator new_it = new_apps->begin(); |
- new_it != new_apps->end(); |
- ++new_it) { |
- std::string id; |
- CHECK((*new_it)->GetAsString(&id)); |
- |
- std::map<std::string, KioskAppData*>::iterator old_it = old_apps.find(id); |
- if (old_it != old_apps.end()) { |
- apps_.push_back(old_it->second); |
- old_apps.erase(old_it); |
- } else { |
- KioskAppData* new_app = new KioskAppData(this, id); |
- apps_.push_back(new_app); // Takes ownership of |new_app|. |
- new_app->Load(); |
+ auto_launch_app_id_.clear(); |
+ std::string auto_login_account_id; |
+ CrosSettings::Get()->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId, |
+ &auto_login_account_id); |
+ |
+ const base::ListValue* local_accounts; |
+ if (CrosSettings::Get()->GetList(kAccountsPrefDeviceLocalAccounts, |
+ &local_accounts)) { |
+ // Re-populates |apps_| and reuses existing KioskAppData when possible. |
+ for (base::ListValue::const_iterator account(local_accounts->begin()); |
+ account != local_accounts->end(); ++account) { |
+ std::string account_id; |
+ std::string kiosk_app_id; |
+ if (!DecodeDeviceLocalAccount(*account, &account_id, &kiosk_app_id)) |
+ continue; |
+ |
+ if (account_id == auto_login_account_id) |
+ auto_launch_app_id_ = kiosk_app_id; |
+ |
+ // TODO(mnissler): Support non-CWS update URLs. |
+ |
+ std::map<std::string, KioskAppData*>::iterator old_it = |
+ old_apps.find(kiosk_app_id); |
+ if (old_it != old_apps.end()) { |
+ apps_.push_back(old_it->second); |
+ old_apps.erase(old_it); |
+ } else { |
+ KioskAppData* new_app = new KioskAppData(this, kiosk_app_id); |
+ apps_.push_back(new_app); // Takes ownership of |new_app|. |
+ new_app->Load(); |
+ } |
} |
} |
@@ -189,15 +297,15 @@ void KioskAppManager::UpdateAppData() { |
it->first, base::Bind(&OnRemoveAppCryptohomeComplete, it->first)); |
} |
STLDeleteValues(&old_apps); |
+ |
+ FOR_EACH_OBSERVER(KioskAppManagerObserver, observers_, |
+ OnKioskAppsSettingsChanged()); |
} |
void KioskAppManager::Observe(int type, |
const content::NotificationSource& source, |
const content::NotificationDetails& details) { |
DCHECK_EQ(chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED, type); |
- DCHECK_EQ(kKioskApps, |
- *content::Details<const std::string>(details).ptr()); |
- |
UpdateAppData(); |
} |