diff options
author | bartfab@chromium.org <bartfab@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-22 15:37:26 +0000 |
---|---|---|
committer | bartfab@chromium.org <bartfab@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-22 15:37:26 +0000 |
commit | 08450ddae76a3aa8fdd03dad55eeb60eb9e47039 (patch) | |
tree | 3e332be53f87225d671cdc8cbd59c8f76ec718bf /chrome/browser | |
parent | 2288626251248d496510c8c2a7c1b251e40edc7c (diff) | |
download | chromium_src-08450ddae76a3aa8fdd03dad55eeb60eb9e47039.zip chromium_src-08450ddae76a3aa8fdd03dad55eeb60eb9e47039.tar.gz chromium_src-08450ddae76a3aa8fdd03dad55eeb60eb9e47039.tar.bz2 |
Translate device-local account IDs to user IDs
This CL decouples the namespaces used for device-local accounts in policy
and user management. In addition to the account ID assigned by the server,
each device-local account is given a user ID that always follows a
canonical format and allows the account type to be identified just by
looking at the user ID, regardless of the format chosen for the account ID
by the server.
BUG=240276
TEST=Manual in VM
TBR=jhawkins (chrome/browser/ui/webui/policy_ui.cc)
Review URL: https://chromiumcodereview.appspot.com/14927015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@201532 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
36 files changed, 872 insertions, 594 deletions
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc index fd07e9c..680ccc8 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc @@ -246,10 +246,12 @@ class KioskAppData::WebstoreDataParser // KioskAppData KioskAppData::KioskAppData(KioskAppDataDelegate* delegate, - const std::string& app_id) + const std::string& app_id, + const std::string& user_id) : delegate_(delegate), status_(STATUS_INIT), - id_(app_id) { + app_id_(app_id), + user_id_(user_id) { } KioskAppData::~KioskAppData() {} @@ -269,7 +271,7 @@ void KioskAppData::ClearCache() { DictionaryPrefUpdate dict_update(local_state, KioskAppManager::kKioskDictionaryName); - std::string app_key = std::string(KioskAppManager::kKeyApps) + '.' + id_; + std::string app_key = std::string(KioskAppManager::kKeyApps) + '.' + app_id_; dict_update->Remove(app_key, NULL); if (!icon_path_.empty()) { @@ -297,10 +299,10 @@ void KioskAppData::SetStatus(Status status) { break; case STATUS_LOADING: case STATUS_LOADED: - delegate_->OnKioskAppDataChanged(id_); + delegate_->OnKioskAppDataChanged(app_id_); break; case STATUS_ERROR: - delegate_->OnKioskAppDataLoadFailure(id_); + delegate_->OnKioskAppDataLoadFailure(app_id_); break; }; } @@ -310,7 +312,7 @@ net::URLRequestContextGetter* KioskAppData::GetRequestContextGetter() { } bool KioskAppData::LoadFromCache() { - std::string app_key = std::string(KioskAppManager::kKeyApps) + '.' + id_; + std::string app_key = std::string(KioskAppManager::kKeyApps) + '.' + app_id_; std::string name_key = app_key + '.' + kKeyName; std::string icon_path_key = app_key + '.' + kKeyIcon; @@ -333,7 +335,7 @@ bool KioskAppData::LoadFromCache() { void KioskAppData::SetCache(const std::string& name, const base::FilePath& icon_path) { - std::string app_key = std::string(KioskAppManager::kKeyApps) + '.' + id_; + std::string app_key = std::string(KioskAppManager::kKeyApps) + '.' + app_id_; std::string name_key = app_key + '.' + kKeyName; std::string icon_path_key = app_key + '.' + kKeyIcon; @@ -373,7 +375,7 @@ void KioskAppData::OnWebstoreParseSuccess(const SkBitmap& icon) { delegate_->GetKioskAppIconCacheDir(&cache_dir); base::FilePath icon_path = - cache_dir.AppendASCII(id_).AddExtension(kIconFileExtension); + cache_dir.AppendASCII(app_id_).AddExtension(kIconFileExtension); BrowserThread::GetBlockingPool()->PostTask( FROM_HERE, base::Bind(&SaveIconToLocalOnBlockingPool, icon_path, raw_icon_)); @@ -391,7 +393,7 @@ void KioskAppData::StartFetch() { this, GetRequestContextGetter(), GURL(), - id_)); + app_id_)); webstore_fetcher_->Start(); } @@ -430,7 +432,7 @@ void KioskAppData::OnWebstoreResponseParseSuccess( } // WebstoreDataParser deletes itself when done. - (new WebstoreDataParser(AsWeakPtr()))->Start(id_, + (new WebstoreDataParser(AsWeakPtr()))->Start(app_id_, manifest, icon_url, GetRequestContextGetter()); diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_data.h b/chrome/browser/chromeos/app_mode/kiosk_app_data.h index 61bea86..9214dac 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_data.h +++ b/chrome/browser/chromeos/app_mode/kiosk_app_data.h @@ -42,7 +42,9 @@ class KioskAppData : public base::SupportsWeakPtr<KioskAppData>, STATUS_ERROR, // Failed to load data. }; - KioskAppData(KioskAppDataDelegate* delegate, const std::string& app_id); + KioskAppData(KioskAppDataDelegate* delegate, + const std::string& app_id, + const std::string& user_id); virtual ~KioskAppData(); // Loads app data from cache. If there is no cached data, fetches it @@ -55,7 +57,8 @@ class KioskAppData : public base::SupportsWeakPtr<KioskAppData>, // Returns true if web store data fetching is in progress. bool IsLoading() const; - const std::string& id() const { return id_; } + const std::string& app_id() const { return app_id_; } + const std::string& user_id() const { return user_id_; } const std::string& name() const { return name_; } const gfx::ImageSkia& icon() const { return icon_; } const base::RefCountedString* raw_icon() const { @@ -100,7 +103,8 @@ class KioskAppData : public base::SupportsWeakPtr<KioskAppData>, KioskAppDataDelegate* delegate_; // not owned. Status status_; - std::string id_; + std::string app_id_; + std::string user_id_; std::string name_; gfx::ImageSkia icon_; scoped_refptr<base::RefCountedString> raw_icon_; diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_launcher.cc b/chrome/browser/chromeos/app_mode/kiosk_app_launcher.cc index f5a760a..9301b58 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_launcher.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_app_launcher.cc @@ -8,10 +8,12 @@ #include "base/logging.h" #include "base/memory/weak_ptr.h" #include "base/message_loop.h" +#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/chromeos/app_mode/startup_app_launcher.h" #include "chrome/browser/chromeos/login/login_display_host_impl.h" #include "chrome/browser/chromeos/login/login_utils.h" #include "chrome/browser/chromeos/login/user_manager.h" +#include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/ui/app_launch_view.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chromeos/cryptohome/async_method_caller.h" @@ -24,14 +26,6 @@ using content::BrowserThread; namespace chromeos { -namespace { - -std::string GetAppUserNameFromAppId(const std::string& app_id) { - return app_id + "@" + UserManager::kKioskAppUserDomain; -} - -} // namespace - // static KioskAppLauncher* KioskAppLauncher::running_instance_ = NULL; @@ -105,8 +99,13 @@ class KioskAppLauncher::CryptohomedChecker class KioskAppLauncher::ProfileLoader : public LoginUtils::Delegate { public: - explicit ProfileLoader(KioskAppLauncher* launcher) - : launcher_(launcher) { + ProfileLoader(KioskAppManager* kiosk_app_manager, + KioskAppLauncher* kiosk_app_launcher) + : kiosk_app_launcher_(kiosk_app_launcher) { + KioskAppManager::App app; + if (!kiosk_app_manager->GetApp(kiosk_app_launcher->app_id_, &app)) + NOTREACHED() << "Logging into nonexistent kiosk-app account."; + user_id_ = app.user_id; } virtual ~ProfileLoader() { @@ -115,7 +114,7 @@ class KioskAppLauncher::ProfileLoader : public LoginUtils::Delegate { void Start() { cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername( - GetAppUserNameFromAppId(launcher_->app_id_), + user_id_, base::Bind(&ProfileLoader::OnUsernameHashRetrieved, base::Unretained(this))); } @@ -124,14 +123,14 @@ class KioskAppLauncher::ProfileLoader : public LoginUtils::Delegate { void OnUsernameHashRetrieved(bool success, const std::string& username_hash) { if (!success) { - LOG(ERROR) << "Unable to retrieve username hash for user '" << - GetAppUserNameFromAppId(launcher_->app_id_) << "'"; - launcher_->ReportLaunchResult( + LOG(ERROR) << "Unable to retrieve username hash for user '" << user_id_ + << "'."; + kiosk_app_launcher_->ReportLaunchResult( KioskAppLaunchError::UNABLE_TO_RETRIEVE_HASH); return; } LoginUtils::Get()->PrepareProfile( - UserContext(GetAppUserNameFromAppId(launcher_->app_id_), + UserContext(user_id_, std::string(), // password std::string(), // auth_code username_hash), @@ -143,18 +142,22 @@ class KioskAppLauncher::ProfileLoader : public LoginUtils::Delegate { // LoginUtils::Delegate overrides: virtual void OnProfilePrepared(Profile* profile) OVERRIDE { - launcher_->OnProfilePrepared(profile); + kiosk_app_launcher_->OnProfilePrepared(profile); } - KioskAppLauncher* launcher_; + KioskAppLauncher* kiosk_app_launcher_; + std::string user_id_; + DISALLOW_COPY_AND_ASSIGN(ProfileLoader); }; //////////////////////////////////////////////////////////////////////////////// // KioskAppLauncher -KioskAppLauncher::KioskAppLauncher(const std::string& app_id) - : app_id_(app_id), +KioskAppLauncher::KioskAppLauncher(KioskAppManager* kiosk_app_manager, + const std::string& app_id) + : kiosk_app_manager_(kiosk_app_manager), + app_id_(app_id), remove_attempted_(false) { } @@ -210,7 +213,7 @@ void KioskAppLauncher::StartMount() { void KioskAppLauncher::MountCallback(bool mount_success, cryptohome::MountError mount_error) { if (mount_success) { - profile_loader_.reset(new ProfileLoader(this)); + profile_loader_.reset(new ProfileLoader(kiosk_app_manager_, this)); profile_loader_->Start(); return; } diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_launcher.h b/chrome/browser/chromeos/app_mode/kiosk_app_launcher.h index 5061761..44f9946 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_launcher.h +++ b/chrome/browser/chromeos/app_mode/kiosk_app_launcher.h @@ -17,6 +17,8 @@ class Profile; namespace chromeos { +class KioskAppManager; + // KioskAppLauncher launches a given app from login screen. It first attempts // to mount a cryptohome for the app. If the mount is successful, it prepares // app profile then calls StartupAppLauncher to finish the launch. If mount @@ -25,7 +27,8 @@ namespace chromeos { // progress. class KioskAppLauncher { public: - explicit KioskAppLauncher(const std::string& app_id); + KioskAppLauncher(KioskAppManager* kiosk_app_manager, + const std::string& app_id); // Starts a launch attempt. Fails immediately if there is already a launch // attempt running. @@ -52,6 +55,7 @@ class KioskAppLauncher { // The instance of the current running launch. static KioskAppLauncher* running_instance_; + KioskAppManager* kiosk_app_manager_; const std::string app_id_; scoped_ptr<CryptohomedChecker> crytohomed_checker; diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc index 4654215..9efe5bf 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc @@ -9,15 +9,14 @@ #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/policy/device_local_account.h" #include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chrome/browser/chromeos/settings/cros_settings_names.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_paths.h" #include "chromeos/cryptohome/async_method_caller.h" @@ -26,8 +25,11 @@ namespace chromeos { namespace { -std::string FormatKioskAppUserId(const std::string& app_id) { - return app_id + '@' + UserManager::kKioskAppUserDomain; +// Domain that is used for kiosk-app account IDs. +const char kKioskAppAccountDomain[] = "kiosk-apps"; + +std::string GenerateKioskAppAccountId(const std::string& app_id) { + return app_id + '@' + kKioskAppAccountDomain; } void OnRemoveAppCryptohomeComplete(const std::string& app, @@ -39,40 +41,6 @@ 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 @@ -100,7 +68,8 @@ void KioskAppManager::RegisterPrefs(PrefRegistrySimple* registry) { } KioskAppManager::App::App(const KioskAppData& data) - : id(data.id()), + : app_id(data.app_id()), + user_id(data.user_id()), name(data.name()), icon(data.icon()), is_loading(data.IsLoading()) { @@ -116,65 +85,53 @@ std::string KioskAppManager::GetAutoLaunchApp() const { void KioskAppManager::SetAutoLaunchApp(const std::string& app_id) { CrosSettings::Get()->SetString( kAccountsPrefDeviceLocalAccountAutoLoginId, - app_id.empty() ? std::string() : FormatKioskAppUserId(app_id)); + app_id.empty() ? std::string() : GenerateKioskAppAccountId(app_id)); CrosSettings::Get()->SetInteger( kAccountsPrefDeviceLocalAccountAutoLoginDelay, 0); } void KioskAppManager::AddApp(const std::string& app_id) { - 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()); + std::vector<policy::DeviceLocalAccount> device_local_accounts = + policy::GetDeviceLocalAccounts(CrosSettings::Get()); + + // Don't insert the app if it's already in the list. + for (std::vector<policy::DeviceLocalAccount>::const_iterator + it = device_local_accounts.begin(); + it != device_local_accounts.end(); ++it) { + if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP && + it->kiosk_app_id == app_id) { + return; } } // 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); + device_local_accounts.push_back(policy::DeviceLocalAccount( + policy::DeviceLocalAccount::TYPE_KIOSK_APP, + GenerateKioskAppAccountId(app_id), + app_id, + std::string())); + + policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts); } void KioskAppManager::RemoveApp(const std::string& app_id) { - CrosSettings* cros_settings = CrosSettings::Get(); - const base::ListValue* accounts_list = NULL; - cros_settings->GetList(kAccountsPrefDeviceLocalAccounts, &accounts_list); - if (!accounts_list) + std::vector<policy::DeviceLocalAccount> device_local_accounts = + policy::GetDeviceLocalAccounts(CrosSettings::Get()); + if (device_local_accounts.empty()) 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; + // Remove entries that match |app_id|. + for (std::vector<policy::DeviceLocalAccount>::iterator + it = device_local_accounts.begin(); + it != device_local_accounts.end(); ++it) { + if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP && + it->kiosk_app_id == app_id) { + device_local_accounts.erase(it); + break; } - new_accounts_list.Append((*entry)->DeepCopy()); } - cros_settings->Set(kAccountsPrefDeviceLocalAccounts, new_accounts_list); + policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts); } void KioskAppManager::GetApps(Apps* apps) const { @@ -241,7 +198,7 @@ const KioskAppData* KioskAppManager::GetAppData( const std::string& app_id) const { for (size_t i = 0; i < apps_.size(); ++i) { const KioskAppData* data = apps_[i]; - if (data->id() == app_id) + if (data->app_id() == app_id) return data; } @@ -252,7 +209,7 @@ void KioskAppManager::UpdateAppData() { // Gets app id to data mapping for existing apps. std::map<std::string, KioskAppData*> old_apps; for (size_t i = 0; i < apps_.size(); ++i) - old_apps[apps_[i]->id()] = apps_[i]; + old_apps[apps_[i]->app_id()] = apps_[i]; apps_.weak_clear(); // |old_apps| takes ownership auto_launch_app_id_.clear(); @@ -260,32 +217,30 @@ void KioskAppManager::UpdateAppData() { 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(); - } + // Re-populates |apps_| and reuses existing KioskAppData when possible. + const std::vector<policy::DeviceLocalAccount> device_local_accounts = + policy::GetDeviceLocalAccounts(CrosSettings::Get()); + for (std::vector<policy::DeviceLocalAccount>::const_iterator + it = device_local_accounts.begin(); + it != device_local_accounts.end(); ++it) { + if (it->type != policy::DeviceLocalAccount::TYPE_KIOSK_APP) + continue; + + if (it->account_id == auto_login_account_id) + auto_launch_app_id_ = it->kiosk_app_id; + + // TODO(mnissler): Support non-CWS update URLs. + + std::map<std::string, KioskAppData*>::iterator old_it = + old_apps.find(it->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, it->kiosk_app_id, it->user_id); + apps_.push_back(new_app); // Takes ownership of |new_app|. + new_app->Load(); } } diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.h b/chrome/browser/chromeos/app_mode/kiosk_app_manager.h index 40791a9..401dfeb 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.h +++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.h @@ -37,7 +37,8 @@ class KioskAppManager : public content::NotificationObserver, App(); ~App(); - std::string id; + std::string app_id; + std::string user_id; std::string name; gfx::ImageSkia icon; bool is_loading; @@ -118,7 +119,7 @@ class KioskAppManager : public content::NotificationObserver, // Gets KioskAppData for the given app id. const KioskAppData* GetAppData(const std::string& app_id) const; - // Update app data |apps_| based on |prefs_|. + // Update app data |apps_| based on CrosSettings. void UpdateAppData(); // content::NotificationObserver overrides: diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc index ed1153d..a61dba7 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc @@ -12,6 +12,7 @@ #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h" +#include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/settings/cros_settings_names.h" #include "chrome/browser/prefs/scoped_user_pref_update.h" @@ -130,7 +131,7 @@ class KioskAppManagerTest : public InProcessBrowserTest { for (size_t i = 0; i < apps.size(); ++i) { if (i > 0) str += ','; - str += apps[i].id; + str += apps[i].app_id; } return str; @@ -203,7 +204,7 @@ IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, LoadCached) { "app_1_id"); entry->SetIntegerWithoutPathExpansion( kAccountsPrefDeviceLocalAccountsKeyType, - DEVICE_LOCAL_ACCOUNT_TYPE_KIOSK_APP); + policy::DeviceLocalAccount::TYPE_KIOSK_APP); entry->SetStringWithoutPathExpansion( kAccountsPrefDeviceLocalAccountsKeyKioskAppId, "app_1"); @@ -218,7 +219,7 @@ IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, LoadCached) { KioskAppManager::Apps apps; manager()->GetApps(&apps); EXPECT_EQ(1u, apps.size()); - EXPECT_EQ("app_1", apps[0].id); + EXPECT_EQ("app_1", apps[0].app_id); EXPECT_EQ("App1 Name", apps[0].name); EXPECT_EQ(gfx::Size(16, 16), apps[0].icon.size()); } @@ -249,7 +250,7 @@ IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, GoodApp) { KioskAppManager::Apps apps; manager()->GetApps(&apps); EXPECT_EQ(1u, apps.size()); - EXPECT_EQ("app_1", apps[0].id); + EXPECT_EQ("app_1", apps[0].app_id); EXPECT_EQ("Name of App 1", apps[0].name); EXPECT_EQ(gfx::Size(16, 16), apps[0].icon.size()); @@ -269,7 +270,7 @@ IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, GoodApp) { ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &expected_icon_path)); expected_icon_path = expected_icon_path. AppendASCII(KioskAppManager::kIconCacheDir). - AppendASCII(apps[0].id).AddExtension(".png"); + AppendASCII(apps[0].app_id).AddExtension(".png"); EXPECT_EQ(expected_icon_path.value(), icon_path_string); } diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index 4f88eae..816a71f 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc @@ -270,8 +270,8 @@ void OptionallyRunChromeOSLoginManager(const CommandLine& parsed_command_line, void RunAutoLaunchKioskApp() { // KioskAppLauncher deletes itself when done. - (new KioskAppLauncher( - KioskAppManager::Get()->GetAutoLaunchApp()))->Start(); + (new KioskAppLauncher(KioskAppManager::Get(), + KioskAppManager::Get()->GetAutoLaunchApp()))->Start(); // Login screen is skipped but 'login-prompt-visible' signal is still needed. LOG(INFO) << "Kiosk app auto launch >> login-prompt-visible"; diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc index de37a98..201faa6 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.cc +++ b/chrome/browser/chromeos/login/existing_user_controller.cc @@ -33,6 +33,7 @@ #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/net/connectivity_state_helper.h" +#include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/settings/cros_settings_names.h" @@ -914,10 +915,20 @@ void ExistingUserController::ActivateWizard(const std::string& screen_name) { } void ExistingUserController::ConfigurePublicSessionAutoLogin() { - if (!cros_settings_->GetString( - kAccountsPrefDeviceLocalAccountAutoLoginId, - &public_session_auto_login_username_)) { - public_session_auto_login_username_.clear(); + std::string auto_login_account_id; + cros_settings_->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId, + &auto_login_account_id); + const std::vector<policy::DeviceLocalAccount> device_local_accounts = + policy::GetDeviceLocalAccounts(cros_settings_); + + public_session_auto_login_username_.clear(); + for (std::vector<policy::DeviceLocalAccount>::const_iterator + it = device_local_accounts.begin(); + it != device_local_accounts.end(); ++it) { + if (it->account_id == auto_login_account_id) { + public_session_auto_login_username_ = it->user_id; + break; + } } const User* user = diff --git a/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc b/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc index 8046f3f8..3a7cadf 100644 --- a/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc +++ b/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc @@ -2,13 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <string> + #include "base/message_loop.h" +#include "base/values.h" #include "chrome/browser/chromeos/login/existing_user_controller.h" #include "chrome/browser/chromeos/login/mock_login_display.h" #include "chrome/browser/chromeos/login/mock_login_display_host.h" #include "chrome/browser/chromeos/login/mock_login_utils.h" #include "chrome/browser/chromeos/login/mock_user_manager.h" #include "chrome/browser/chromeos/login/user_manager.h" +#include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/settings/cros_settings_names.h" #include "chrome/browser/chromeos/settings/device_settings_test_helper.h" @@ -27,7 +31,7 @@ namespace chromeos { namespace { -const char kAutoLoginUsername[] = "public_session_user@localhost"; +const char kAutoLoginAccountId[] = "public_session_user@localhost"; // These values are only used to test the configuration. They don't // delay the test. const int kAutoLoginNoDelay = 0; @@ -39,7 +43,10 @@ const int kAutoLoginDelay2 = 180000; class ExistingUserControllerAutoLoginTest : public ::testing::Test { protected: ExistingUserControllerAutoLoginTest() - : message_loop_(MessageLoop::TYPE_UI), + : auto_login_user_id_(policy::GenerateDeviceLocalAccountUserId( + kAutoLoginAccountId, + policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION)), + message_loop_(MessageLoop::TYPE_UI), ui_thread_(content::BrowserThread::UI, &message_loop_), local_state_(TestingBrowserProcess::GetGlobal()), mock_user_manager_(new MockUserManager()), @@ -61,13 +68,24 @@ class ExistingUserControllerAutoLoginTest : public ::testing::Test { EXPECT_CALL(*mock_user_manager_, Shutdown()).Times(AnyNumber()); EXPECT_CALL(*mock_user_manager_, FindUser(_)) .WillRepeatedly(ReturnNull()); - EXPECT_CALL(*mock_user_manager_, FindUser(kAutoLoginUsername)) + EXPECT_CALL(*mock_user_manager_, FindUser(auto_login_user_id_)) .WillRepeatedly(Return( - mock_user_manager_->CreatePublicAccountUser(kAutoLoginUsername))); + mock_user_manager_->CreatePublicAccountUser(auto_login_user_id_))); existing_user_controller_.reset( new ExistingUserController(mock_login_display_host_.get())); + scoped_ptr<base::DictionaryValue> account(new base::DictionaryValue); + account->SetStringWithoutPathExpansion( + kAccountsPrefDeviceLocalAccountsKeyId, + kAutoLoginAccountId); + account->SetIntegerWithoutPathExpansion( + kAccountsPrefDeviceLocalAccountsKeyType, + policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION); + base::ListValue accounts; + accounts.Append(account.release()); + CrosSettings::Get()->Set(kAccountsPrefDeviceLocalAccounts, accounts); + // Prevent settings changes from auto-starting the timer. CrosSettings::Get()->RemoveSettingsObserver( kAccountsPrefDeviceLocalAccountAutoLoginId, @@ -85,10 +103,10 @@ class ExistingUserControllerAutoLoginTest : public ::testing::Test { return ExistingUserController::current_controller(); } - void SetAutoLoginSettings(const std::string& username, int delay) { + void SetAutoLoginSettings(const std::string& account_id, int delay) { CrosSettings::Get()->SetString( kAccountsPrefDeviceLocalAccountAutoLoginId, - username); + account_id); CrosSettings::Get()->SetInteger( kAccountsPrefDeviceLocalAccountAutoLoginDelay, delay); @@ -124,6 +142,8 @@ class ExistingUserControllerAutoLoginTest : public ::testing::Test { existing_user_controller()->ConfigurePublicSessionAutoLogin(); } + const std::string auto_login_user_id_; + private: // Owned by LoginUtilsWrapper. MockLoginUtils* mock_login_utils_; @@ -150,7 +170,7 @@ class ExistingUserControllerAutoLoginTest : public ::testing::Test { TEST_F(ExistingUserControllerAutoLoginTest, StartAutoLoginTimer) { // Timer shouldn't start until signin screen is ready. - set_auto_login_username(kAutoLoginUsername); + set_auto_login_username(auto_login_user_id_); set_auto_login_delay(kAutoLoginDelay2); existing_user_controller()->StartPublicSessionAutoLoginTimer(); EXPECT_FALSE(auto_login_timer()); @@ -162,7 +182,7 @@ TEST_F(ExistingUserControllerAutoLoginTest, StartAutoLoginTimer) { EXPECT_FALSE(auto_login_timer()); // Timer shouldn't fire in the middle of a login attempt. - set_auto_login_username(kAutoLoginUsername); + set_auto_login_username(auto_login_user_id_); set_is_login_in_progress(true); existing_user_controller()->StartPublicSessionAutoLoginTimer(); EXPECT_FALSE(auto_login_timer()); @@ -178,7 +198,7 @@ TEST_F(ExistingUserControllerAutoLoginTest, StartAutoLoginTimer) { TEST_F(ExistingUserControllerAutoLoginTest, StopAutoLoginTimer) { existing_user_controller()->OnSigninScreenReady(); - set_auto_login_username(kAutoLoginUsername); + set_auto_login_username(auto_login_user_id_); set_auto_login_delay(kAutoLoginDelay2); existing_user_controller()->StartPublicSessionAutoLoginTimer(); @@ -192,7 +212,7 @@ TEST_F(ExistingUserControllerAutoLoginTest, StopAutoLoginTimer) { TEST_F(ExistingUserControllerAutoLoginTest, ResetAutoLoginTimer) { existing_user_controller()->OnSigninScreenReady(); - set_auto_login_username(kAutoLoginUsername); + set_auto_login_username(auto_login_user_id_); // Timer starts off not running. EXPECT_FALSE(auto_login_timer()); @@ -235,27 +255,27 @@ TEST_F(ExistingUserControllerAutoLoginTest, ConfigureAutoLogin) { EXPECT_EQ(auto_login_delay(), kAutoLoginDelay1); EXPECT_EQ(auto_login_username(), ""); - // Timer should start when the username is set. - SetAutoLoginSettings(kAutoLoginUsername, kAutoLoginDelay1); + // Timer should start when the account ID is set. + SetAutoLoginSettings(kAutoLoginAccountId, kAutoLoginDelay1); ConfigureAutoLogin(); ASSERT_TRUE(auto_login_timer()); EXPECT_TRUE(auto_login_timer()->IsRunning()); EXPECT_EQ(auto_login_timer()->GetCurrentDelay().InMilliseconds(), kAutoLoginDelay1); EXPECT_EQ(auto_login_delay(), kAutoLoginDelay1); - EXPECT_EQ(auto_login_username(), kAutoLoginUsername); + EXPECT_EQ(auto_login_username(), auto_login_user_id_); // Timer should restart when the delay is changed. - SetAutoLoginSettings(kAutoLoginUsername, kAutoLoginDelay2); + SetAutoLoginSettings(kAutoLoginAccountId, kAutoLoginDelay2); ConfigureAutoLogin(); ASSERT_TRUE(auto_login_timer()); EXPECT_TRUE(auto_login_timer()->IsRunning()); EXPECT_EQ(auto_login_timer()->GetCurrentDelay().InMilliseconds(), kAutoLoginDelay2); EXPECT_EQ(auto_login_delay(), kAutoLoginDelay2); - EXPECT_EQ(auto_login_username(), kAutoLoginUsername); + EXPECT_EQ(auto_login_username(), auto_login_user_id_); - // Timer should stop when the username is unset. + // Timer should stop when the account ID is unset. SetAutoLoginSettings("", kAutoLoginDelay2); ConfigureAutoLogin(); ASSERT_TRUE(auto_login_timer()); diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc index b0f0922..79d3a4a 100644 --- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc +++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc @@ -9,14 +9,12 @@ #include "base/callback.h" #include "base/command_line.h" #include "base/location.h" -#include "base/memory/ref_counted.h" #include "base/run_loop.h" #include "chrome/browser/chromeos/cros/cros_mock.h" #include "chrome/browser/chromeos/cros/mock_network_library.h" #include "chrome/browser/chromeos/login/authenticator.h" #include "chrome/browser/chromeos/login/existing_user_controller.h" #include "chrome/browser/chromeos/login/helper.h" -#include "chrome/browser/chromeos/login/login_status_consumer.h" #include "chrome/browser/chromeos/login/mock_authenticator.h" #include "chrome/browser/chromeos/login/mock_login_display.h" #include "chrome/browser/chromeos/login/mock_login_display_host.h" @@ -25,6 +23,7 @@ #include "chrome/browser/chromeos/login/mock_user_manager.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/login/wizard_controller.h" +#include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h" #include "chrome/browser/chromeos/settings/cros_settings.h" @@ -70,24 +69,14 @@ const char kUsername[] = "test_user@gmail.com"; const char kNewUsername[] = "test_new_user@gmail.com"; const char kPassword[] = "test_password"; -const char kAutoLoginUsername[] = "public_session_user@localhost"; +const char kPublicSessionAccountId[] = "public_session_user@localhost"; const int kAutoLoginNoDelay = 0; const int kAutoLoginShortDelay = 1; const int kAutoLoginLongDelay = 10000; -scoped_refptr<Authenticator> CreateAuthenticator( - LoginStatusConsumer* consumer) { - return new MockAuthenticator(consumer, kUsername, kPassword); -} - -scoped_refptr<Authenticator> CreateAuthenticatorNewUser( - LoginStatusConsumer* consumer) { - return new MockAuthenticator(consumer, kNewUsername, kPassword); -} -scoped_refptr<Authenticator> CreateAuthenticatorForPublicSession( - LoginStatusConsumer* consumer) { - return new MockAuthenticator(consumer, kAutoLoginUsername, ""); +ACTION_P2(CreateAuthenticator, username, password) { + return new MockAuthenticator(arg0, username, password); } // Observes a specific notification type and quits the message loop once a @@ -306,7 +295,7 @@ IN_PROC_BROWSER_TEST_P(ExistingUserControllerTest, ExistingUserLogin) { .Times(2); EXPECT_CALL(*mock_login_utils_, CreateAuthenticator(_)) .Times(1) - .WillOnce(WithArg<0>(Invoke(CreateAuthenticator))); + .WillOnce(WithArg<0>(CreateAuthenticator(kUsername, kPassword))); EXPECT_CALL(*mock_login_utils_, PrepareProfile(UserContext(kUsername, kPassword, "", kUsername), _, _, _, _)) @@ -372,7 +361,7 @@ IN_PROC_BROWSER_TEST_P(ExistingUserControllerTest, .Times(1); EXPECT_CALL(*mock_login_utils_, CreateAuthenticator(_)) .Times(1) - .WillOnce(WithArg<0>(Invoke(CreateAuthenticatorNewUser))); + .WillOnce(WithArg<0>(CreateAuthenticator(kNewUsername, kPassword))); EXPECT_CALL(*mock_login_utils_, PrepareProfile(UserContext(kNewUsername, kPassword, @@ -416,25 +405,28 @@ MATCHER_P(HasDetails, expected, "") { class ExistingUserControllerPublicSessionTest : public ExistingUserControllerTest { protected: - ExistingUserControllerPublicSessionTest() { + ExistingUserControllerPublicSessionTest() + : public_session_user_id_(policy::GenerateDeviceLocalAccountUserId( + kPublicSessionAccountId, + policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION)) { } virtual void SetUpOnMainThread() OVERRIDE { ExistingUserControllerTest::SetUpOnMainThread(); // Wait for the public session user to be created. - if (!chromeos::UserManager::Get()->IsKnownUser(kAutoLoginUsername)) { + if (!chromeos::UserManager::Get()->IsKnownUser(public_session_user_id_)) { NotificationWatcher( chrome::NOTIFICATION_USER_LIST_CHANGED, base::Bind(&chromeos::UserManager::IsKnownUser, base::Unretained(chromeos::UserManager::Get()), - kAutoLoginUsername)).Run(); + public_session_user_id_)).Run(); } // Wait for the device local account policy to be installed. policy::CloudPolicyStore* store = TestingBrowserProcess::GetGlobal()-> browser_policy_connector()->GetDeviceLocalAccountPolicyService()-> - GetBrokerForAccount(kAutoLoginUsername)->core()->store(); + GetBrokerForUser(public_session_user_id_)->core()->store(); if (!store->has_policy()) { policy::MockCloudPolicyStoreObserver observer; @@ -455,21 +447,22 @@ class ExistingUserControllerPublicSessionTest em::ChromeDeviceSettingsProto& proto(device_policy()->payload()); em::DeviceLocalAccountInfoProto* account = proto.mutable_device_local_accounts()->add_account(); - account->set_account_id(kAutoLoginUsername); + account->set_account_id(kPublicSessionAccountId); account->set_type( em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION); RefreshDevicePolicy(); // Setup the device local account policy. policy::UserPolicyBuilder device_local_account_policy; - device_local_account_policy.policy_data().set_username(kAutoLoginUsername); + device_local_account_policy.policy_data().set_username( + kPublicSessionAccountId); device_local_account_policy.policy_data().set_policy_type( policy::dm_protocol::kChromePublicAccountPolicyType); device_local_account_policy.policy_data().set_settings_entity_id( - kAutoLoginUsername); + kPublicSessionAccountId); device_local_account_policy.Build(); session_manager_client()->set_device_local_account_policy( - kAutoLoginUsername, + kPublicSessionAccountId, device_local_account_policy.GetBlob()); } @@ -490,14 +483,12 @@ class ExistingUserControllerPublicSessionTest } void ExpectSuccessfulLogin(const std::string& username, - const std::string& password, - scoped_refptr<Authenticator> create_authenticator( - LoginStatusConsumer* consumer)) { + const std::string& password) { EXPECT_CALL(*mock_login_display_, SetUIEnabled(false)) .Times(AnyNumber()); EXPECT_CALL(*mock_login_utils_, CreateAuthenticator(_)) .Times(1) - .WillOnce(WithArg<0>(Invoke(create_authenticator))); + .WillOnce(WithArg<0>(CreateAuthenticator(username, password))); EXPECT_CALL(*mock_login_utils_, PrepareProfile(UserContext(username, password, "", username), _, _, _, _)) @@ -584,6 +575,8 @@ class ExistingUserControllerPublicSessionTest existing_user_controller()->OnPublicSessionAutoLoginTimerFire(); } + const std::string public_session_user_id_; + private: DISALLOW_COPY_AND_ASSIGN(ExistingUserControllerPublicSessionTest); }; @@ -596,8 +589,8 @@ IN_PROC_BROWSER_TEST_P(ExistingUserControllerPublicSessionTest, EXPECT_FALSE(auto_login_timer()); // Set the policy. - SetAutoLoginPolicy(kAutoLoginUsername, kAutoLoginLongDelay); - EXPECT_EQ(kAutoLoginUsername, auto_login_username()); + SetAutoLoginPolicy(kPublicSessionAccountId, kAutoLoginLongDelay); + EXPECT_EQ(public_session_user_id_, auto_login_username()); EXPECT_EQ(kAutoLoginLongDelay, auto_login_delay()); ASSERT_TRUE(auto_login_timer()); EXPECT_TRUE(auto_login_timer()->IsRunning()); @@ -613,22 +606,20 @@ IN_PROC_BROWSER_TEST_P(ExistingUserControllerPublicSessionTest, IN_PROC_BROWSER_TEST_P(ExistingUserControllerPublicSessionTest, AutoLoginNoDelay) { // Set up mocks to check login success. - ExpectSuccessfulLogin(kAutoLoginUsername, "", - CreateAuthenticatorForPublicSession); + ExpectSuccessfulLogin(public_session_user_id_, ""); existing_user_controller()->OnSigninScreenReady(); // Start auto-login and wait for login tasks to complete. - SetAutoLoginPolicy(kAutoLoginUsername, kAutoLoginNoDelay); + SetAutoLoginPolicy(kPublicSessionAccountId, kAutoLoginNoDelay); content::RunAllPendingInMessageLoop(); } IN_PROC_BROWSER_TEST_P(ExistingUserControllerPublicSessionTest, AutoLoginShortDelay) { // Set up mocks to check login success. - ExpectSuccessfulLogin(kAutoLoginUsername, "", - CreateAuthenticatorForPublicSession); + ExpectSuccessfulLogin(public_session_user_id_, ""); existing_user_controller()->OnSigninScreenReady(); - SetAutoLoginPolicy(kAutoLoginUsername, kAutoLoginShortDelay); + SetAutoLoginPolicy(kPublicSessionAccountId, kAutoLoginShortDelay); ASSERT_TRUE(auto_login_timer()); // Don't assert that timer is running: with the short delay sometimes // the trigger happens before the assert. We've already tested that @@ -649,10 +640,10 @@ IN_PROC_BROWSER_TEST_P(ExistingUserControllerPublicSessionTest, IN_PROC_BROWSER_TEST_P(ExistingUserControllerPublicSessionTest, LoginStopsAutoLogin) { // Set up mocks to check login success. - ExpectSuccessfulLogin(kUsername, kPassword, CreateAuthenticator); + ExpectSuccessfulLogin(kUsername, kPassword); existing_user_controller()->OnSigninScreenReady(); - SetAutoLoginPolicy(kAutoLoginUsername, kAutoLoginLongDelay); + SetAutoLoginPolicy(kPublicSessionAccountId, kAutoLoginLongDelay); ASSERT_TRUE(auto_login_timer()); // Login and check that it stopped the timer. @@ -675,12 +666,12 @@ IN_PROC_BROWSER_TEST_P(ExistingUserControllerPublicSessionTest, .Times(1); EXPECT_CALL(*mock_login_utils_, CreateAuthenticator(_)) .Times(1) - .WillOnce(WithArg<0>(Invoke(CreateAuthenticator))); + .WillOnce(WithArg<0>(CreateAuthenticator(kUsername, kPassword))); EXPECT_CALL(*mock_login_utils_, CompleteOffTheRecordLogin(_)) .Times(1); existing_user_controller()->OnSigninScreenReady(); - SetAutoLoginPolicy(kAutoLoginUsername, kAutoLoginLongDelay); + SetAutoLoginPolicy(kPublicSessionAccountId, kAutoLoginLongDelay); ASSERT_TRUE(auto_login_timer()); // Login and check that it stopped the timer. @@ -700,12 +691,12 @@ IN_PROC_BROWSER_TEST_P(ExistingUserControllerPublicSessionTest, IN_PROC_BROWSER_TEST_P(ExistingUserControllerPublicSessionTest, CompleteLoginStopsAutoLogin) { // Set up mocks to check login success. - ExpectSuccessfulLogin(kUsername, kPassword, CreateAuthenticator); + ExpectSuccessfulLogin(kUsername, kPassword); EXPECT_CALL(*mock_login_display_host_, OnCompleteLogin()) .Times(1); existing_user_controller()->OnSigninScreenReady(); - SetAutoLoginPolicy(kAutoLoginUsername, kAutoLoginLongDelay); + SetAutoLoginPolicy(kPublicSessionAccountId, kAutoLoginLongDelay); ASSERT_TRUE(auto_login_timer()); // Check that login completes and stops the timer. @@ -725,14 +716,13 @@ IN_PROC_BROWSER_TEST_P(ExistingUserControllerPublicSessionTest, IN_PROC_BROWSER_TEST_P(ExistingUserControllerPublicSessionTest, PublicSessionLoginStopsAutoLogin) { // Set up mocks to check login success. - ExpectSuccessfulLogin(kAutoLoginUsername, "", - CreateAuthenticatorForPublicSession); + ExpectSuccessfulLogin(public_session_user_id_, ""); existing_user_controller()->OnSigninScreenReady(); - SetAutoLoginPolicy(kAutoLoginUsername, kAutoLoginLongDelay); + SetAutoLoginPolicy(kPublicSessionAccountId, kAutoLoginLongDelay); ASSERT_TRUE(auto_login_timer()); // Login and check that it stopped the timer. - existing_user_controller()->LoginAsPublicAccount(kAutoLoginUsername); + existing_user_controller()->LoginAsPublicAccount(public_session_user_id_); EXPECT_TRUE(is_login_in_progress()); ASSERT_TRUE(auto_login_timer()); EXPECT_FALSE(auto_login_timer()->IsRunning()); diff --git a/chrome/browser/chromeos/login/login_performer.cc b/chrome/browser/chromeos/login/login_performer.cc index 605fe9a..2c24f7b 100644 --- a/chrome/browser/chromeos/login/login_performer.cc +++ b/chrome/browser/chromeos/login/login_performer.cc @@ -303,8 +303,7 @@ void LoginPerformer::LoginAsPublicAccount(const std::string& username) { policy::DeviceLocalAccountPolicyService* policy_service = g_browser_process->browser_policy_connector()-> GetDeviceLocalAccountPolicyService(); - if (!policy_service || - !policy_service->IsPolicyAvailableForAccount(username)) { + if (!policy_service || !policy_service->IsPolicyAvailableForUser(username)) { DCHECK(delegate_); if (delegate_) delegate_->PolicyLoadFailed(); diff --git a/chrome/browser/chromeos/login/user_manager.cc b/chrome/browser/chromeos/login/user_manager.cc index 24b44e527..8c6dbab 100644 --- a/chrome/browser/chromeos/login/user_manager.cc +++ b/chrome/browser/chromeos/login/user_manager.cc @@ -20,12 +20,9 @@ const char UserManager::kGuestUserName[] = "$guest"; const char UserManager::kLocallyManagedUserDomain[] = "locally-managed.localhost"; -// static -const char UserManager::kKioskAppUserDomain[] = "kiosk-apps.localhost"; // static const char UserManager::kRetailModeUserName[] = "demouser@"; - static UserManager* g_user_manager = NULL; UserManager::Observer::~Observer() { diff --git a/chrome/browser/chromeos/login/user_manager.h b/chrome/browser/chromeos/login/user_manager.h index 0f41393..613c547 100644 --- a/chrome/browser/chromeos/login/user_manager.h +++ b/chrome/browser/chromeos/login/user_manager.h @@ -70,9 +70,6 @@ class UserManager { // Domain that is used for all locally managed users. static const char kLocallyManagedUserDomain[]; - // Domain that is used for kiosk app robot. - static const char kKioskAppUserDomain[]; - // The retail mode user has a magic, domainless e-mail address. static const char kRetailModeUserName[]; diff --git a/chrome/browser/chromeos/login/user_manager_impl.cc b/chrome/browser/chromeos/login/user_manager_impl.cc index 8c23c1e..3a2413a 100644 --- a/chrome/browser/chromeos/login/user_manager_impl.cc +++ b/chrome/browser/chromeos/login/user_manager_impl.cc @@ -30,7 +30,9 @@ #include "chrome/browser/chromeos/login/remove_user_delegate.h" #include "chrome/browser/chromeos/login/user_image_manager_impl.h" #include "chrome/browser/chromeos/login/wizard_controller.h" +#include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/session_length_limiter.h" +#include "chrome/browser/chromeos/settings/cros_settings_names.h" #include "chrome/browser/policy/browser_policy_connector.h" #include "chrome/browser/prefs/scoped_user_pref_update.h" #include "chrome/browser/profiles/profile_manager.h" @@ -266,8 +268,7 @@ void UserManagerImpl::UserLoggedIn(const std::string& email, GuestUserLoggedIn(); } else if (email == UserManager::kRetailModeUserName) { RetailModeUserLoggedIn(); - } else if (gaia::ExtractDomainName(email) == - UserManager::kKioskAppUserDomain) { + } else if (policy::IsKioskAppUser(email)) { KioskAppLoggedIn(email); } else { EnsureUsersLoaded(); @@ -663,8 +664,8 @@ void UserManagerImpl::OnStateChanged() { } } -void UserManagerImpl::OnPolicyUpdated(const std::string& account_id) { - UpdatePublicAccountDisplayName(account_id); +void UserManagerImpl::OnPolicyUpdated(const std::string& user_id) { + UpdatePublicAccountDisplayName(user_id); NotifyUserListChanged(); } @@ -917,12 +918,11 @@ void UserManagerImpl::RetrieveTrustedDevicePolicies() { cros_settings_->GetBoolean(kAccountsPrefEphemeralUsersEnabled, &ephemeral_users_enabled_); cros_settings_->GetString(kDeviceOwner, &owner_email_); - base::ListValue public_accounts; - ReadPublicAccounts(&public_accounts); EnsureUsersLoaded(); - bool changed = UpdateAndCleanUpPublicAccounts(public_accounts); + bool changed = UpdateAndCleanUpPublicAccounts( + policy::GetDeviceLocalAccounts(cros_settings_)); // If ephemeral users are enabled and we are on the login screen, take this // opportunity to clean up by removing all regular users except the owner. @@ -1095,17 +1095,38 @@ void UserManagerImpl::PublicAccountUserLoggedIn(User* user) { void UserManagerImpl::KioskAppLoggedIn(const std::string& username) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - DCHECK_EQ(gaia::ExtractDomainName(username), - UserManager::kKioskAppUserDomain); + DCHECK(policy::IsKioskAppUser(username)); WallpaperManager::Get()->SetInitialUserWallpaper(username, false); active_user_ = User::CreateKioskAppUser(username); active_user_->SetStubImage(User::kInvalidImageIndex, false); + // TODO(bartfab): Add KioskAppUsers to the users_ list and keep metadata like + // the kiosk_app_id in these objects, removing the need to re-parse the + // device-local account list here to extract the kiosk_app_id. + const std::vector<policy::DeviceLocalAccount> device_local_accounts = + policy::GetDeviceLocalAccounts(cros_settings_); + const policy::DeviceLocalAccount* account = NULL; + for (std::vector<policy::DeviceLocalAccount>::const_iterator + it = device_local_accounts.begin(); + it != device_local_accounts.end(); ++it) { + if (it->user_id == username) { + account = &*it; + break; + } + } + std::string kiosk_app_id; + if (account) { + kiosk_app_id = account->kiosk_app_id; + } else { + LOG(ERROR) << "Logged into nonexistent kiosk-app account: " << username; + NOTREACHED(); + } + CommandLine* command_line = CommandLine::ForCurrentProcess(); command_line->AppendSwitch(::switches::kForceAppMode); - command_line->AppendSwitchASCII(::switches::kAppId, - active_user_->GetAccountName(false)); + command_line->AppendSwitchASCII(::switches::kAppId, kiosk_app_id); + // Disable window animation since kiosk app runs in a single full screen // window and window animation causes start-up janks. command_line->AppendSwitch( @@ -1194,6 +1215,20 @@ User* UserManagerImpl::RemoveRegularOrLocallyManagedUserFromList( return user; } +void UserManagerImpl::CleanUpPublicAccountNonCryptohomeDataPendingRemoval() { + PrefService* local_state = g_browser_process->local_state(); + const std::string public_account_pending_data_removal = + local_state->GetString(kPublicAccountPendingDataRemoval); + if (public_account_pending_data_removal.empty() || + (IsUserLoggedIn() && + public_account_pending_data_removal == GetActiveUser()->email())) { + return; + } + + RemoveNonCryptohomeData(public_account_pending_data_removal); + local_state->ClearPref(kPublicAccountPendingDataRemoval); +} + void UserManagerImpl::CleanUpPublicAccountNonCryptohomeData( const std::vector<std::string>& old_public_accounts) { std::set<std::string> users; @@ -1222,45 +1257,27 @@ void UserManagerImpl::CleanUpPublicAccountNonCryptohomeData( } bool UserManagerImpl::UpdateAndCleanUpPublicAccounts( - const base::ListValue& public_accounts) { - PrefService* local_state = g_browser_process->local_state(); - - // Determine the currently logged-in user's email. - std::string active_user_email; - if (IsUserLoggedIn()) - active_user_email = GetLoggedInUser()->email(); + const std::vector<policy::DeviceLocalAccount>& device_local_accounts) { + // Try to remove any public account data marked as pending removal. + CleanUpPublicAccountNonCryptohomeDataPendingRemoval(); - // If there is a public account whose data is pending removal and the user is - // not currently logged in with that account, take this opportunity to remove - // the data. - std::string public_account_pending_data_removal = - local_state->GetString(kPublicAccountPendingDataRemoval); - if (!public_account_pending_data_removal.empty() && - public_account_pending_data_removal != active_user_email) { - RemoveNonCryptohomeData(public_account_pending_data_removal); - local_state->ClearPref(kPublicAccountPendingDataRemoval); - } - - // Split the current user list public accounts and regular users. + // Get the current list of public accounts. std::vector<std::string> old_public_accounts; - std::set<std::string> regular_users; for (UserList::const_iterator it = users_.begin(); it != users_.end(); ++it) { if ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT) old_public_accounts.push_back((*it)->email()); - else - regular_users.insert((*it)->email()); } // Get the new list of public accounts from policy. std::vector<std::string> new_public_accounts; - std::set<std::string> new_public_accounts_set; - ParseUserList(public_accounts, regular_users, - &new_public_accounts, &new_public_accounts_set); - - // Persist the new list of public accounts in a pref. - ListPrefUpdate prefs_public_accounts_update(local_state, kPublicAccounts); - scoped_ptr<base::ListValue> prefs_public_accounts(public_accounts.DeepCopy()); - prefs_public_accounts_update->Swap(prefs_public_accounts.get()); + for (std::vector<policy::DeviceLocalAccount>::const_iterator it = + device_local_accounts.begin(); + it != device_local_accounts.end(); ++it) { + // TODO(mnissler, nkostylev, bartfab): Process Kiosk Apps within the + // standard login framework: http://crbug.com/234694 + if (it->type == policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION) + new_public_accounts.push_back(it->user_id); + } // If the list of public accounts has not changed, return. if (new_public_accounts.size() == old_public_accounts.size()) { @@ -1275,6 +1292,16 @@ bool UserManagerImpl::UpdateAndCleanUpPublicAccounts( return false; } + // Persist the new list of public accounts in a pref. + ListPrefUpdate prefs_public_accounts_update(g_browser_process->local_state(), + kPublicAccounts); + prefs_public_accounts_update->Clear(); + for (std::vector<std::string>::const_iterator + it = new_public_accounts.begin(); + it != new_public_accounts.end(); ++it) { + prefs_public_accounts_update->AppendString(*it); + } + // Remove the old public accounts from the user list. for (UserList::iterator it = users_.begin(); it != users_.end(); ) { if ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT) { @@ -1290,7 +1317,7 @@ bool UserManagerImpl::UpdateAndCleanUpPublicAccounts( for (std::vector<std::string>::const_reverse_iterator it = new_public_accounts.rbegin(); it != new_public_accounts.rend(); ++it) { - if (IsLoggedInAsPublicAccount() && *it == active_user_email) + if (IsLoggedInAsPublicAccount() && *it == GetActiveUser()->email()) users_.insert(users_.begin(), GetLoggedInUser()); else users_.insert(users_.begin(), User::CreatePublicAccountUser(*it)); @@ -1313,7 +1340,7 @@ void UserManagerImpl::UpdatePublicAccountDisplayName( if (device_local_account_policy_service_) { policy::DeviceLocalAccountPolicyBroker* broker = - device_local_account_policy_service_->GetBrokerForAccount(username); + device_local_account_policy_service_->GetBrokerForUser(username); if (broker) display_name = broker->GetDisplayName(); } @@ -1498,38 +1525,6 @@ void UserManagerImpl::UpdateLoginState() { LoginState::Get()->SetLoggedInState(logged_in_state, login_user_type); } -void UserManagerImpl::ReadPublicAccounts(base::ListValue* public_accounts) { - const base::ListValue* accounts = NULL; - if (cros_settings_->GetList(kAccountsPrefDeviceLocalAccounts, &accounts)) { - for (base::ListValue::const_iterator entry(accounts->begin()); - entry != accounts->end(); ++entry) { - const base::DictionaryValue* entry_dict = NULL; - if (!(*entry)->GetAsDictionary(&entry_dict)) { - NOTREACHED(); - continue; - } - - int type = DEVICE_LOCAL_ACCOUNT_TYPE_PUBLIC_SESSION; - entry_dict->GetIntegerWithoutPathExpansion( - kAccountsPrefDeviceLocalAccountsKeyType, &type); - switch (type) { - case DEVICE_LOCAL_ACCOUNT_TYPE_PUBLIC_SESSION: { - std::string id; - if (entry_dict->GetStringWithoutPathExpansion( - kAccountsPrefDeviceLocalAccountsKeyId, &id)) { - public_accounts->AppendString(id); - } - break; - } - case DEVICE_LOCAL_ACCOUNT_TYPE_KIOSK_APP: - // TODO(mnissler, nkostylev, bartfab): Process Kiosk Apps within the - // standard login framework: http://crbug.com/234694 - break; - } - } - } -} - void UserManagerImpl::SetLRUUser(User* user) { UserList::iterator it = std::find(lru_logged_in_users_.begin(), lru_logged_in_users_.end(), diff --git a/chrome/browser/chromeos/login/user_manager_impl.h b/chrome/browser/chromeos/login/user_manager_impl.h index 5b220bb..d70892c 100644 --- a/chrome/browser/chromeos/login/user_manager_impl.h +++ b/chrome/browser/chromeos/login/user_manager_impl.h @@ -11,10 +11,8 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" -#include "base/memory/singleton.h" #include "base/observer_list.h" #include "base/synchronization/lock.h" -#include "base/values.h" #include "chrome/browser/chromeos/login/user.h" #include "chrome/browser/chromeos/login/user_image_manager_impl.h" #include "chrome/browser/chromeos/login/user_manager.h" @@ -29,6 +27,10 @@ class PrefService; class ProfileSyncService; +namespace policy { +struct DeviceLocalAccount; +} + namespace chromeos { class RemoveUserDelegate; @@ -133,7 +135,7 @@ class UserManagerImpl virtual void OnStateChanged() OVERRIDE; // policy::DeviceLocalAccountPolicyService::Observer implementation. - virtual void OnPolicyUpdated(const std::string& account_id) OVERRIDE; + virtual void OnPolicyUpdated(const std::string& user_id) OVERRIDE; virtual void OnDeviceLocalAccountsChanged() OVERRIDE; private: @@ -218,6 +220,10 @@ class UserManagerImpl // Also removes the user from the persistent user list. User* RemoveRegularOrLocallyManagedUserFromList(const std::string& username); + // If data for a public account is marked as pending removal and the user is + // no longer logged into that account, removes the data. + void CleanUpPublicAccountNonCryptohomeDataPendingRemoval(); + // Removes data belonging to public accounts that are no longer found on the // user list. If the user is currently logged into one of these accounts, the // data for that account is not removed immediately but marked as pending @@ -225,12 +231,13 @@ class UserManagerImpl void CleanUpPublicAccountNonCryptohomeData( const std::vector<std::string>& old_public_accounts); - // Replaces the list of public accounts with |public_accounts|. Ensures that - // data belonging to accounts no longer on the list is removed. Returns |true| - // if the list has changed. + // Replaces the list of public accounts with those found in + // |device_local_accounts|. Ensures that data belonging to accounts no longer + // on the list is removed. Returns |true| if the list has changed. // Public accounts are defined by policy. This method is called whenever an // updated list of public accounts is received from policy. - bool UpdateAndCleanUpPublicAccounts(const base::ListValue& public_accounts); + bool UpdateAndCleanUpPublicAccounts( + const std::vector<policy::DeviceLocalAccount>& device_local_accounts); // Updates the display name for public account |username| from policy settings // associated with that username. @@ -257,9 +264,6 @@ class UserManagerImpl // Update the global LoginState. void UpdateLoginState(); - // Gets the list of public accounts defined in device settings. - void ReadPublicAccounts(base::ListValue* public_accounts); - // Insert |user| at the front of the LRU user list.. void SetLRUUser(User* user); diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index 236368a..41b9dc3 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc @@ -555,7 +555,7 @@ void WizardController::OnEnrollmentDone() { ExistingUserController::current_controller()->PrepareKioskAppLaunch(); // KioskAppLauncher deletes itself when done. - (new KioskAppLauncher(auto_launch_app))->Start(); + (new KioskAppLauncher(KioskAppManager::Get(), auto_launch_app))->Start(); } else if (!force_enrollment_ || can_exit_enrollment_) { ShowLoginScreen(); } diff --git a/chrome/browser/chromeos/policy/device_local_account.cc b/chrome/browser/chromeos/policy/device_local_account.cc new file mode 100644 index 0000000..a2c9c09 --- /dev/null +++ b/chrome/browser/chromeos/policy/device_local_account.cc @@ -0,0 +1,158 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/policy/device_local_account.h" + +#include <set> + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_number_conversions.h" +#include "base/values.h" +#include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chrome/browser/chromeos/settings/cros_settings_names.h" +#include "google_apis/gaia/gaia_auth_util.h" + +namespace policy { + +namespace { + +const char kPublicAccountDomainPrefix[] = "public-accounts"; +const char kKioskAppAccountDomainPrefix[] = "kiosk-apps"; +const char kDeviceLocalAccountDomainSuffix[] = ".device-local.localhost"; + +} // namespace + +DeviceLocalAccount::DeviceLocalAccount(Type type, + const std::string& account_id, + const std::string& kiosk_app_id, + const std::string& kiosk_app_update_url) + : type(type), + account_id(account_id), + user_id(GenerateDeviceLocalAccountUserId(account_id, type)), + kiosk_app_id(kiosk_app_id), + kiosk_app_update_url(kiosk_app_update_url) { +} + +DeviceLocalAccount::~DeviceLocalAccount() { +} + +std::string GenerateDeviceLocalAccountUserId(const std::string& account_id, + DeviceLocalAccount::Type type) { + std::string domain_prefix; + switch (type) { + case DeviceLocalAccount::TYPE_PUBLIC_SESSION: + domain_prefix = kPublicAccountDomainPrefix; + break; + case DeviceLocalAccount::TYPE_KIOSK_APP: + domain_prefix = kKioskAppAccountDomainPrefix; + break; + case DeviceLocalAccount::TYPE_COUNT: + NOTREACHED(); + break; + } + return base::HexEncode(account_id.c_str(), account_id.size()) + "@" + + domain_prefix + kDeviceLocalAccountDomainSuffix; +} + +bool IsKioskAppUser(const std::string& user_id) { + return gaia::ExtractDomainName(user_id) == + std::string(kKioskAppAccountDomainPrefix) + + kDeviceLocalAccountDomainSuffix; +} + +void SetDeviceLocalAccounts( + chromeos::CrosSettings* cros_settings, + const std::vector<DeviceLocalAccount>& accounts) { + base::ListValue list; + for (std::vector<DeviceLocalAccount>::const_iterator it = accounts.begin(); + it != accounts.end(); ++it) { + scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue); + entry->SetStringWithoutPathExpansion( + chromeos::kAccountsPrefDeviceLocalAccountsKeyId, + it->account_id); + entry->SetIntegerWithoutPathExpansion( + chromeos::kAccountsPrefDeviceLocalAccountsKeyType, + it->type); + if (it->type == DeviceLocalAccount::TYPE_KIOSK_APP) { + entry->SetStringWithoutPathExpansion( + chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppId, + it->kiosk_app_id); + if (!it->kiosk_app_update_url.empty()) { + entry->SetStringWithoutPathExpansion( + chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppUpdateURL, + it->kiosk_app_update_url); + } + } + list.Append(entry.release()); + } + + cros_settings->Set(chromeos::kAccountsPrefDeviceLocalAccounts, list); +} + +std::vector<DeviceLocalAccount> GetDeviceLocalAccounts( + chromeos::CrosSettings* cros_settings) { + std::vector<DeviceLocalAccount> accounts; + + const base::ListValue* list = NULL; + cros_settings->GetList(chromeos::kAccountsPrefDeviceLocalAccounts, &list); + if (!list) + return accounts; + + std::set<std::string> account_ids; + for (size_t i = 0; i < list->GetSize(); ++i) { + const base::DictionaryValue* entry = NULL; + if (!list->GetDictionary(i, &entry)) { + LOG(ERROR) << "Corrupt entry in device-local account list at index " << i + << "."; + continue; + } + + std::string account_id; + if (!entry->GetStringWithoutPathExpansion( + chromeos::kAccountsPrefDeviceLocalAccountsKeyId, &account_id) || + account_id.empty()) { + LOG(ERROR) << "Missing account ID in device-local account list at index " + << i << "."; + continue; + } + + int type; + if (!entry->GetIntegerWithoutPathExpansion( + chromeos::kAccountsPrefDeviceLocalAccountsKeyType, &type) || + type < 0 || type >= DeviceLocalAccount::TYPE_COUNT) { + LOG(ERROR) << "Missing or invalid account type in device-local account " + << "list at index " << i << "."; + continue; + } + + std::string kiosk_app_id; + std::string kiosk_app_update_url; + if (type == DeviceLocalAccount::TYPE_KIOSK_APP) { + if (!entry->GetStringWithoutPathExpansion( + chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppId, + &kiosk_app_id)) { + LOG(ERROR) << "Missing app ID in device-local account entry at index " + << i << "."; + continue; + } + entry->GetStringWithoutPathExpansion( + chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppUpdateURL, + &kiosk_app_update_url); + } + + if (!account_ids.insert(account_id).second) { + LOG(ERROR) << "Duplicate entry in device-local account list at index " + << i << ": " << account_id << "."; + continue; + } + + accounts.push_back(DeviceLocalAccount( + static_cast<DeviceLocalAccount::Type>(type), + account_id, kiosk_app_id, kiosk_app_update_url)); + } + return accounts; +} + +} // namespace policy diff --git a/chrome/browser/chromeos/policy/device_local_account.h b/chrome/browser/chromeos/policy/device_local_account.h new file mode 100644 index 0000000..6d1896e --- /dev/null +++ b/chrome/browser/chromeos/policy/device_local_account.h @@ -0,0 +1,60 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_POLICY_DEVICE_LOCAL_ACCOUNT_H_ +#define CHROME_BROWSER_CHROMEOS_POLICY_DEVICE_LOCAL_ACCOUNT_H_ + +#include <string> +#include <vector> + +namespace chromeos { +class CrosSettings; +} + +namespace policy { + +// This must match DeviceLocalAccountInfoProto.AccountType in +// chrome_device_policy.proto. +struct DeviceLocalAccount { + enum Type { + // A login-less, policy-configured browsing session. + TYPE_PUBLIC_SESSION, + // An account that serves as a container for a single full-screen app. + TYPE_KIOSK_APP, + // Sentinel, must be last. + TYPE_COUNT + }; + + DeviceLocalAccount(Type type, + const std::string& account_id, + const std::string& kiosk_app_id, + const std::string& kiosk_app_update_url); + ~DeviceLocalAccount(); + + Type type; + std::string account_id; + std::string user_id; + std::string kiosk_app_id; + std::string kiosk_app_update_url; +}; + +std::string GenerateDeviceLocalAccountUserId(const std::string& account_id, + DeviceLocalAccount::Type type); + +bool IsKioskAppUser(const std::string& user_id); + +// Stores a list of device-local accounts in |cros_settings|. The accounts are +// stored as a list of dictionaries with each dictionary containing the +// information about one |DeviceLocalAccount|. +void SetDeviceLocalAccounts( + chromeos::CrosSettings* cros_settings, + const std::vector<DeviceLocalAccount>& accounts); + +// Retrieves a list of device-local accounts from |cros_settings|. +std::vector<DeviceLocalAccount> GetDeviceLocalAccounts( + chromeos::CrosSettings* cros_settings); + +} // namespace policy + +#endif // CHROME_BROWSER_CHROMEOS_POLICY_DEVICE_LOCAL_ACCOUNT_H_ diff --git a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc index 7d11853..7acfcde 100644 --- a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc +++ b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc @@ -23,6 +23,7 @@ #include "chrome/browser/chromeos/login/user.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/login/wizard_controller.h" +#include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/policy/device_policy_builder.h" #include "chrome/browser/chromeos/policy/enterprise_install_attributes.h" #include "chrome/browser/lifetime/application_lifetime.h" @@ -115,7 +116,12 @@ class NotificationWatcher : public content::NotificationObserver { class DeviceLocalAccountTest : public InProcessBrowserTest { protected: - DeviceLocalAccountTest() {} + DeviceLocalAccountTest() + : user_id_1_(GenerateDeviceLocalAccountUserId( + kAccountId1, DeviceLocalAccount::TYPE_PUBLIC_SESSION)), + user_id_2_(GenerateDeviceLocalAccountUserId( + kAccountId2, DeviceLocalAccount::TYPE_PUBLIC_SESSION)) {} + virtual ~DeviceLocalAccountTest() {} virtual void SetUp() OVERRIDE { @@ -274,6 +280,9 @@ class DeviceLocalAccountTest : public InProcessBrowserTest { EXPECT_EQ(chromeos::User::USER_TYPE_PUBLIC_ACCOUNT, user->GetType()); } + const std::string user_id_1_; + const std::string user_id_2_; + LocalPolicyTestServer test_server_; base::ScopedTempDir temp_dir_; @@ -286,12 +295,12 @@ static bool IsKnownUser(const std::string& account_id) { IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) { NotificationWatcher(chrome::NOTIFICATION_USER_LIST_CHANGED, - base::Bind(&IsKnownUser, kAccountId1)).Run(); + base::Bind(&IsKnownUser, user_id_1_)).Run(); NotificationWatcher(chrome::NOTIFICATION_USER_LIST_CHANGED, - base::Bind(&IsKnownUser, kAccountId2)).Run(); + base::Bind(&IsKnownUser, user_id_2_)).Run(); - CheckPublicSessionPresent(kAccountId1); - CheckPublicSessionPresent(kAccountId2); + CheckPublicSessionPresent(user_id_1_); + CheckPublicSessionPresent(user_id_2_); } static bool DisplayNameMatches(const std::string& account_id, @@ -307,7 +316,7 @@ static bool DisplayNameMatches(const std::string& account_id, IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) { NotificationWatcher( chrome::NOTIFICATION_USER_LIST_CHANGED, - base::Bind(&DisplayNameMatches, kAccountId1, kDisplayName1)).Run(); + base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName1)).Run(); } IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) { @@ -317,7 +326,7 @@ IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) { // as signal to indicate successful policy download. NotificationWatcher( chrome::NOTIFICATION_USER_LIST_CHANGED, - base::Bind(&DisplayNameMatches, kAccountId2, kDisplayName2)).Run(); + base::Bind(&DisplayNameMatches, user_id_2_, kDisplayName2)).Run(); // Sanity check: The policy should be present now. ASSERT_FALSE(session_manager_client_->device_local_account_policy( @@ -331,9 +340,9 @@ static bool IsNotKnownUser(const std::string& account_id) { IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DevicePolicyChange) { // Wait until the login screen is up. NotificationWatcher(chrome::NOTIFICATION_USER_LIST_CHANGED, - base::Bind(&IsKnownUser, kAccountId1)).Run(); + base::Bind(&IsKnownUser, user_id_1_)).Run(); NotificationWatcher(chrome::NOTIFICATION_USER_LIST_CHANGED, - base::Bind(&IsKnownUser, kAccountId2)).Run(); + base::Bind(&IsKnownUser, user_id_2_)).Run(); // Update policy to remove kAccountId2. em::ChromeDeviceSettingsProto policy; @@ -350,7 +359,7 @@ IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DevicePolicyChange) { // Make sure the second device-local account disappears. NotificationWatcher(chrome::NOTIFICATION_USER_LIST_CHANGED, - base::Bind(&IsNotKnownUser, kAccountId2)).Run(); + base::Bind(&IsNotKnownUser, user_id_2_)).Run(); } static bool IsSessionStarted() { @@ -363,12 +372,12 @@ IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) { // successful login. NotificationWatcher( chrome::NOTIFICATION_USER_LIST_CHANGED, - base::Bind(&DisplayNameMatches, kAccountId1, kDisplayName1)).Run(); + base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName1)).Run(); chromeos::ExistingUserController* controller = chromeos::ExistingUserController::current_controller(); ASSERT_TRUE(controller); - controller->LoginAsPublicAccount(kAccountId1); + controller->LoginAsPublicAccount(user_id_1_); // Wait for the session to start. NotificationWatcher(chrome::NOTIFICATION_SESSION_STARTED, diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_provider.cc b/chrome/browser/chromeos/policy/device_local_account_policy_provider.cc index a269ef3..6b0535e 100644 --- a/chrome/browser/chromeos/policy/device_local_account_policy_provider.cc +++ b/chrome/browser/chromeos/policy/device_local_account_policy_provider.cc @@ -12,9 +12,9 @@ namespace policy { DeviceLocalAccountPolicyProvider::DeviceLocalAccountPolicyProvider( - const std::string& account_id, + const std::string& user_id, DeviceLocalAccountPolicyService* service) - : account_id_(account_id), + : user_id_(user_id), service_(service), store_initialized_(false), waiting_for_policy_refresh_(false), @@ -47,8 +47,8 @@ void DeviceLocalAccountPolicyProvider::RefreshPolicies() { } void DeviceLocalAccountPolicyProvider::OnPolicyUpdated( - const std::string& account_id) { - if (account_id == account_id_) + const std::string& user_id) { + if (user_id == user_id_) UpdateFromBroker(); } @@ -57,7 +57,7 @@ void DeviceLocalAccountPolicyProvider::OnDeviceLocalAccountsChanged() { } DeviceLocalAccountPolicyBroker* DeviceLocalAccountPolicyProvider::GetBroker() { - return service_->GetBrokerForAccount(account_id_); + return service_->GetBrokerForUser(user_id_); } void DeviceLocalAccountPolicyProvider::ReportPolicyRefresh(bool success) { diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_provider.h b/chrome/browser/chromeos/policy/device_local_account_policy_provider.h index 4728215..6dbd13c 100644 --- a/chrome/browser/chromeos/policy/device_local_account_policy_provider.h +++ b/chrome/browser/chromeos/policy/device_local_account_policy_provider.h @@ -24,7 +24,7 @@ class DeviceLocalAccountPolicyProvider : public ConfigurationPolicyProvider, public DeviceLocalAccountPolicyService::Observer { public: - DeviceLocalAccountPolicyProvider(const std::string& account_id, + DeviceLocalAccountPolicyProvider(const std::string& user_id, DeviceLocalAccountPolicyService* service); virtual ~DeviceLocalAccountPolicyProvider(); @@ -33,11 +33,11 @@ class DeviceLocalAccountPolicyProvider virtual void RefreshPolicies() OVERRIDE; // DeviceLocalAccountPolicyService::Observer: - virtual void OnPolicyUpdated(const std::string& account_id) OVERRIDE; + virtual void OnPolicyUpdated(const std::string& user_id) OVERRIDE; virtual void OnDeviceLocalAccountsChanged() OVERRIDE; private: - // Returns the broker for |account_id_| or NULL if not available. + // Returns the broker for |user_id_| or NULL if not available. DeviceLocalAccountPolicyBroker* GetBroker(); // Handles completion of policy refreshes and triggers the update callback. @@ -48,7 +48,7 @@ class DeviceLocalAccountPolicyProvider // policy from the broker if available or keeping the current policy. void UpdateFromBroker(); - const std::string account_id_; + const std::string user_id_; DeviceLocalAccountPolicyService* service_; bool store_initialized_; diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_service.cc b/chrome/browser/chromeos/policy/device_local_account_policy_service.cc index df918a8..a538826 100644 --- a/chrome/browser/chromeos/policy/device_local_account_policy_service.cc +++ b/chrome/browser/chromeos/policy/device_local_account_policy_service.cc @@ -4,35 +4,87 @@ #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" +#include <vector> + +#include "base/bind.h" #include "base/logging.h" #include "base/message_loop.h" +#include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/policy/device_local_account_policy_store.h" +#include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chrome/browser/chromeos/settings/cros_settings_names.h" +#include "chrome/browser/chromeos/settings/cros_settings_provider.h" +#include "chrome/browser/chromeos/settings/device_settings_service.h" #include "chrome/browser/policy/cloud/cloud_policy_client.h" #include "chrome/browser/policy/cloud/cloud_policy_constants.h" #include "chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h" #include "chrome/browser/policy/cloud/device_management_service.h" -#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h" #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h" +#include "chrome/common/chrome_notification_types.h" #include "chromeos/dbus/session_manager_client.h" +#include "content/public/browser/notification_details.h" #include "policy/policy_constants.h" namespace em = enterprise_management; namespace policy { +namespace { + +// Creates a broker for the device-local account with the given |user_id| and +// |account_id|. +scoped_ptr<DeviceLocalAccountPolicyBroker> CreateBroker( + const std::string& user_id, + const std::string& account_id, + chromeos::SessionManagerClient* session_manager_client, + chromeos::DeviceSettingsService* device_settings_service, + DeviceLocalAccountPolicyService* device_local_account_policy_service) { + scoped_ptr<DeviceLocalAccountPolicyStore> store( + new DeviceLocalAccountPolicyStore(account_id, session_manager_client, + device_settings_service)); + scoped_ptr<DeviceLocalAccountPolicyBroker> broker( + new DeviceLocalAccountPolicyBroker(user_id, store.Pass())); + broker->core()->store()->AddObserver(device_local_account_policy_service); + broker->core()->store()->Load(); + return broker.Pass(); +} + +// Creates and initializes a cloud policy client. Returns NULL if the device +// doesn't have credentials in device settings (i.e. is not +// enterprise-enrolled). +scoped_ptr<CloudPolicyClient> CreateClient( + chromeos::DeviceSettingsService* device_settings_service, + DeviceManagementService* device_management_service) { + const em::PolicyData* policy_data = device_settings_service->policy_data(); + if (!policy_data || + !policy_data->has_request_token() || + !policy_data->has_device_id() || + !device_management_service) { + return scoped_ptr<CloudPolicyClient>(); + } + + scoped_ptr<CloudPolicyClient> client( + new CloudPolicyClient(std::string(), std::string(), + USER_AFFILIATION_MANAGED, + NULL, device_management_service)); + client->SetupRegistration(policy_data->request_token(), + policy_data->device_id()); + return client.Pass(); +} + +} // namespace + DeviceLocalAccountPolicyBroker::DeviceLocalAccountPolicyBroker( + const std::string& user_id, scoped_ptr<DeviceLocalAccountPolicyStore> store) - : store_(store.Pass()), + : user_id_(user_id), + store_(store.Pass()), core_(PolicyNamespaceKey(dm_protocol::kChromePublicAccountPolicyType, store_->account_id()), store_.get()) {} DeviceLocalAccountPolicyBroker::~DeviceLocalAccountPolicyBroker() {} -const std::string& DeviceLocalAccountPolicyBroker::account_id() const { - return store_->account_id(); -} - void DeviceLocalAccountPolicyBroker::Connect( scoped_ptr<CloudPolicyClient> client) { core_.Connect(client.Pass()); @@ -63,18 +115,60 @@ std::string DeviceLocalAccountPolicyBroker::GetDisplayName() const { return display_name; } +DeviceLocalAccountPolicyService::PolicyBrokerWrapper::PolicyBrokerWrapper() + : parent(NULL), broker(NULL) {} + +DeviceLocalAccountPolicyBroker* + DeviceLocalAccountPolicyService::PolicyBrokerWrapper::GetBroker() { + if (!broker) { + broker = CreateBroker(user_id, account_id, + parent->session_manager_client_, + parent->device_settings_service_, + parent).release(); + } + return broker; +} + +void DeviceLocalAccountPolicyService::PolicyBrokerWrapper::ConnectIfPossible() { + if (broker && broker->core()->client()) + return; + scoped_ptr<CloudPolicyClient> client(CreateClient( + parent->device_settings_service_, + parent->device_management_service_)); + if (client) + GetBroker()->Connect(client.Pass()); +} + +void DeviceLocalAccountPolicyService::PolicyBrokerWrapper::Disconnect() { + if (broker) + broker->Disconnect(); +} + +void DeviceLocalAccountPolicyService::PolicyBrokerWrapper::DeleteBroker() { + if (!broker) + return; + broker->core()->store()->RemoveObserver(parent); + delete broker; + broker = NULL; +} + DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService( chromeos::SessionManagerClient* session_manager_client, - chromeos::DeviceSettingsService* device_settings_service) + chromeos::DeviceSettingsService* device_settings_service, + chromeos::CrosSettings* cros_settings) : session_manager_client_(session_manager_client), device_settings_service_(device_settings_service), - device_management_service_(NULL) { - device_settings_service_->AddObserver(this); - DeviceSettingsUpdated(); + cros_settings_(cros_settings), + device_management_service_(NULL), + cros_settings_callback_factory_(this) { + cros_settings_->AddSettingsObserver( + chromeos::kAccountsPrefDeviceLocalAccounts, this); + UpdateAccountList(); } DeviceLocalAccountPolicyService::~DeviceLocalAccountPolicyService() { - device_settings_service_->RemoveObserver(this); + cros_settings_->RemoveSettingsObserver( + chromeos::kAccountsPrefDeviceLocalAccounts, this); DeleteBrokers(&policy_brokers_); } @@ -84,11 +178,9 @@ void DeviceLocalAccountPolicyService::Connect( device_management_service_ = device_management_service; // Connect the brokers. - for (PolicyBrokerMap::iterator broker(policy_brokers_.begin()); - broker != policy_brokers_.end(); ++broker) { - DCHECK(!broker->second->core()->client()); - broker->second->Connect( - CreateClientForAccount(broker->second->account_id()).Pass()); + for (PolicyBrokerMap::iterator it(policy_brokers_.begin()); + it != policy_brokers_.end(); ++it) { + it->second.ConnectIfPossible(); } } @@ -97,28 +189,25 @@ void DeviceLocalAccountPolicyService::Disconnect() { device_management_service_ = NULL; // Disconnect the brokers. - for (PolicyBrokerMap::iterator broker(policy_brokers_.begin()); - broker != policy_brokers_.end(); ++broker) { - broker->second->Disconnect(); + for (PolicyBrokerMap::iterator it(policy_brokers_.begin()); + it != policy_brokers_.end(); ++it) { + it->second.Disconnect(); } } DeviceLocalAccountPolicyBroker* - DeviceLocalAccountPolicyService::GetBrokerForAccount( - const std::string& account_id) { - PolicyBrokerMap::iterator entry = policy_brokers_.find(account_id); + DeviceLocalAccountPolicyService::GetBrokerForUser( + const std::string& user_id) { + PolicyBrokerMap::iterator entry = policy_brokers_.find(user_id); if (entry == policy_brokers_.end()) return NULL; - if (!entry->second) - entry->second = CreateBroker(account_id).release(); - - return entry->second; + return entry->second.GetBroker(); } -bool DeviceLocalAccountPolicyService::IsPolicyAvailableForAccount( - const std::string& account_id) { - DeviceLocalAccountPolicyBroker* broker = GetBrokerForAccount(account_id); +bool DeviceLocalAccountPolicyService::IsPolicyAvailableForUser( + const std::string& user_id) { + DeviceLocalAccountPolicyBroker* broker = GetBrokerForUser(user_id); return broker && broker->core()->store()->is_managed(); } @@ -130,79 +219,69 @@ void DeviceLocalAccountPolicyService::RemoveObserver(Observer* observer) { observers_.RemoveObserver(observer); } -void DeviceLocalAccountPolicyService::OwnershipStatusChanged() { - // TODO(mnissler): The policy key has changed, re-fetch policy. For - // consumer devices, re-sign the current settings and send updates to - // session_manager. -} +void DeviceLocalAccountPolicyService::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + if (type != chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED || + *content::Details<const std::string>(details).ptr() != + chromeos::kAccountsPrefDeviceLocalAccounts) { + NOTREACHED(); + return; + } -void DeviceLocalAccountPolicyService::DeviceSettingsUpdated() { - const em::ChromeDeviceSettingsProto* device_settings = - device_settings_service_->device_settings(); - if (device_settings) - UpdateAccountList(*device_settings); + // Avoid unnecessary calls to UpdateAccountList(): If an earlier call is still + // pending (because the |cros_settings_| are not trusted yet), the updated + // account list will be processed by that call when it eventually runs. + if (!cros_settings_callback_factory_.HasWeakPtrs()) + UpdateAccountList(); } void DeviceLocalAccountPolicyService::OnStoreLoaded(CloudPolicyStore* store) { DeviceLocalAccountPolicyBroker* broker = GetBrokerForStore(store); + DCHECK(broker); + if (!broker) + return; broker->UpdateRefreshDelay(); - FOR_EACH_OBSERVER(Observer, observers_, - OnPolicyUpdated(broker->account_id())); + FOR_EACH_OBSERVER(Observer, observers_, OnPolicyUpdated(broker->user_id())); } void DeviceLocalAccountPolicyService::OnStoreError(CloudPolicyStore* store) { DeviceLocalAccountPolicyBroker* broker = GetBrokerForStore(store); - FOR_EACH_OBSERVER(Observer, observers_, - OnPolicyUpdated(broker->account_id())); + DCHECK(broker); + if (!broker) + return; + FOR_EACH_OBSERVER(Observer, observers_, OnPolicyUpdated(broker->user_id())); } -void DeviceLocalAccountPolicyService::UpdateAccountList( - const em::ChromeDeviceSettingsProto& device_settings) { - using google::protobuf::RepeatedPtrField; +void DeviceLocalAccountPolicyService::UpdateAccountList() { + if (chromeos::CrosSettingsProvider::TRUSTED != + cros_settings_->PrepareTrustedValues( + base::Bind(&DeviceLocalAccountPolicyService::UpdateAccountList, + cros_settings_callback_factory_.GetWeakPtr()))) { + return; + } // Update |policy_brokers_|, keeping existing entries. PolicyBrokerMap new_policy_brokers; - const RepeatedPtrField<em::DeviceLocalAccountInfoProto>& accounts = - device_settings.device_local_accounts().account(); - RepeatedPtrField<em::DeviceLocalAccountInfoProto>::const_iterator entry; - for (entry = accounts.begin(); entry != accounts.end(); ++entry) { - std::string account_id; - if (entry->has_type() && - entry->type() == - em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION) { - account_id = entry->account_id(); - } else if (entry->has_deprecated_public_session_id()) { - account_id = entry->deprecated_public_session_id(); - } - - if (account_id.empty()) - continue; - - // Sanity check for whether this account ID has already been processed. - DeviceLocalAccountPolicyBroker*& new_broker = - new_policy_brokers[account_id]; - if (new_broker) { - LOG(WARNING) << "Duplicate public account " << account_id; - continue; - } + const std::vector<DeviceLocalAccount> device_local_accounts = + GetDeviceLocalAccounts(cros_settings_); + for (std::vector<DeviceLocalAccount>::const_iterator it = + device_local_accounts.begin(); + it != device_local_accounts.end(); ++it) { + PolicyBrokerWrapper& wrapper = new_policy_brokers[it->user_id]; + wrapper.user_id = it->user_id; + wrapper.account_id = it->account_id; + wrapper.parent = this; // Reuse the existing broker if present. - DeviceLocalAccountPolicyBroker*& existing_broker = - policy_brokers_[account_id]; - new_broker = existing_broker; - existing_broker = NULL; + PolicyBrokerWrapper& existing_wrapper = policy_brokers_[it->user_id]; + wrapper.broker = existing_wrapper.broker; + existing_wrapper.broker = NULL; // Fire up the cloud connection for fetching policy for the account from // the cloud if this is an enterprise-managed device. - if (!new_broker || !new_broker->core()->client()) { - scoped_ptr<CloudPolicyClient> client( - CreateClientForAccount(account_id)); - if (client.get()) { - if (!new_broker) - new_broker = CreateBroker(account_id).release(); - new_broker->Connect(client.Pass()); - } - } + wrapper.ConnectIfPossible(); } policy_brokers_.swap(new_policy_brokers); DeleteBrokers(&new_policy_brokers); @@ -210,59 +289,21 @@ void DeviceLocalAccountPolicyService::UpdateAccountList( FOR_EACH_OBSERVER(Observer, observers_, OnDeviceLocalAccountsChanged()); } -scoped_ptr<DeviceLocalAccountPolicyBroker> - DeviceLocalAccountPolicyService::CreateBroker( - const std::string& account_id) { - scoped_ptr<DeviceLocalAccountPolicyStore> store( - new DeviceLocalAccountPolicyStore(account_id, session_manager_client_, - device_settings_service_)); - scoped_ptr<DeviceLocalAccountPolicyBroker> broker( - new DeviceLocalAccountPolicyBroker(store.Pass())); - broker->core()->store()->AddObserver(this); - broker->core()->store()->Load(); - return broker.Pass(); -} - void DeviceLocalAccountPolicyService::DeleteBrokers(PolicyBrokerMap* map) { - for (PolicyBrokerMap::iterator broker = map->begin(); broker != map->end(); - ++broker) { - if (broker->second) { - broker->second->core()->store()->RemoveObserver(this); - delete broker->second; - } - } + for (PolicyBrokerMap::iterator it = map->begin(); it != map->end(); ++it) + it->second.DeleteBroker(); map->clear(); } DeviceLocalAccountPolicyBroker* DeviceLocalAccountPolicyService::GetBrokerForStore( CloudPolicyStore* store) { - for (PolicyBrokerMap::iterator broker(policy_brokers_.begin()); - broker != policy_brokers_.end(); ++broker) { - if (broker->second->core()->store() == store) - return broker->second; + for (PolicyBrokerMap::iterator it(policy_brokers_.begin()); + it != policy_brokers_.end(); ++it) { + if (it->second.broker && it->second.broker->core()->store() == store) + return it->second.broker; } return NULL; } -scoped_ptr<CloudPolicyClient> - DeviceLocalAccountPolicyService::CreateClientForAccount( - const std::string& account_id) { - const em::PolicyData* policy_data = device_settings_service_->policy_data(); - if (!policy_data || - !policy_data->has_request_token() || - !policy_data->has_device_id() || - !device_management_service_) { - return scoped_ptr<CloudPolicyClient>(); - } - - scoped_ptr<CloudPolicyClient> client( - new CloudPolicyClient(std::string(), std::string(), - USER_AFFILIATION_MANAGED, - NULL, device_management_service_)); - client->SetupRegistration(policy_data->request_token(), - policy_data->device_id()); - return client.Pass(); -} - } // namespace policy diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_service.h b/chrome/browser/chromeos/policy/device_local_account_policy_service.h index cb0f056..049af56 100644 --- a/chrome/browser/chromeos/policy/device_local_account_policy_service.h +++ b/chrome/browser/chromeos/policy/device_local_account_policy_service.h @@ -9,15 +9,17 @@ #include <string> #include "base/basictypes.h" -#include "base/callback_forward.h" #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" #include "base/observer_list.h" -#include "chrome/browser/chromeos/settings/device_settings_service.h" #include "chrome/browser/policy/cloud/cloud_policy_core.h" #include "chrome/browser/policy/cloud/cloud_policy_store.h" +#include "content/public/browser/notification_observer.h" namespace chromeos { +class CrosSettings; +class DeviceSettingsService; class SessionManagerClient; } @@ -32,10 +34,11 @@ class DeviceManagementService; class DeviceLocalAccountPolicyBroker { public: explicit DeviceLocalAccountPolicyBroker( + const std::string& user_id, scoped_ptr<DeviceLocalAccountPolicyStore> store); ~DeviceLocalAccountPolicyBroker(); - const std::string& account_id() const; + const std::string& user_id() const { return user_id_; } CloudPolicyCore* core() { return &core_; } const CloudPolicyCore* core() const { return &core_; } @@ -54,7 +57,7 @@ class DeviceLocalAccountPolicyBroker { std::string GetDisplayName() const; private: - const std::string account_id_; + const std::string user_id_; scoped_ptr<DeviceLocalAccountPolicyStore> store_; CloudPolicyCore core_; @@ -65,17 +68,16 @@ class DeviceLocalAccountPolicyBroker { // The actual policy blobs are brokered by session_manager (to prevent file // manipulation), and we're making signature checks on the policy blobs to // ensure they're issued by the device owner. -class DeviceLocalAccountPolicyService - : public chromeos::DeviceSettingsService::Observer, - public CloudPolicyStore::Observer { +class DeviceLocalAccountPolicyService : public content::NotificationObserver, + public CloudPolicyStore::Observer { public: // Interface for interested parties to observe policy changes. class Observer { public: virtual ~Observer() {} - // Policy for the given account has changed. - virtual void OnPolicyUpdated(const std::string& account_id) = 0; + // Policy for the given |user_id| has changed. + virtual void OnPolicyUpdated(const std::string& user_id) = 0; // The list of accounts has been updated. virtual void OnDeviceLocalAccountsChanged() = 0; @@ -83,7 +85,8 @@ class DeviceLocalAccountPolicyService DeviceLocalAccountPolicyService( chromeos::SessionManagerClient* session_manager_client, - chromeos::DeviceSettingsService* device_settings_service); + chromeos::DeviceSettingsService* device_settings_service, + chromeos::CrosSettings* cros_settings); virtual ~DeviceLocalAccountPolicyService(); // Initializes the cloud policy service connection. @@ -92,38 +95,54 @@ class DeviceLocalAccountPolicyService // Prevents further policy fetches from the cloud. void Disconnect(); - // Get the policy broker for a given account. Returns NULL if that account is - // not valid. - DeviceLocalAccountPolicyBroker* GetBrokerForAccount( - const std::string& account_id); + // Get the policy broker for a given |user_id|. Returns NULL if that |user_id| + // does not belong to an existing device-local account. + DeviceLocalAccountPolicyBroker* GetBrokerForUser(const std::string& user_id); // Indicates whether policy has been successfully fetched for the given - // account. - bool IsPolicyAvailableForAccount(const std::string& account_id); + // |user_id|. + bool IsPolicyAvailableForUser(const std::string& user_id); void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); - // DeviceSettingsService::Observer: - virtual void OwnershipStatusChanged() OVERRIDE; - virtual void DeviceSettingsUpdated() OVERRIDE; + // NotificationObserver: + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; // CloudPolicyStore::Observer: virtual void OnStoreLoaded(CloudPolicyStore* store) OVERRIDE; virtual void OnStoreError(CloudPolicyStore* store) OVERRIDE; private: - typedef std::map<std::string, DeviceLocalAccountPolicyBroker*> - PolicyBrokerMap; + struct PolicyBrokerWrapper { + PolicyBrokerWrapper(); + + // Return the |broker|, creating it first if necessary. + DeviceLocalAccountPolicyBroker* GetBroker(); + + // Fire up the cloud connection for fetching policy for the account from the + // cloud if this is an enterprise-managed device. + void ConnectIfPossible(); + + // Destroy the cloud connection. + void Disconnect(); + + // Delete the broker. + void DeleteBroker(); + + std::string user_id; + std::string account_id; + DeviceLocalAccountPolicyService* parent; + DeviceLocalAccountPolicyBroker* broker; + }; + + typedef std::map<std::string, PolicyBrokerWrapper> PolicyBrokerMap; // Re-queries the list of defined device-local accounts from device settings // and updates |policy_brokers_| to match that list. - void UpdateAccountList( - const enterprise_management::ChromeDeviceSettingsProto& device_settings); - - // Creates a broker for the given account ID. - scoped_ptr<DeviceLocalAccountPolicyBroker> CreateBroker( - const std::string& account_id); + void UpdateAccountList(); // Deletes brokers in |map| and clears it. void DeleteBrokers(PolicyBrokerMap* map); @@ -131,22 +150,21 @@ class DeviceLocalAccountPolicyService // Find the broker for a given |store|. Returns NULL if |store| is unknown. DeviceLocalAccountPolicyBroker* GetBrokerForStore(CloudPolicyStore* store); - // Creates and initializes a cloud policy client for |account_id|. Returns - // NULL if the device doesn't have credentials in device settings (i.e. is not - // enterprise-enrolled). - scoped_ptr<CloudPolicyClient> CreateClientForAccount( - const std::string& account_id); - chromeos::SessionManagerClient* session_manager_client_; chromeos::DeviceSettingsService* device_settings_service_; + chromeos::CrosSettings* cros_settings_; DeviceManagementService* device_management_service_; - // The device-local account policy brokers, keyed by account ID. + // The device-local account policy brokers, keyed by user ID. PolicyBrokerMap policy_brokers_; ObserverList<Observer, true> observers_; + // Weak pointer factory for cros_settings_->PrepareTrustedValues() callbacks. + base::WeakPtrFactory<DeviceLocalAccountPolicyService> + cros_settings_callback_factory_; + DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyService); }; diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc b/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc index 3c3c20a..f764b91 100644 --- a/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc +++ b/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc @@ -7,7 +7,10 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/memory/scoped_ptr.h" +#include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/policy/device_local_account_policy_provider.h" +#include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chrome/browser/chromeos/settings/device_settings_service.h" #include "chrome/browser/chromeos/settings/device_settings_test_helper.h" #include "chrome/browser/policy/cloud/cloud_policy_client.h" #include "chrome/browser/policy/cloud/cloud_policy_constants.h" @@ -41,7 +44,13 @@ class DeviceLocalAccountPolicyServiceTest : public chromeos::DeviceSettingsTestBase { public: DeviceLocalAccountPolicyServiceTest() - : service_(&device_settings_test_helper_, &device_settings_service_) {} + : public_session_user_id_(GenerateDeviceLocalAccountUserId( + PolicyBuilder::kFakeUsername, + DeviceLocalAccount::TYPE_PUBLIC_SESSION)), + cros_settings_(&device_settings_service_), + service_(&device_settings_test_helper_, + &device_settings_service_, + &cros_settings_) {} virtual void SetUp() OVERRIDE { DeviceSettingsTestBase::SetUp(); @@ -107,8 +116,11 @@ class DeviceLocalAccountPolicyServiceTest MOCK_METHOD1(OnRefreshDone, void(bool)); + const std::string public_session_user_id_; + PolicyMap expected_policy_map_; UserPolicyBuilder device_local_account_policy_; + chromeos::CrosSettings cros_settings_; MockDeviceLocalAccountPolicyServiceObserver service_observer_; MockDeviceManagementService mock_device_management_service_; DeviceLocalAccountPolicyService service_; @@ -118,16 +130,16 @@ class DeviceLocalAccountPolicyServiceTest }; TEST_F(DeviceLocalAccountPolicyServiceTest, NoAccounts) { - EXPECT_FALSE(service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername)); + EXPECT_FALSE(service_.GetBrokerForUser(public_session_user_id_)); } TEST_F(DeviceLocalAccountPolicyServiceTest, GetBroker) { InstallDevicePolicy(); DeviceLocalAccountPolicyBroker* broker = - service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + service_.GetBrokerForUser(public_session_user_id_); ASSERT_TRUE(broker); - EXPECT_EQ(PolicyBuilder::kFakeUsername, broker->account_id()); + EXPECT_EQ(public_session_user_id_, broker->user_id()); ASSERT_TRUE(broker->core()->store()); EXPECT_EQ(CloudPolicyStore::STATUS_OK, broker->core()->store()->status()); EXPECT_FALSE(broker->core()->client()); @@ -137,9 +149,9 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, GetBroker) { TEST_F(DeviceLocalAccountPolicyServiceTest, LoadNoPolicy) { InstallDevicePolicy(); - EXPECT_CALL(service_observer_, OnPolicyUpdated(PolicyBuilder::kFakeUsername)); + EXPECT_CALL(service_observer_, OnPolicyUpdated(public_session_user_id_)); DeviceLocalAccountPolicyBroker* broker = - service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + service_.GetBrokerForUser(public_session_user_id_); ASSERT_TRUE(broker); FlushDeviceSettings(); Mock::VerifyAndClearExpectations(&service_observer_); @@ -148,8 +160,7 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, LoadNoPolicy) { EXPECT_EQ(CloudPolicyStore::STATUS_LOAD_ERROR, broker->core()->store()->status()); EXPECT_TRUE(broker->core()->store()->policy_map().empty()); - EXPECT_FALSE(service_.IsPolicyAvailableForAccount( - PolicyBuilder::kFakeUsername)); + EXPECT_FALSE(service_.IsPolicyAvailableForUser(public_session_user_id_)); } TEST_F(DeviceLocalAccountPolicyServiceTest, LoadValidationFailure) { @@ -160,9 +171,9 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, LoadValidationFailure) { PolicyBuilder::kFakeUsername, device_local_account_policy_.GetBlob()); InstallDevicePolicy(); - EXPECT_CALL(service_observer_, OnPolicyUpdated(PolicyBuilder::kFakeUsername)); + EXPECT_CALL(service_observer_, OnPolicyUpdated(public_session_user_id_)); DeviceLocalAccountPolicyBroker* broker = - service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + service_.GetBrokerForUser(public_session_user_id_); ASSERT_TRUE(broker); FlushDeviceSettings(); Mock::VerifyAndClearExpectations(&service_observer_); @@ -171,8 +182,7 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, LoadValidationFailure) { EXPECT_EQ(CloudPolicyStore::STATUS_VALIDATION_ERROR, broker->core()->store()->status()); EXPECT_TRUE(broker->core()->store()->policy_map().empty()); - EXPECT_FALSE(service_.IsPolicyAvailableForAccount( - PolicyBuilder::kFakeUsername)); + EXPECT_FALSE(service_.IsPolicyAvailableForUser(public_session_user_id_)); } TEST_F(DeviceLocalAccountPolicyServiceTest, LoadPolicy) { @@ -180,9 +190,9 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, LoadPolicy) { PolicyBuilder::kFakeUsername, device_local_account_policy_.GetBlob()); InstallDevicePolicy(); - EXPECT_CALL(service_observer_, OnPolicyUpdated(PolicyBuilder::kFakeUsername)); + EXPECT_CALL(service_observer_, OnPolicyUpdated(public_session_user_id_)); DeviceLocalAccountPolicyBroker* broker = - service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + service_.GetBrokerForUser(public_session_user_id_); ASSERT_TRUE(broker); FlushDeviceSettings(); Mock::VerifyAndClearExpectations(&service_observer_); @@ -195,8 +205,7 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, LoadPolicy) { broker->core()->store()->policy()->SerializeAsString()); EXPECT_TRUE(expected_policy_map_.Equals( broker->core()->store()->policy_map())); - EXPECT_TRUE(service_.IsPolicyAvailableForAccount( - PolicyBuilder::kFakeUsername)); + EXPECT_TRUE(service_.IsPolicyAvailableForUser(public_session_user_id_)); } TEST_F(DeviceLocalAccountPolicyServiceTest, StoreValidationFailure) { @@ -205,9 +214,9 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, StoreValidationFailure) { device_local_account_policy_.Build(); InstallDevicePolicy(); - EXPECT_CALL(service_observer_, OnPolicyUpdated(PolicyBuilder::kFakeUsername)); + EXPECT_CALL(service_observer_, OnPolicyUpdated(public_session_user_id_)); DeviceLocalAccountPolicyBroker* broker = - service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + service_.GetBrokerForUser(public_session_user_id_); ASSERT_TRUE(broker); ASSERT_TRUE(broker->core()->store()); broker->core()->store()->Store(device_local_account_policy_.policy()); @@ -219,16 +228,15 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, StoreValidationFailure) { broker->core()->store()->status()); EXPECT_EQ(CloudPolicyValidatorBase::VALIDATION_WRONG_POLICY_TYPE, broker->core()->store()->validation_status()); - EXPECT_FALSE(service_.IsPolicyAvailableForAccount( - PolicyBuilder::kFakeUsername)); + EXPECT_FALSE(service_.IsPolicyAvailableForUser(public_session_user_id_)); } TEST_F(DeviceLocalAccountPolicyServiceTest, StorePolicy) { InstallDevicePolicy(); - EXPECT_CALL(service_observer_, OnPolicyUpdated(PolicyBuilder::kFakeUsername)); + EXPECT_CALL(service_observer_, OnPolicyUpdated(public_session_user_id_)); DeviceLocalAccountPolicyBroker* broker = - service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + service_.GetBrokerForUser(public_session_user_id_); ASSERT_TRUE(broker); ASSERT_TRUE(broker->core()->store()); broker->core()->store()->Store(device_local_account_policy_.policy()); @@ -238,8 +246,7 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, StorePolicy) { EXPECT_EQ(device_local_account_policy_.GetBlob(), device_settings_test_helper_.device_local_account_policy_blob( PolicyBuilder::kFakeUsername)); - EXPECT_TRUE(service_.IsPolicyAvailableForAccount( - PolicyBuilder::kFakeUsername)); + EXPECT_TRUE(service_.IsPolicyAvailableForUser(public_session_user_id_)); } TEST_F(DeviceLocalAccountPolicyServiceTest, DevicePolicyChange) { @@ -253,14 +260,14 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, DevicePolicyChange) { device_settings_test_helper_.set_policy_blob(device_policy_.GetBlob()); device_settings_service_.PropertyChangeComplete(true); FlushDeviceSettings(); - EXPECT_FALSE(service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername)); + EXPECT_FALSE(service_.GetBrokerForUser(public_session_user_id_)); Mock::VerifyAndClearExpectations(&service_observer_); } TEST_F(DeviceLocalAccountPolicyServiceTest, DuplicateAccounts) { InstallDevicePolicy(); DeviceLocalAccountPolicyBroker* broker = - service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + service_.GetBrokerForUser(public_session_user_id_); ASSERT_TRUE(broker); // Add a second entry with a duplicate account name to device policy. @@ -275,15 +282,15 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, DuplicateAccounts) { device_settings_test_helper_.set_policy_blob(device_policy_.GetBlob()); EXPECT_CALL(service_observer_, OnDeviceLocalAccountsChanged()); - EXPECT_CALL(service_observer_, OnPolicyUpdated(PolicyBuilder::kFakeUsername)); + EXPECT_CALL(service_observer_, OnPolicyUpdated(public_session_user_id_)); device_settings_service_.PropertyChangeComplete(true); FlushDeviceSettings(); Mock::VerifyAndClearExpectations(&service_observer_); // Make sure the broker is accessible and policy got loaded. - broker = service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + broker = service_.GetBrokerForUser(public_session_user_id_); ASSERT_TRUE(broker); - EXPECT_EQ(PolicyBuilder::kFakeUsername, broker->account_id()); + EXPECT_EQ(public_session_user_id_, broker->user_id()); EXPECT_TRUE(broker->core()->store()->policy()); } @@ -293,7 +300,7 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, FetchPolicy) { InstallDevicePolicy(); DeviceLocalAccountPolicyBroker* broker = - service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + service_.GetBrokerForUser(public_session_user_id_); ASSERT_TRUE(broker); service_.Connect(&mock_device_management_service_); @@ -314,7 +321,7 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, FetchPolicy) { device_policy_.policy_data().device_id(), _)) .WillOnce(SaveArg<6>(&request)); - EXPECT_CALL(service_observer_, OnPolicyUpdated(PolicyBuilder::kFakeUsername)); + EXPECT_CALL(service_observer_, OnPolicyUpdated(public_session_user_id_)); broker->core()->client()->FetchPolicy(); FlushDeviceSettings(); Mock::VerifyAndClearExpectations(&service_observer_); @@ -335,16 +342,14 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, FetchPolicy) { broker->core()->store()->policy()->SerializeAsString()); EXPECT_TRUE(expected_policy_map_.Equals( broker->core()->store()->policy_map())); - EXPECT_TRUE(service_.IsPolicyAvailableForAccount( - PolicyBuilder::kFakeUsername)); + EXPECT_TRUE(service_.IsPolicyAvailableForUser(public_session_user_id_)); - EXPECT_CALL(service_observer_, - OnPolicyUpdated(PolicyBuilder::kFakeUsername)).Times(0); + EXPECT_CALL(service_observer_, OnPolicyUpdated(public_session_user_id_)) + .Times(0); service_.Disconnect(); EXPECT_FALSE(broker->core()->client()); Mock::VerifyAndClearExpectations(&service_observer_); - EXPECT_TRUE(service_.IsPolicyAvailableForAccount( - PolicyBuilder::kFakeUsername)); + EXPECT_TRUE(service_.IsPolicyAvailableForUser(public_session_user_id_)); } TEST_F(DeviceLocalAccountPolicyServiceTest, RefreshPolicy) { @@ -353,7 +358,7 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, RefreshPolicy) { InstallDevicePolicy(); DeviceLocalAccountPolicyBroker* broker = - service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + service_.GetBrokerForUser(public_session_user_id_); ASSERT_TRUE(broker); service_.Connect(&mock_device_management_service_); @@ -366,7 +371,7 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, RefreshPolicy) { .WillOnce(mock_device_management_service_.SucceedJob(response)); EXPECT_CALL(mock_device_management_service_, StartJob(_, _, _, _, _, _, _)); EXPECT_CALL(*this, OnRefreshDone(true)).Times(1); - EXPECT_CALL(service_observer_, OnPolicyUpdated(PolicyBuilder::kFakeUsername)); + EXPECT_CALL(service_observer_, OnPolicyUpdated(public_session_user_id_)); broker->core()->service()->RefreshPolicy( base::Bind(&DeviceLocalAccountPolicyServiceTest::OnRefreshDone, base::Unretained(this))); @@ -380,15 +385,18 @@ TEST_F(DeviceLocalAccountPolicyServiceTest, RefreshPolicy) { broker->core()->store()->status()); EXPECT_TRUE(expected_policy_map_.Equals( broker->core()->store()->policy_map())); - EXPECT_TRUE(service_.IsPolicyAvailableForAccount( - PolicyBuilder::kFakeUsername)); + EXPECT_TRUE(service_.IsPolicyAvailableForUser(public_session_user_id_)); } class DeviceLocalAccountPolicyProviderTest : public DeviceLocalAccountPolicyServiceTest { protected: DeviceLocalAccountPolicyProviderTest() - : provider_(PolicyBuilder::kFakeUsername, &service_) {} + : provider_( + GenerateDeviceLocalAccountUserId( + PolicyBuilder::kFakeUsername, + DeviceLocalAccount::TYPE_PUBLIC_SESSION), + &service_) {} virtual void SetUp() OVERRIDE { DeviceLocalAccountPolicyServiceTest::SetUp(); @@ -460,7 +468,7 @@ TEST_F(DeviceLocalAccountPolicyProviderTest, Policy) { device_settings_test_helper_.set_device_local_account_policy_blob( PolicyBuilder::kFakeUsername, device_local_account_policy_.GetBlob()); DeviceLocalAccountPolicyBroker* broker = - service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + service_.GetBrokerForUser(public_session_user_id_); ASSERT_TRUE(broker); broker->core()->store()->Load(); FlushDeviceSettings(); @@ -505,7 +513,7 @@ TEST_F(DeviceLocalAccountPolicyProviderTest, Policy) { TEST_F(DeviceLocalAccountPolicyProviderTest, RefreshPolicies) { // If there's no device policy, the refresh completes immediately. - EXPECT_FALSE(service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername)); + EXPECT_FALSE(service_.GetBrokerForUser(public_session_user_id_)); EXPECT_CALL(provider_observer_, OnUpdatePolicy(&provider_)).Times(AtLeast(1)); provider_.RefreshPolicies(); Mock::VerifyAndClearExpectations(&provider_observer_); @@ -516,11 +524,11 @@ TEST_F(DeviceLocalAccountPolicyProviderTest, RefreshPolicies) { device_settings_test_helper_.set_policy_blob(device_policy_.GetBlob()); ReloadDeviceSettings(); Mock::VerifyAndClearExpectations(&provider_observer_); - EXPECT_TRUE(service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername)); + EXPECT_TRUE(service_.GetBrokerForUser(public_session_user_id_)); // If there's no cloud connection, refreshes are still immediate. DeviceLocalAccountPolicyBroker* broker = - service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + service_.GetBrokerForUser(public_session_user_id_); ASSERT_TRUE(broker); EXPECT_FALSE(broker->core()->client()); EXPECT_CALL(provider_observer_, OnUpdatePolicy(&provider_)).Times(AtLeast(1)); diff --git a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc index 59d4ea8..5d22a9b 100644 --- a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc +++ b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc @@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/values.h" +#include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/policy/enterprise_install_attributes.h" #include "chrome/browser/chromeos/settings/cros_settings_names.h" #include "chrome/browser/policy/policy_map.h" @@ -148,7 +149,7 @@ void DecodeLoginPolicies(const em::ChromeDeviceSettingsProto& policy, entry->deprecated_public_session_id()); entry_dict->SetIntegerWithoutPathExpansion( chromeos::kAccountsPrefDeviceLocalAccountsKeyType, - chromeos::DEVICE_LOCAL_ACCOUNT_TYPE_PUBLIC_SESSION); + DeviceLocalAccount::TYPE_PUBLIC_SESSION); } account_list->Append(entry_dict.release()); } diff --git a/chrome/browser/chromeos/settings/cros_settings.cc b/chrome/browser/chromeos/settings/cros_settings.cc index 050bef9..799d925 100644 --- a/chrome/browser/chromeos/settings/cros_settings.cc +++ b/chrome/browser/chromeos/settings/cros_settings.cc @@ -28,7 +28,7 @@ static CrosSettings* g_cros_settings = NULL; // static void CrosSettings::Initialize() { CHECK(!g_cros_settings); - g_cros_settings = new CrosSettings(); + g_cros_settings = new CrosSettings(DeviceSettingsService::Get()); } // static @@ -49,6 +49,27 @@ CrosSettings* CrosSettings::Get() { return g_cros_settings; } +CrosSettings::CrosSettings(DeviceSettingsService* device_settings_service) { + CrosSettingsProvider::NotifyObserversCallback notify_cb( + base::Bind(&CrosSettings::FireObservers, + // This is safe since |this| is never deleted. + base::Unretained(this))); + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kStubCrosSettings)) { + AddSettingsProvider(new StubCrosSettingsProvider(notify_cb)); + } else { + AddSettingsProvider( + new DeviceSettingsProvider(notify_cb, device_settings_service)); + } + // System settings are not mocked currently. + AddSettingsProvider(new SystemSettingsProvider(notify_cb)); +} + +CrosSettings::~CrosSettings() { + STLDeleteElements(&providers_); + STLDeleteValues(&settings_observers_); +} + bool CrosSettings::IsCrosSettings(const std::string& path) { return StartsWithASCII(path, kCrosSettingsPrefix, true); } @@ -298,27 +319,6 @@ CrosSettingsProvider* CrosSettings::GetProvider( return NULL; } -CrosSettings::CrosSettings() { - CrosSettingsProvider::NotifyObserversCallback notify_cb( - base::Bind(&CrosSettings::FireObservers, - // This is safe since |this| is never deleted. - base::Unretained(this))); - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kStubCrosSettings)) { - AddSettingsProvider(new StubCrosSettingsProvider(notify_cb)); - } else { - AddSettingsProvider( - new DeviceSettingsProvider(notify_cb, DeviceSettingsService::Get())); - } - // System settings are not mocked currently. - AddSettingsProvider(new SystemSettingsProvider(notify_cb)); -} - -CrosSettings::~CrosSettings() { - STLDeleteElements(&providers_); - STLDeleteValues(&settings_observers_); -} - void CrosSettings::FireObservers(const std::string& path) { DCHECK(CalledOnValidThread()); SettingsObserverMap::iterator observer_iterator = diff --git a/chrome/browser/chromeos/settings/cros_settings.h b/chrome/browser/chromeos/settings/cros_settings.h index 8a312aa..610d54a 100644 --- a/chrome/browser/chromeos/settings/cros_settings.h +++ b/chrome/browser/chromeos/settings/cros_settings.h @@ -24,6 +24,8 @@ class Value; namespace chromeos { +class DeviceSettingsService; + // This class manages per-device/global settings. class CrosSettings : public base::NonThreadSafe { public: @@ -33,6 +35,11 @@ class CrosSettings : public base::NonThreadSafe { static void Shutdown(); static CrosSettings* Get(); + // Creates a device settings service instance. This is meant for unit tests, + // production code uses the singleton returned by Get() above. + explicit CrosSettings(DeviceSettingsService* device_settings_service); + virtual ~CrosSettings(); + // Helper function to test if the given |path| is a valid cros setting. static bool IsCrosSettings(const std::string& path); @@ -99,9 +106,6 @@ class CrosSettings : public base::NonThreadSafe { private: friend class CrosSettingsTest; - CrosSettings(); - virtual ~CrosSettings(); - // Fires system setting change notification. void FireObservers(const std::string& path); diff --git a/chrome/browser/chromeos/settings/cros_settings_names.h b/chrome/browser/chromeos/settings/cros_settings_names.h index e04b9b2..d7d4bb4 100644 --- a/chrome/browser/chromeos/settings/cros_settings_names.h +++ b/chrome/browser/chromeos/settings/cros_settings_names.h @@ -23,15 +23,6 @@ extern const char kAccountsPrefDeviceLocalAccountAutoLoginId[]; extern const char kAccountsPrefDeviceLocalAccountAutoLoginDelay[]; extern const char kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled[]; -// This must match DeviceLocalAccountInfoProto.AccountType in -// chrome_device_policy.proto. -enum DeviceLocalAccountType { - // A login-less, policy-configured browsing session. - DEVICE_LOCAL_ACCOUNT_TYPE_PUBLIC_SESSION, - // An account that serves as a container for a single full-screen app. - DEVICE_LOCAL_ACCOUNT_TYPE_KIOSK_APP, -}; - extern const char kSignedDataRoamingEnabled[]; extern const char kSystemTimezonePolicy[]; diff --git a/chrome/browser/chromeos/settings/cros_settings_unittest.cc b/chrome/browser/chromeos/settings/cros_settings_unittest.cc index 00e162f..b119c98 100644 --- a/chrome/browser/chromeos/settings/cros_settings_unittest.cc +++ b/chrome/browser/chromeos/settings/cros_settings_unittest.cc @@ -13,6 +13,7 @@ #include "base/values.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/settings/cros_settings_names.h" +#include "chrome/browser/chromeos/settings/device_settings_service.h" #include "chrome/browser/chromeos/settings/device_settings_test_helper.h" #include "chrome/browser/policy/cloud/cloud_policy_constants.h" #include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h" @@ -32,6 +33,7 @@ class CrosSettingsTest : public testing::Test { : message_loop_(MessageLoop::TYPE_UI), ui_thread_(content::BrowserThread::UI, &message_loop_), local_state_(TestingBrowserProcess::GetGlobal()), + settings_(DeviceSettingsService::Get()), weak_factory_(this) {} virtual ~CrosSettingsTest() {} diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc index b738edb..6e0daff 100644 --- a/chrome/browser/chromeos/settings/device_settings_provider.cc +++ b/chrome/browser/chromeos/settings/device_settings_provider.cc @@ -17,6 +17,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/network_library.h" +#include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/settings/cros_settings_names.h" #include "chrome/browser/chromeos/settings/device_settings_cache.h" @@ -488,7 +489,7 @@ void DeviceSettingsProvider::DecodeLoginPolicies( entry->deprecated_public_session_id()); entry_dict->SetIntegerWithoutPathExpansion( kAccountsPrefDeviceLocalAccountsKeyType, - DEVICE_LOCAL_ACCOUNT_TYPE_PUBLIC_SESSION); + policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION); } account_list->Append(entry_dict.release()); } diff --git a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc index c9eb07b..503cd0f 100644 --- a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc +++ b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc @@ -13,6 +13,7 @@ #include "base/test/scoped_path_override.h" #include "base/values.h" #include "chrome/browser/chromeos/cros/cros_library.h" +#include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/settings/cros_settings_names.h" #include "chrome/browser/chromeos/settings/device_settings_test_helper.h" #include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h" @@ -280,7 +281,7 @@ TEST_F(DeviceSettingsProviderTest, LegacyDeviceLocalAccounts) { entry_dict->SetString(kAccountsPrefDeviceLocalAccountsKeyId, policy::PolicyBuilder::kFakeUsername); entry_dict->SetInteger(kAccountsPrefDeviceLocalAccountsKeyType, - DEVICE_LOCAL_ACCOUNT_TYPE_PUBLIC_SESSION); + policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION); expected_accounts.Append(entry_dict.release()); const base::Value* actual_accounts = provider_->Get(kAccountsPrefDeviceLocalAccounts); diff --git a/chrome/browser/policy/browser_policy_connector.cc b/chrome/browser/policy/browser_policy_connector.cc index a4781aa..3c3122a 100644 --- a/chrome/browser/policy/browser_policy_connector.cc +++ b/chrome/browser/policy/browser_policy_connector.cc @@ -188,7 +188,8 @@ void BrowserPolicyConnector::Init( device_local_account_policy_service_.reset( new DeviceLocalAccountPolicyService( chromeos::DBusThreadManager::Get()->GetSessionManagerClient(), - chromeos::DeviceSettingsService::Get())); + chromeos::DeviceSettingsService::Get(), + chromeos::CrosSettings::Get())); device_local_account_policy_service_->Connect( device_management_service_.get()); } diff --git a/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc b/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc index cfa016b..8313886 100644 --- a/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc @@ -69,7 +69,7 @@ void KioskAppMenuHandler::SendKioskApps() { const KioskAppManager::App& app_data = apps[i]; scoped_ptr<base::DictionaryValue> app_info(new base::DictionaryValue); - app_info->SetString("id", app_data.id); + app_info->SetString("id", app_data.app_id); app_info->SetString("label", app_data.name); // TODO(xiyuan): Replace data url with a URLDataSource. @@ -109,7 +109,7 @@ void KioskAppMenuHandler::HandleLaunchKioskApps(const base::ListValue* args) { ExistingUserController::current_controller()->PrepareKioskAppLaunch(); // KioskAppLauncher deletes itself when done. - (new KioskAppLauncher(app_id))->Start(); + (new KioskAppLauncher(KioskAppManager::Get(), app_id))->Start(); } void KioskAppMenuHandler::HandleCheckKioskAppLaunchError( diff --git a/chrome/browser/ui/webui/options/chromeos/kiosk_apps_handler.cc b/chrome/browser/ui/webui/options/chromeos/kiosk_apps_handler.cc index f813d2c..7c7ee91 100644 --- a/chrome/browser/ui/webui/options/chromeos/kiosk_apps_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/kiosk_apps_handler.cc @@ -39,12 +39,12 @@ void PopulateAppDict(const KioskAppManager::App& app_data, if (!app_data.icon.isNull()) icon_url = webui::GetBitmapDataUrl(*app_data.icon.bitmap()); - app_dict->SetString("id", app_data.id); + app_dict->SetString("id", app_data.app_id); app_dict->SetString("name", app_data.name); app_dict->SetString("iconURL", icon_url); app_dict->SetBoolean( "autoLaunch", - KioskAppManager::Get()->GetAutoLaunchApp() == app_data.id); + KioskAppManager::Get()->GetAutoLaunchApp() == app_data.app_id); app_dict->SetBoolean("isLoading", app_data.is_loading); } diff --git a/chrome/browser/ui/webui/policy_ui.cc b/chrome/browser/ui/webui/policy_ui.cc index 8a881e9..b6436bd 100644 --- a/chrome/browser/ui/webui/policy_ui.cc +++ b/chrome/browser/ui/webui/policy_ui.cc @@ -228,8 +228,8 @@ class DevicePolicyStatusProvider : public CloudPolicyCoreStatusProvider { }; // A cloud policy status provider that reads policy status from the policy core -// associated with the device-local account specified by |account_id| at -// construction time. The indirection via account ID and +// associated with the device-local account specified by |user_id| at +// construction time. The indirection via user ID and // DeviceLocalAccountPolicyService is necessary because the device-local account // may go away any time behind the scenes, at which point the status message // text will indicate CloudPolicyStore::STATUS_BAD_STATE. @@ -238,7 +238,7 @@ class DeviceLocalAccountPolicyStatusProvider public policy::DeviceLocalAccountPolicyService::Observer { public: DeviceLocalAccountPolicyStatusProvider( - const std::string& account_id, + const std::string& user_id, policy::DeviceLocalAccountPolicyService* service); virtual ~DeviceLocalAccountPolicyStatusProvider(); @@ -246,11 +246,11 @@ class DeviceLocalAccountPolicyStatusProvider virtual void GetStatus(base::DictionaryValue* dict) OVERRIDE; // policy::DeviceLocalAccountPolicyService::Observer implementation. - virtual void OnPolicyUpdated(const std::string& account_id) OVERRIDE; + virtual void OnPolicyUpdated(const std::string& user_id) OVERRIDE; virtual void OnDeviceLocalAccountsChanged() OVERRIDE; private: - const std::string account_id_; + const std::string user_id_; policy::DeviceLocalAccountPolicyService* service_; DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyStatusProvider); @@ -378,9 +378,9 @@ void DevicePolicyStatusProvider::GetStatus(base::DictionaryValue* dict) { } DeviceLocalAccountPolicyStatusProvider::DeviceLocalAccountPolicyStatusProvider( - const std::string& account_id, + const std::string& user_id, policy::DeviceLocalAccountPolicyService* service) - : account_id_(account_id), + : user_id_(user_id), service_(service) { service_->AddObserver(this); } @@ -393,7 +393,7 @@ DeviceLocalAccountPolicyStatusProvider:: void DeviceLocalAccountPolicyStatusProvider::GetStatus( base::DictionaryValue* dict) { const policy::DeviceLocalAccountPolicyBroker* broker = - service_->GetBrokerForAccount(account_id_); + service_->GetBrokerForUser(user_id_); if (broker) { GetStatusFromCore(broker->core(), dict); } else { @@ -402,15 +402,15 @@ void DeviceLocalAccountPolicyStatusProvider::GetStatus( policy::FormatStoreStatus( policy::CloudPolicyStore::STATUS_BAD_STATE, policy::CloudPolicyValidatorBase::VALIDATION_OK)); - dict->SetString("username", account_id_); + dict->SetString("username", std::string()); } ExtractDomainFromUsername(dict); dict->SetBoolean("publicAccount", true); } void DeviceLocalAccountPolicyStatusProvider::OnPolicyUpdated( - const std::string& account_id) { - if (account_id == account_id_) + const std::string& user_id) { + if (user_id == user_id_) NotifyStatusChange(); } |