Index: components/user_manager/known_user.cc |
diff --git a/components/user_manager/known_user.cc b/components/user_manager/known_user.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d78dff7d3cff673233dd883af48440aed4307d4f |
--- /dev/null |
+++ b/components/user_manager/known_user.cc |
@@ -0,0 +1,334 @@ |
+// 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. |
+ |
+#include "components/user_manager/known_user.h" |
+ |
+#include "base/logging.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/prefs/pref_registry_simple.h" |
+#include "base/prefs/scoped_user_pref_update.h" |
+#include "base/values.h" |
+#include "chromeos/login/user_names.h" |
+#include "components/user_manager/user_manager.h" |
+#include "google_apis/gaia/gaia_auth_util.h" |
+ |
+namespace user_manager { |
+namespace known_user { |
+namespace { |
+ |
+// A vector pref of preferences of known users. All new preferences should be |
+// placed in this list. |
+const char kKnownUsers[] = "KnownUsers"; |
+ |
+// Known user preferences keys (stored in Local State). |
+ |
+// Key of canonical e-mail value. |
+const char kCanonicalEmail[] = "email"; |
+ |
+// Key of obfuscated GAIA id value. |
+const char kGAIAIdKey[] = "gaia_id"; |
+ |
+// Key of whether this user ID refers to a SAML user. |
+const char kUsingSAMLKey[] = "using_saml"; |
+ |
+// Key of Device Id. |
+const char kDeviceId[] = "device_id"; |
+ |
+// Key of GAPS cookie. |
+const char kGAPSCookie[] = "gaps_cookie"; |
+ |
+// Key of the reason for re-auth. |
+const char kReauthReasonKey[] = "reauth_reason"; |
+ |
+PrefService* GetLocalState() { |
+ UserManager* user_manager = UserManager::Get(); |
+ if (user_manager) |
+ return user_manager->GetLocalState(); |
+ |
+ return nullptr; |
+} |
+ |
+// Checks if values in |dict| correspond with |account_id| identity. |
+bool UserMatches(const AccountId& account_id, |
+ const base::DictionaryValue& dict) { |
+ std::string value; |
+ |
+ // TODO(alemate): update code once user id is really a struct. |
+ bool has_gaia_id = dict.GetString(kGAIAIdKey, &value); |
+ if (has_gaia_id && account_id.GetGaiaId() == value) |
+ return true; |
+ |
+ bool has_email = dict.GetString(kCanonicalEmail, &value); |
+ if (has_email && account_id.GetUserEmail() == value) |
+ return true; |
+ |
+ return false; |
+} |
+ |
+// Fills relevant |dict| values based on |account_id|. |
+void UpdateIdentity(const AccountId& account_id, base::DictionaryValue& dict) { |
+ dict.SetString(kCanonicalEmail, account_id.GetUserEmail()); |
+} |
+ |
+} // namespace |
+ |
+bool FindPrefs(const AccountId& account_id, |
+ const base::DictionaryValue** out_value) { |
+ PrefService* local_state = GetLocalState(); |
+ |
+ // Local State may not be initialized in tests. |
+ if (!local_state) |
+ return false; |
+ |
+ // UserManager is usually NULL in unit tests. |
+ UserManager* user_manager = UserManager::Get(); |
+ if (user_manager && |
+ user_manager->IsUserNonCryptohomeDataEphemeral(account_id)) |
+ return false; |
+ |
+ 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(account_id, *element)) { |
+ known_users->GetDictionary(i, out_value); |
+ return true; |
+ } |
+ } |
+ } |
+ return false; |
+} |
+ |
+void UpdatePrefs(const AccountId& account_id, |
+ const base::DictionaryValue& values, |
+ bool clear) { |
+ PrefService* local_state = GetLocalState(); |
+ |
+ // Local State may not be initialized in tests. |
+ if (!local_state) |
+ return; |
+ |
+ // UserManager is usually NULL in unit tests. |
+ UserManager* user_manager = UserManager::Get(); |
+ if (user_manager && |
+ user_manager->IsUserNonCryptohomeDataEphemeral(account_id)) |
+ return; |
+ |
+ ListPrefUpdate update(local_state, kKnownUsers); |
+ for (size_t i = 0; i < update->GetSize(); ++i) { |
+ base::DictionaryValue* element = nullptr; |
+ if (update->GetDictionary(i, &element)) { |
+ if (UserMatches(account_id, *element)) { |
+ if (clear) |
+ element->Clear(); |
+ element->MergeDictionary(&values); |
+ UpdateIdentity(account_id, *element); |
+ return; |
+ } |
+ } |
+ } |
+ scoped_ptr<base::DictionaryValue> new_value(new base::DictionaryValue()); |
+ new_value->MergeDictionary(&values); |
+ UpdateIdentity(account_id, *new_value); |
+ update->Append(new_value.release()); |
+} |
+ |
+bool GetStringPref(const AccountId& account_id, |
+ const std::string& path, |
+ std::string* out_value) { |
+ const base::DictionaryValue* user_pref_dict = nullptr; |
+ if (!FindPrefs(account_id, &user_pref_dict)) |
+ return false; |
+ |
+ return user_pref_dict->GetString(path, out_value); |
+} |
+ |
+void SetStringPref(const AccountId& account_id, |
+ const std::string& path, |
+ const std::string& in_value) { |
+ PrefService* local_state = GetLocalState(); |
+ |
+ // Local State may not be initialized in tests. |
+ if (!local_state) |
+ return; |
+ |
+ ListPrefUpdate update(local_state, kKnownUsers); |
+ base::DictionaryValue dict; |
+ dict.SetString(path, in_value); |
+ UpdatePrefs(account_id, dict, false); |
+} |
+ |
+bool GetBooleanPref(const AccountId& account_id, |
+ const std::string& path, |
+ bool* out_value) { |
+ const base::DictionaryValue* user_pref_dict = nullptr; |
+ if (!FindPrefs(account_id, &user_pref_dict)) |
+ return false; |
+ |
+ return user_pref_dict->GetBoolean(path, out_value); |
+} |
+ |
+void SetBooleanPref(const AccountId& account_id, |
+ const std::string& path, |
+ const bool in_value) { |
+ PrefService* local_state = GetLocalState(); |
+ |
+ // Local State may not be initialized in tests. |
+ if (!local_state) |
+ return; |
+ |
+ ListPrefUpdate update(local_state, kKnownUsers); |
+ base::DictionaryValue dict; |
+ dict.SetBoolean(path, in_value); |
+ UpdatePrefs(account_id, dict, false); |
+} |
+ |
+bool GetIntegerPref(const AccountId& account_id, |
+ const std::string& path, |
+ int* out_value) { |
+ const base::DictionaryValue* user_pref_dict = nullptr; |
+ if (!FindPrefs(account_id, &user_pref_dict)) |
+ return false; |
+ return user_pref_dict->GetInteger(path, out_value); |
+} |
+ |
+void SetIntegerPref(const AccountId& account_id, |
+ const std::string& path, |
+ const int in_value) { |
+ PrefService* local_state = GetLocalState(); |
+ |
+ // Local State may not be initialized in tests. |
+ if (!local_state) |
+ return; |
+ |
+ ListPrefUpdate update(local_state, kKnownUsers); |
+ base::DictionaryValue dict; |
+ dict.SetInteger(path, in_value); |
+ UpdatePrefs(account_id, dict, false); |
+} |
+ |
+AccountId GetAccountId(const std::string& user_email, |
+ const std::string& gaia_id) { |
+ // In tests empty accounts are possible. |
+ if (user_email.empty() && gaia_id.empty()) |
+ return EmptyAccountId(); |
+ |
+ if (user_email == chromeos::login::kStubUser) |
+ return chromeos::login::StubAccountId(); |
+ |
+ if (user_email == chromeos::login::kGuestUserName) |
+ return chromeos::login::GuestAccountId(); |
+ |
+ // We can have several users with the same gaia_id but different e-mails. |
+ // The opposite case is not possible. |
+ std::string stored_gaia_id; |
+ const std::string sanitized_email = |
+ user_email.empty() |
+ ? std::string() |
+ : gaia::CanonicalizeEmail(gaia::SanitizeEmail(user_email)); |
+ |
+ if (!sanitized_email.empty() && |
+ GetStringPref(AccountId::FromUserEmail(sanitized_email), kGAIAIdKey, |
+ &stored_gaia_id)) { |
+ if (!gaia_id.empty() && gaia_id != stored_gaia_id) |
+ LOG(ERROR) << "User gaia id has changed. Sync will not work."; |
+ |
+ // gaia_id is associated with cryptohome. |
+ return AccountId::FromUserEmailGaiaId(sanitized_email, stored_gaia_id); |
+ } |
+ |
+ std::string stored_email; |
+ // GetStringPref() returns the first user record that matches |
+ // given ID. So we will get the first one if there are multiples. |
+ if (!gaia_id.empty() && GetStringPref(AccountId::FromGaiaId(gaia_id), |
+ kCanonicalEmail, &stored_email)) { |
+ return AccountId::FromUserEmailGaiaId(stored_email, gaia_id); |
+ } |
+ |
+ return (gaia_id.empty() |
+ ? AccountId::FromUserEmail(user_email) |
+ : AccountId::FromUserEmailGaiaId(user_email, gaia_id)); |
+} |
+ |
+void UpdateGaiaID(const AccountId& account_id, const std::string& gaia_id) { |
+ SetStringPref(account_id, kGAIAIdKey, gaia_id); |
+} |
+ |
+bool FindGaiaID(const AccountId& account_id, std::string* out_value) { |
+ return GetStringPref(account_id, kGAIAIdKey, out_value); |
+} |
+ |
+void SetDeviceId(const AccountId& account_id, const std::string& device_id) { |
+ const std::string known_device_id = GetDeviceId(account_id); |
+ if (!known_device_id.empty() && device_id != known_device_id) { |
+ NOTREACHED() << "Trying to change device ID for known user."; |
+ } |
+ SetStringPref(account_id, kDeviceId, device_id); |
+} |
+ |
+std::string GetDeviceId(const AccountId& account_id) { |
+ std::string device_id; |
+ if (GetStringPref(account_id, kDeviceId, &device_id)) { |
+ return device_id; |
+ } |
+ return std::string(); |
+} |
+ |
+void SetGAPSCookie(const AccountId& account_id, |
+ const std::string& gaps_cookie) { |
+ SetStringPref(account_id, kGAPSCookie, gaps_cookie); |
+} |
+ |
+std::string GetGAPSCookie(const AccountId& account_id) { |
+ std::string gaps_cookie; |
+ if (GetStringPref(account_id, kGAPSCookie, &gaps_cookie)) { |
+ return gaps_cookie; |
+ } |
+ return std::string(); |
+} |
+ |
+void UpdateUsingSAML(const AccountId& account_id, const bool using_saml) { |
+ SetBooleanPref(account_id, kUsingSAMLKey, using_saml); |
+} |
+ |
+bool IsUsingSAML(const AccountId& account_id) { |
+ bool using_saml; |
+ if (GetBooleanPref(account_id, kUsingSAMLKey, &using_saml)) |
+ return using_saml; |
+ return false; |
+} |
+ |
+void UpdateReauthReason(const AccountId& account_id, const int reauth_reason) { |
+ SetIntegerPref(account_id, kReauthReasonKey, reauth_reason); |
+} |
+ |
+bool FindReauthReason(const AccountId& account_id, int* out_value) { |
+ return GetIntegerPref(account_id, kReauthReasonKey, out_value); |
+} |
+ |
+void RemovePrefs(const AccountId& account_id) { |
+ PrefService* local_state = GetLocalState(); |
+ |
+ // Local State may not be initialized in tests. |
+ if (!local_state) |
+ return; |
+ |
+ ListPrefUpdate update(local_state, kKnownUsers); |
+ for (size_t i = 0; i < update->GetSize(); ++i) { |
+ base::DictionaryValue* element = nullptr; |
+ if (update->GetDictionary(i, &element)) { |
+ if (UserMatches(account_id, *element)) { |
+ update->Remove(i, nullptr); |
+ break; |
+ } |
+ } |
+ } |
+} |
+ |
+void RegisterPrefs(PrefRegistrySimple* registry) { |
+ registry->RegisterListPref(kKnownUsers); |
+} |
+ |
+} // namespace known_user |
+} // namespace user_manager |