From 35a5775571bf93a67b17e28a5757ae347f45c631 Mon Sep 17 00:00:00 2001 From: antrim Date: Wed, 11 Mar 2015 05:42:18 -0700 Subject: [PATCH] Add per-user preferences support. BUG=462823 R=nkostylev@chromium.org Review URL: https://codereview.chromium.org/993023002 Cr-Commit-Position: refs/heads/master@{#320071} --- components/user_manager.gypi | 1 + components/user_manager/BUILD.gn | 1 + components/user_manager/user_id.h | 15 +++++ components/user_manager/user_manager_base.cc | 86 ++++++++++++++++++++++++++++ components/user_manager/user_manager_base.h | 20 +++++++ 5 files changed, 123 insertions(+) create mode 100644 components/user_manager/user_id.h diff --git a/components/user_manager.gypi b/components/user_manager.gypi index 027e41580bb4..9154cce77c0f 100644 --- a/components/user_manager.gypi +++ b/components/user_manager.gypi @@ -19,6 +19,7 @@ 'user_manager/remove_user_delegate.h', 'user_manager/user.cc', 'user_manager/user.h', + 'user_manager/user_id.h', 'user_manager/user_image/default_user_images.cc', 'user_manager/user_image/default_user_images.h', 'user_manager/user_image/user_image.cc', diff --git a/components/user_manager/BUILD.gn b/components/user_manager/BUILD.gn index 59dbd92f0ba1..1d98ed4bcec3 100644 --- a/components/user_manager/BUILD.gn +++ b/components/user_manager/BUILD.gn @@ -26,6 +26,7 @@ component("user_manager") { "remove_user_delegate.h", "user.cc", "user.h", + "user_id.h", "user_image/default_user_images.cc", "user_image/default_user_images.h", "user_image/user_image.cc", diff --git a/components/user_manager/user_id.h b/components/user_manager/user_id.h new file mode 100644 index 000000000000..fb89ddd10139 --- /dev/null +++ b/components/user_manager/user_id.h @@ -0,0 +1,15 @@ +// Copyright 2015 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 COMPONENTS_USER_MANAGER_USER_ID_H_ +#define COMPONENTS_USER_MANAGER_USER_ID_H_ + +namespace user_manager { + +// Type that contains enough information to identify user on ChromeOS. +typedef std::string UserID; + +} // namespace user_manager + +#endif // COMPONENTS_USER_MANAGER_USER_ID_H_ diff --git a/components/user_manager/user_manager_base.cc b/components/user_manager/user_manager_base.cc index c6c7ec0d2ee0..364b135f63b5 100644 --- a/components/user_manager/user_manager_base.cc +++ b/components/user_manager/user_manager_base.cc @@ -70,6 +70,16 @@ const char kLastLoggedInGaiaUser[] = "LastLoggedInRegularUser"; // session restore. const char kLastActiveUser[] = "LastActiveUser"; +// A vector pref of preferences of known users. All new preferences should be +// placed in this list. +const char kKnownUsers[] = "KnownUsers"; + +// Key of obfuscated GAIA id value. +const char kGAIAIdKey[] = "gaia_id"; + +// Key of canonical e-mail value. +const char kCanonicalEmail[] = "email"; + // Upper bound for a histogram metric reporting the amount of time between // one regular user logging out and a different regular user logging in. const int kLogoutToLoginDelayMaxSec = 1800; @@ -91,11 +101,33 @@ void ResolveLocale(const std::string& raw_locale, ignore_result(l10n_util::CheckAndResolveLocale(raw_locale, resolved_locale)); } +// Checks if values in |dict| correspond with |user_id| identity. +bool UserMatches(const UserID& user_id, const base::DictionaryValue& dict) { + std::string value; + + bool has_email = dict.GetString(kCanonicalEmail, &value); + if (has_email && user_id == value) + return true; + + // TODO(antrim): update code once user id is really a struct. + bool has_gaia_id = dict.GetString(kGAIAIdKey, &value); + if (has_gaia_id && user_id == value) + return true; + + return false; +} + +// Fills relevant |dict| values based on |user_id|. +void UpdateIdentity(const UserID& user_id, base::DictionaryValue& dict) { + dict.SetString(kCanonicalEmail, user_id); +} + } // namespace // static void UserManagerBase::RegisterPrefs(PrefRegistrySimple* registry) { registry->RegisterListPref(kRegularUsers); + registry->RegisterListPref(kKnownUsers); registry->RegisterStringPref(kLastLoggedInGaiaUser, std::string()); registry->RegisterDictionaryPref(kUserDisplayName); registry->RegisterDictionaryPref(kUserGivenName); @@ -939,11 +971,52 @@ void UserManagerBase::RemoveNonCryptohomeData(const std::string& user_id) { DictionaryPrefUpdate prefs_force_online_update(prefs, kUserForceOnlineSignin); prefs_force_online_update->RemoveWithoutPathExpansion(user_id, NULL); + RemoveKnowUserPrefs(user_id); + std::string last_active_user = GetLocalState()->GetString(kLastActiveUser); if (user_id == last_active_user) GetLocalState()->SetString(kLastActiveUser, std::string()); } +bool UserManagerBase::FindKnowUserPrefs( + const UserID& user_id, + const base::DictionaryValue** out_value) { + PrefService* local_state = GetLocalState(); + const base::ListValue* known_users = local_state->GetList(kKnownUsers); + for (size_t i = 0; i < known_users->GetSize(); ++i) { + const base::DictionaryValue* element = nullptr; + if (known_users->GetDictionary(i, &element)) { + if (UserMatches(user_id, *element)) { + known_users->GetDictionary(i, out_value); + return true; + } + } + } + return false; +} + +void UserManagerBase::UpdateKnowUserPrefs(const UserID& user_id, + const base::DictionaryValue& values, + bool clear) { + ListPrefUpdate update(GetLocalState(), kKnownUsers); + for (size_t i = 0; i < update->GetSize(); ++i) { + base::DictionaryValue* element = nullptr; + if (update->GetDictionary(i, &element)) { + if (UserMatches(user_id, *element)) { + if (clear) + element->Clear(); + element->MergeDictionary(&values); + UpdateIdentity(user_id, *element); + return; + } + } + } + scoped_ptr new_value(new base::DictionaryValue()); + new_value->MergeDictionary(&values); + UpdateIdentity(user_id, *new_value); + update->Append(new_value.release()); +} + User* UserManagerBase::RemoveRegularOrSupervisedUserFromList( const std::string& user_id) { ListPrefUpdate prefs_users_update(GetLocalState(), kRegularUsers); @@ -963,6 +1036,19 @@ User* UserManagerBase::RemoveRegularOrSupervisedUserFromList( return user; } +void UserManagerBase::RemoveKnowUserPrefs(const UserID& user_id) { + ListPrefUpdate update(GetLocalState(), kKnownUsers); + for (size_t i = 0; i < update->GetSize(); ++i) { + base::DictionaryValue* element = nullptr; + if (update->GetDictionary(i, &element)) { + if (UserMatches(user_id, *element)) { + update->Remove(i, nullptr); + break; + } + } + } +} + void UserManagerBase::NotifyActiveUserChanged(const User* active_user) { DCHECK(task_runner_->RunsTasksOnCurrentThread()); FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver, diff --git a/components/user_manager/user_manager_base.h b/components/user_manager/user_manager_base.h index cddf3cc73f05..4faae77f2dfc 100644 --- a/components/user_manager/user_manager_base.h +++ b/components/user_manager/user_manager_base.h @@ -15,6 +15,7 @@ #include "base/synchronization/lock.h" #include "base/time/time.h" #include "components/user_manager/user.h" +#include "components/user_manager/user_id.h" #include "components/user_manager/user_manager.h" #include "components/user_manager/user_manager_export.h" #include "components/user_manager/user_type.h" @@ -23,6 +24,7 @@ class PrefService; class PrefRegistrySimple; namespace base { +class DictionaryValue; class ListValue; class TaskRunner; } @@ -200,6 +202,21 @@ class USER_MANAGER_EXPORT UserManagerBase : public UserManager { // avatar, OAuth token status, display name, display email). virtual void RemoveNonCryptohomeData(const std::string& user_id); + // Methods for storage/retrieval of per-user properties in Local State. + + // Performs a lookup of properties associated with |user_id|. If found, + // returns |true| and fills |out_value|. |out_value| can be NULL, if + // only existence check is required. + bool FindKnowUserPrefs(const UserID& user_id, + const base::DictionaryValue** out_value); + + // Updates (or creates) properties associated with |user_id| based + // on |values|. |clear| defines if existing properties are cleared (|true|) + // or if it is just a incremental update (|false|). + void UpdateKnowUserPrefs(const UserID& user_id, + const base::DictionaryValue& values, + bool clear); + // Check for a particular user type. // Returns true if |user_id| represents demo app. @@ -325,6 +342,9 @@ class USER_MANAGER_EXPORT UserManagerBase : public UserManager { void DoUpdateAccountLocale(const std::string& user_id, scoped_ptr resolved_locale); + // Removes all user preferences associated with |user_id|. + void RemoveKnowUserPrefs(const UserID& user_id); + // Indicates stage of loading user from prefs. UserLoadStage user_loading_stage_; -- 2.11.4.GIT