known_user.cc 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/user_manager/known_user.h"
  5. #include <stddef.h>
  6. #include <memory>
  7. #include <utility>
  8. #include "base/json/values_util.h"
  9. #include "base/logging.h"
  10. #include "base/metrics/histogram_macros.h"
  11. #include "base/strings/string_piece_forward.h"
  12. #include "base/time/time.h"
  13. #include "base/values.h"
  14. #include "components/account_id/account_id.h"
  15. #include "components/prefs/pref_registry_simple.h"
  16. #include "components/prefs/scoped_user_pref_update.h"
  17. #include "components/user_manager/user_manager.h"
  18. #include "google_apis/gaia/gaia_auth_util.h"
  19. #include "third_party/abseil-cpp/absl/types/optional.h"
  20. namespace user_manager {
  21. namespace {
  22. // A vector pref of preferences of known users. All new preferences should be
  23. // placed in this list.
  24. const char kKnownUsers[] = "KnownUsers";
  25. // Known user preferences keys (stored in Local State). All keys should be
  26. // listed in kReservedKeys or kObsoleteKeys below.
  27. // Key of canonical e-mail value.
  28. const char kCanonicalEmail[] = "email";
  29. // Key of obfuscated GAIA id value.
  30. const char kGAIAIdKey[] = "gaia_id";
  31. // Key of obfuscated object guid value for Active Directory accounts.
  32. const char kObjGuidKey[] = "obj_guid";
  33. // Key of account type.
  34. const char kAccountTypeKey[] = "account_type";
  35. // Key of whether this user ID refers to a SAML user.
  36. const char kUsingSAMLKey[] = "using_saml";
  37. // Key of whether this user authenticated via SAML using the principals API.
  38. const char kIsUsingSAMLPrincipalsAPI[] = "using_saml_principals_api";
  39. // Key of Device Id.
  40. const char kDeviceId[] = "device_id";
  41. // Key of GAPS cookie.
  42. const char kGAPSCookie[] = "gaps_cookie";
  43. // Key of the reason for re-auth.
  44. const char kReauthReasonKey[] = "reauth_reason";
  45. // Key for the GaiaId migration status.
  46. const char kGaiaIdMigrationObsolete[] = "gaia_id_migration";
  47. // Key of the boolean flag telling if a minimal user home migration has been
  48. // attempted. This flag is not used since M88 and is only kept here to be able
  49. // to remove it from existing entries.
  50. const char kMinimalMigrationAttemptedObsolete[] = "minimal_migration_attempted";
  51. // Key of the boolean flag telling if user session requires policy.
  52. const char kProfileRequiresPolicy[] = "profile_requires_policy";
  53. // Key of the boolean flag telling if user is ephemeral and should be removed
  54. // from the local state on logout.
  55. const char kIsEphemeral[] = "is_ephemeral";
  56. // Key of the list value that stores challenge-response authentication keys.
  57. const char kChallengeResponseKeys[] = "challenge_response_keys";
  58. const char kLastOnlineSignin[] = "last_online_singin";
  59. const char kOfflineSigninLimitObsolete[] = "offline_signin_limit";
  60. const char kOfflineSigninLimit[] = "offline_signin_limit2";
  61. // Key of the boolean flag telling if user is enterprise managed.
  62. const char kIsEnterpriseManaged[] = "is_enterprise_managed";
  63. // Key of the name of the entity (either a domain or email address) that manages
  64. // the policies for this account.
  65. const char kAccountManager[] = "enterprise_account_manager";
  66. // Key of the last input method user used which is suitable for login/lock
  67. // screen.
  68. const char kLastInputMethod[] = "last_input_method";
  69. // Key of the PIN auto submit length.
  70. const char kPinAutosubmitLength[] = "pin_autosubmit_length";
  71. // Key for the PIN auto submit backfill needed indicator.
  72. const char kPinAutosubmitBackfillNeeded[] = "pin_autosubmit_backfill_needed";
  73. // Sync token for SAML password multi-device sync
  74. const char kPasswordSyncToken[] = "password_sync_token";
  75. // Major version in which the user completed the onboarding flow.
  76. const char kOnboardingCompletedVersion[] = "onboarding_completed_version";
  77. // Last screen shown in the onboarding flow.
  78. const char kPendingOnboardingScreen[] = "onboarding_screen_pending";
  79. // List containing all the known user preferences keys.
  80. const char* kReservedKeys[] = {kCanonicalEmail,
  81. kGAIAIdKey,
  82. kObjGuidKey,
  83. kAccountTypeKey,
  84. kUsingSAMLKey,
  85. kIsUsingSAMLPrincipalsAPI,
  86. kDeviceId,
  87. kGAPSCookie,
  88. kReauthReasonKey,
  89. kProfileRequiresPolicy,
  90. kIsEphemeral,
  91. kChallengeResponseKeys,
  92. kLastOnlineSignin,
  93. kOfflineSigninLimit,
  94. kIsEnterpriseManaged,
  95. kAccountManager,
  96. kLastInputMethod,
  97. kPinAutosubmitLength,
  98. kPinAutosubmitBackfillNeeded,
  99. kPasswordSyncToken,
  100. kOnboardingCompletedVersion,
  101. kPendingOnboardingScreen};
  102. // List containing all known user preference keys that used to be reserved and
  103. // are now obsolete.
  104. const char* kObsoleteKeys[] = {
  105. kMinimalMigrationAttemptedObsolete,
  106. kGaiaIdMigrationObsolete,
  107. kOfflineSigninLimitObsolete,
  108. };
  109. PrefService* GetLocalStateLegacy() {
  110. if (!UserManager::IsInitialized())
  111. return nullptr;
  112. return UserManager::Get()->GetLocalState();
  113. }
  114. // Checks if values in |dict| correspond with |account_id| identity.
  115. bool UserMatches(const AccountId& account_id, const base::Value& dict) {
  116. const std::string* account_type = dict.FindStringKey(kAccountTypeKey);
  117. if (account_id.GetAccountType() != AccountType::UNKNOWN && account_type &&
  118. account_id.GetAccountType() !=
  119. AccountId::StringToAccountType(*account_type)) {
  120. return false;
  121. }
  122. // TODO(alemate): update code once user id is really a struct.
  123. // TODO(https://crbug.com/1190902): If the gaia id or GUID doesn't match,
  124. // this function should likely be returning false even if the e-mail matches.
  125. switch (account_id.GetAccountType()) {
  126. case AccountType::GOOGLE: {
  127. const std::string* gaia_id = dict.FindStringKey(kGAIAIdKey);
  128. if (gaia_id && account_id.GetGaiaId() == *gaia_id)
  129. return true;
  130. break;
  131. }
  132. case AccountType::ACTIVE_DIRECTORY: {
  133. const std::string* obj_guid = dict.FindStringKey(kObjGuidKey);
  134. if (obj_guid && account_id.GetObjGuid() == *obj_guid)
  135. return true;
  136. break;
  137. }
  138. case AccountType::UNKNOWN: {
  139. }
  140. }
  141. const std::string* email = dict.FindStringKey(kCanonicalEmail);
  142. if (email && account_id.GetUserEmail() == *email)
  143. return true;
  144. return false;
  145. }
  146. // Fills relevant |dict| values based on |account_id|.
  147. // TODO(crbug.com/1287074): Consider a refactor to use base::Value::DictStorage.
  148. // This would require |dict| to not be modified in-place.
  149. void UpdateIdentity(const AccountId& account_id, base::Value& dict) {
  150. DCHECK(dict.is_dict());
  151. if (!account_id.GetUserEmail().empty())
  152. dict.SetStringKey(kCanonicalEmail, account_id.GetUserEmail());
  153. switch (account_id.GetAccountType()) {
  154. case AccountType::GOOGLE:
  155. if (!account_id.GetGaiaId().empty())
  156. dict.SetStringKey(kGAIAIdKey, account_id.GetGaiaId());
  157. break;
  158. case AccountType::ACTIVE_DIRECTORY:
  159. if (!account_id.GetObjGuid().empty())
  160. dict.SetStringKey(kObjGuidKey, account_id.GetObjGuid());
  161. break;
  162. case AccountType::UNKNOWN:
  163. return;
  164. }
  165. dict.SetStringKey(kAccountTypeKey, AccountId::AccountTypeToString(
  166. account_id.GetAccountType()));
  167. }
  168. } // namespace
  169. KnownUser::KnownUser(PrefService* local_state) : local_state_(local_state) {
  170. DCHECK(local_state);
  171. }
  172. KnownUser::~KnownUser() = default;
  173. const base::Value* KnownUser::FindPrefs(const AccountId& account_id) const {
  174. // UserManager is usually NULL in unit tests.
  175. if (account_id.GetAccountType() != AccountType::ACTIVE_DIRECTORY &&
  176. UserManager::IsInitialized() &&
  177. UserManager::Get()->IsUserNonCryptohomeDataEphemeral(account_id)) {
  178. return nullptr;
  179. }
  180. if (!account_id.is_valid())
  181. return nullptr;
  182. const base::Value::List& known_users =
  183. local_state_->GetValueList(kKnownUsers);
  184. for (const base::Value& element_value : known_users) {
  185. if (element_value.is_dict()) {
  186. if (UserMatches(account_id, element_value)) {
  187. return &element_value;
  188. }
  189. }
  190. }
  191. return nullptr;
  192. }
  193. void KnownUser::SetPath(const AccountId& account_id,
  194. const std::string& path,
  195. absl::optional<base::Value> opt_value) {
  196. // UserManager is usually NULL in unit tests.
  197. if (account_id.GetAccountType() != AccountType::ACTIVE_DIRECTORY &&
  198. UserManager::IsInitialized() &&
  199. UserManager::Get()->IsUserNonCryptohomeDataEphemeral(account_id)) {
  200. return;
  201. }
  202. if (!account_id.is_valid())
  203. return;
  204. ListPrefUpdate update(local_state_, kKnownUsers);
  205. for (base::Value& element_value : update->GetList()) {
  206. if (element_value.is_dict()) {
  207. if (UserMatches(account_id, element_value)) {
  208. if (opt_value.has_value())
  209. element_value.SetPath(path, std::move(opt_value).value());
  210. else
  211. element_value.RemovePath(path);
  212. UpdateIdentity(account_id, element_value);
  213. return;
  214. }
  215. }
  216. }
  217. if (!opt_value.has_value())
  218. return;
  219. base::Value new_dict(base::Value::Type::DICTIONARY);
  220. new_dict.SetPath(path, std::move(opt_value).value());
  221. UpdateIdentity(account_id, new_dict);
  222. update->Append(std::move(new_dict));
  223. }
  224. const std::string* KnownUser::FindStringPath(const AccountId& account_id,
  225. base::StringPiece path) const {
  226. const base::Value* user_pref_dict = FindPrefs(account_id);
  227. if (!user_pref_dict)
  228. return nullptr;
  229. return user_pref_dict->FindStringPath(path);
  230. }
  231. bool KnownUser::GetStringPrefForTest(const AccountId& account_id,
  232. const std::string& path,
  233. std::string* out_value) {
  234. const std::string* res = FindStringPath(account_id, path);
  235. if (out_value && res)
  236. *out_value = *res;
  237. return res;
  238. }
  239. void KnownUser::SetStringPref(const AccountId& account_id,
  240. const std::string& path,
  241. const std::string& in_value) {
  242. SetPath(account_id, path, base::Value(in_value));
  243. }
  244. absl::optional<bool> KnownUser::FindBoolPath(const AccountId& account_id,
  245. base::StringPiece path) const {
  246. const base::Value* user_pref_dict = FindPrefs(account_id);
  247. if (!user_pref_dict)
  248. return absl::nullopt;
  249. return user_pref_dict->FindBoolPath(path);
  250. }
  251. bool KnownUser::GetBooleanPrefForTest(const AccountId& account_id,
  252. const std::string& path,
  253. bool* out_value) {
  254. auto opt_val = FindBoolPath(account_id, path);
  255. if (out_value && opt_val.has_value())
  256. *out_value = opt_val.value();
  257. return opt_val.has_value();
  258. }
  259. void KnownUser::SetBooleanPref(const AccountId& account_id,
  260. const std::string& path,
  261. const bool in_value) {
  262. SetPath(account_id, path, base::Value(in_value));
  263. }
  264. absl::optional<int> KnownUser::FindIntPath(const AccountId& account_id,
  265. base::StringPiece path) const {
  266. const base::Value* user_pref_dict = FindPrefs(account_id);
  267. if (!user_pref_dict)
  268. return absl::nullopt;
  269. return user_pref_dict->FindIntPath(path);
  270. }
  271. bool KnownUser::GetIntegerPrefForTest(const AccountId& account_id,
  272. const std::string& path,
  273. int* out_value) {
  274. auto opt_val = FindIntPath(account_id, path);
  275. if (out_value && opt_val.has_value())
  276. *out_value = opt_val.value();
  277. return opt_val.has_value();
  278. }
  279. void KnownUser::SetIntegerPref(const AccountId& account_id,
  280. const std::string& path,
  281. const int in_value) {
  282. SetPath(account_id, path, base::Value(in_value));
  283. }
  284. bool KnownUser::GetPrefForTest(const AccountId& account_id,
  285. const std::string& path,
  286. const base::Value** out_value) {
  287. *out_value = FindPath(account_id, path);
  288. return *out_value != nullptr;
  289. }
  290. const base::Value* KnownUser::FindPath(const AccountId& account_id,
  291. const std::string& path) const {
  292. const base::Value* user_pref_dict = FindPrefs(account_id);
  293. if (!user_pref_dict)
  294. return nullptr;
  295. return user_pref_dict->FindPath(path);
  296. }
  297. void KnownUser::RemovePref(const AccountId& account_id,
  298. const std::string& path) {
  299. // Prevent removing keys that are used internally.
  300. for (const std::string& key : kReservedKeys)
  301. CHECK_NE(path, key);
  302. SetPath(account_id, path, absl::nullopt);
  303. }
  304. AccountId KnownUser::GetAccountId(const std::string& user_email,
  305. const std::string& id,
  306. const AccountType& account_type) {
  307. DCHECK((id.empty() && account_type == AccountType::UNKNOWN) ||
  308. (!id.empty() && account_type != AccountType::UNKNOWN));
  309. // In tests empty accounts are possible.
  310. if (user_email.empty() && id.empty() &&
  311. account_type == AccountType::UNKNOWN) {
  312. return EmptyAccountId();
  313. }
  314. AccountId result(EmptyAccountId());
  315. // UserManager is usually NULL in unit tests.
  316. if (account_type == AccountType::UNKNOWN && UserManager::IsInitialized() &&
  317. UserManager::Get()->GetPlatformKnownUserId(user_email, id, &result)) {
  318. return result;
  319. }
  320. const std::string sanitized_email =
  321. user_email.empty()
  322. ? std::string()
  323. : gaia::CanonicalizeEmail(gaia::SanitizeEmail(user_email));
  324. if (!sanitized_email.empty()) {
  325. const AccountId account_id(AccountId::FromUserEmail(sanitized_email));
  326. if (const std::string* stored_gaia_id =
  327. FindStringPath(account_id, kGAIAIdKey)) {
  328. if (!id.empty()) {
  329. DCHECK(account_type == AccountType::GOOGLE);
  330. if (id != *stored_gaia_id)
  331. LOG(ERROR) << "User gaia id has changed. Sync will not work.";
  332. }
  333. // gaia_id is associated with cryptohome.
  334. return AccountId::FromUserEmailGaiaId(sanitized_email, *stored_gaia_id);
  335. }
  336. if (const std::string* stored_obj_guid =
  337. FindStringPath(account_id, kObjGuidKey)) {
  338. if (!id.empty()) {
  339. DCHECK(account_type == AccountType::ACTIVE_DIRECTORY);
  340. if (id != *stored_obj_guid)
  341. LOG(ERROR) << "User object guid has changed. Sync will not work.";
  342. }
  343. // obj_guid is associated with cryptohome.
  344. return AccountId::AdFromUserEmailObjGuid(sanitized_email,
  345. *stored_obj_guid);
  346. }
  347. }
  348. switch (account_type) {
  349. case AccountType::GOOGLE:
  350. if (const std::string* stored_email =
  351. FindStringPath(AccountId::FromGaiaId(id), kCanonicalEmail)) {
  352. return AccountId::FromUserEmailGaiaId(*stored_email, id);
  353. }
  354. return AccountId::FromUserEmailGaiaId(sanitized_email, id);
  355. case AccountType::ACTIVE_DIRECTORY:
  356. return AccountId::AdFromUserEmailObjGuid(sanitized_email, id);
  357. case AccountType::UNKNOWN:
  358. return AccountId::FromUserEmail(sanitized_email);
  359. }
  360. NOTREACHED();
  361. return EmptyAccountId();
  362. }
  363. std::vector<AccountId> KnownUser::GetKnownAccountIds() {
  364. std::vector<AccountId> result;
  365. const base::Value::List& known_users =
  366. local_state_->GetValueList(kKnownUsers);
  367. for (const base::Value& element_value : known_users) {
  368. if (element_value.is_dict()) {
  369. const std::string* email = element_value.FindStringKey(kCanonicalEmail);
  370. const std::string* gaia_id = element_value.FindStringKey(kGAIAIdKey);
  371. const std::string* obj_guid = element_value.FindStringKey(kObjGuidKey);
  372. AccountType account_type = AccountType::GOOGLE;
  373. if (const std::string* account_type_string =
  374. element_value.FindStringKey(kAccountTypeKey)) {
  375. account_type = AccountId::StringToAccountType(*account_type_string);
  376. }
  377. switch (account_type) {
  378. case AccountType::GOOGLE:
  379. if (email || gaia_id) {
  380. result.push_back(AccountId::FromUserEmailGaiaId(
  381. email ? *email : std::string(),
  382. gaia_id ? *gaia_id : std::string()));
  383. }
  384. break;
  385. case AccountType::ACTIVE_DIRECTORY:
  386. if (email && obj_guid) {
  387. result.push_back(
  388. AccountId::AdFromUserEmailObjGuid(*email, *obj_guid));
  389. }
  390. break;
  391. default:
  392. NOTREACHED() << "Unknown account type";
  393. }
  394. }
  395. }
  396. return result;
  397. }
  398. void KnownUser::SaveKnownUser(const AccountId& account_id) {
  399. const bool is_ephemeral =
  400. UserManager::IsInitialized() &&
  401. UserManager::Get()->IsUserNonCryptohomeDataEphemeral(account_id);
  402. if (is_ephemeral &&
  403. account_id.GetAccountType() != AccountType::ACTIVE_DIRECTORY) {
  404. return;
  405. }
  406. UpdateId(account_id);
  407. local_state_->CommitPendingWrite();
  408. }
  409. void KnownUser::SetIsEphemeralUser(const AccountId& account_id,
  410. bool is_ephemeral) {
  411. if (account_id.GetAccountType() != AccountType::ACTIVE_DIRECTORY)
  412. return;
  413. SetBooleanPref(account_id, kIsEphemeral, is_ephemeral);
  414. }
  415. void KnownUser::UpdateId(const AccountId& account_id) {
  416. switch (account_id.GetAccountType()) {
  417. case AccountType::GOOGLE:
  418. SetStringPref(account_id, kGAIAIdKey, account_id.GetGaiaId());
  419. break;
  420. case AccountType::ACTIVE_DIRECTORY:
  421. SetStringPref(account_id, kObjGuidKey, account_id.GetObjGuid());
  422. break;
  423. case AccountType::UNKNOWN:
  424. return;
  425. }
  426. SetStringPref(account_id, kAccountTypeKey,
  427. AccountId::AccountTypeToString(account_id.GetAccountType()));
  428. }
  429. const std::string* KnownUser::FindGaiaID(const AccountId& account_id) {
  430. return FindStringPath(account_id, kGAIAIdKey);
  431. }
  432. void KnownUser::SetDeviceId(const AccountId& account_id,
  433. const std::string& device_id) {
  434. const std::string known_device_id = GetDeviceId(account_id);
  435. if (!known_device_id.empty() && device_id != known_device_id) {
  436. NOTREACHED() << "Trying to change device ID for known user.";
  437. }
  438. SetStringPref(account_id, kDeviceId, device_id);
  439. }
  440. std::string KnownUser::GetDeviceId(const AccountId& account_id) {
  441. const std::string* device_id = FindStringPath(account_id, kDeviceId);
  442. if (device_id)
  443. return *device_id;
  444. return std::string();
  445. }
  446. void KnownUser::SetGAPSCookie(const AccountId& account_id,
  447. const std::string& gaps_cookie) {
  448. SetStringPref(account_id, kGAPSCookie, gaps_cookie);
  449. }
  450. std::string KnownUser::GetGAPSCookie(const AccountId& account_id) {
  451. const std::string* gaps_cookie = FindStringPath(account_id, kGAPSCookie);
  452. if (gaps_cookie)
  453. return *gaps_cookie;
  454. return std::string();
  455. }
  456. void KnownUser::UpdateUsingSAML(const AccountId& account_id,
  457. const bool using_saml) {
  458. SetBooleanPref(account_id, kUsingSAMLKey, using_saml);
  459. }
  460. bool KnownUser::IsUsingSAML(const AccountId& account_id) {
  461. return FindBoolPath(account_id, kUsingSAMLKey).value_or(false);
  462. }
  463. void KnownUser::UpdateIsUsingSAMLPrincipalsAPI(
  464. const AccountId& account_id,
  465. bool is_using_saml_principals_api) {
  466. SetBooleanPref(account_id, kIsUsingSAMLPrincipalsAPI,
  467. is_using_saml_principals_api);
  468. }
  469. bool KnownUser::GetIsUsingSAMLPrincipalsAPI(const AccountId& account_id) {
  470. return FindBoolPath(account_id, kIsUsingSAMLPrincipalsAPI).value_or(false);
  471. }
  472. void KnownUser::SetProfileRequiresPolicy(const AccountId& account_id,
  473. ProfileRequiresPolicy required) {
  474. DCHECK_NE(required, ProfileRequiresPolicy::kUnknown);
  475. SetBooleanPref(account_id, kProfileRequiresPolicy,
  476. required == ProfileRequiresPolicy::kPolicyRequired);
  477. }
  478. ProfileRequiresPolicy KnownUser::GetProfileRequiresPolicy(
  479. const AccountId& account_id) {
  480. absl::optional<bool> requires_policy =
  481. FindBoolPath(account_id, kProfileRequiresPolicy);
  482. if (requires_policy.has_value()) {
  483. return requires_policy.value() ? ProfileRequiresPolicy::kPolicyRequired
  484. : ProfileRequiresPolicy::kNoPolicyRequired;
  485. }
  486. return ProfileRequiresPolicy::kUnknown;
  487. }
  488. void KnownUser::ClearProfileRequiresPolicy(const AccountId& account_id) {
  489. SetPath(account_id, kProfileRequiresPolicy, absl::nullopt);
  490. }
  491. void KnownUser::UpdateReauthReason(const AccountId& account_id,
  492. const int reauth_reason) {
  493. SetIntegerPref(account_id, kReauthReasonKey, reauth_reason);
  494. }
  495. absl::optional<int> KnownUser::FindReauthReason(
  496. const AccountId& account_id) const {
  497. return FindIntPath(account_id, kReauthReasonKey);
  498. }
  499. void KnownUser::SetChallengeResponseKeys(const AccountId& account_id,
  500. base::Value value) {
  501. DCHECK(value.is_list());
  502. SetPath(account_id, kChallengeResponseKeys, std::move(value));
  503. }
  504. base::Value KnownUser::GetChallengeResponseKeys(const AccountId& account_id) {
  505. const base::Value* value = FindPath(account_id, kChallengeResponseKeys);
  506. if (!value || !value->is_list())
  507. return base::Value();
  508. return value->Clone();
  509. }
  510. void KnownUser::SetLastOnlineSignin(const AccountId& account_id,
  511. base::Time time) {
  512. SetPath(account_id, kLastOnlineSignin, base::TimeToValue(time));
  513. }
  514. base::Time KnownUser::GetLastOnlineSignin(const AccountId& account_id) {
  515. const base::Value* value = FindPath(account_id, kLastOnlineSignin);
  516. if (!value)
  517. return base::Time();
  518. absl::optional<base::Time> time = base::ValueToTime(value);
  519. if (!time)
  520. return base::Time();
  521. return *time;
  522. }
  523. void KnownUser::SetOfflineSigninLimit(
  524. const AccountId& account_id,
  525. absl::optional<base::TimeDelta> time_delta) {
  526. if (!time_delta) {
  527. SetPath(account_id, kOfflineSigninLimit, absl::nullopt);
  528. } else {
  529. SetPath(account_id, kOfflineSigninLimit,
  530. base::TimeDeltaToValue(time_delta.value()));
  531. }
  532. }
  533. absl::optional<base::TimeDelta> KnownUser::GetOfflineSigninLimit(
  534. const AccountId& account_id) {
  535. return base::ValueToTimeDelta(FindPath(account_id, kOfflineSigninLimit));
  536. }
  537. void KnownUser::SetIsEnterpriseManaged(const AccountId& account_id,
  538. bool is_enterprise_managed) {
  539. SetBooleanPref(account_id, kIsEnterpriseManaged, is_enterprise_managed);
  540. }
  541. bool KnownUser::GetIsEnterpriseManaged(const AccountId& account_id) {
  542. return FindBoolPath(account_id, kIsEnterpriseManaged).value_or(false);
  543. }
  544. void KnownUser::SetAccountManager(const AccountId& account_id,
  545. const std::string& manager) {
  546. SetStringPref(account_id, kAccountManager, manager);
  547. }
  548. const std::string* KnownUser::GetAccountManager(const AccountId& account_id) {
  549. return FindStringPath(account_id, kAccountManager);
  550. }
  551. void KnownUser::SetUserLastLoginInputMethodId(
  552. const AccountId& account_id,
  553. const std::string& input_method_id) {
  554. SetStringPref(account_id, kLastInputMethod, input_method_id);
  555. }
  556. const std::string* KnownUser::GetUserLastInputMethodId(
  557. const AccountId& account_id) {
  558. return FindStringPath(account_id, kLastInputMethod);
  559. }
  560. void KnownUser::SetUserPinLength(const AccountId& account_id, int pin_length) {
  561. SetIntegerPref(account_id, kPinAutosubmitLength, pin_length);
  562. }
  563. int KnownUser::GetUserPinLength(const AccountId& account_id) {
  564. return FindIntPath(account_id, kPinAutosubmitLength).value_or(0);
  565. }
  566. bool KnownUser::PinAutosubmitIsBackfillNeeded(const AccountId& account_id) {
  567. // If the pref is not set, the pref needs to be backfilled.
  568. return FindBoolPath(account_id, kPinAutosubmitBackfillNeeded).value_or(true);
  569. }
  570. void KnownUser::PinAutosubmitSetBackfillNotNeeded(const AccountId& account_id) {
  571. SetBooleanPref(account_id, kPinAutosubmitBackfillNeeded, false);
  572. }
  573. void KnownUser::PinAutosubmitSetBackfillNeededForTests(
  574. const AccountId& account_id) {
  575. SetBooleanPref(account_id, kPinAutosubmitBackfillNeeded, true);
  576. }
  577. void KnownUser::SetPasswordSyncToken(const AccountId& account_id,
  578. const std::string& token) {
  579. SetStringPref(account_id, kPasswordSyncToken, token);
  580. }
  581. const std::string* KnownUser::GetPasswordSyncToken(
  582. const AccountId& account_id) const {
  583. return FindStringPath(account_id, kPasswordSyncToken);
  584. }
  585. void KnownUser::SetOnboardingCompletedVersion(
  586. const AccountId& account_id,
  587. const absl::optional<base::Version> version) {
  588. if (!version) {
  589. SetPath(account_id, kOnboardingCompletedVersion, absl::nullopt);
  590. } else {
  591. SetStringPref(account_id, kOnboardingCompletedVersion,
  592. version.value().GetString());
  593. }
  594. }
  595. absl::optional<base::Version> KnownUser::GetOnboardingCompletedVersion(
  596. const AccountId& account_id) {
  597. const std::string* str_version =
  598. FindStringPath(account_id, kOnboardingCompletedVersion);
  599. if (!str_version)
  600. return absl::nullopt;
  601. base::Version version = base::Version(*str_version);
  602. if (!version.IsValid())
  603. return absl::nullopt;
  604. return version;
  605. }
  606. void KnownUser::RemoveOnboardingCompletedVersionForTests(
  607. const AccountId& account_id) {
  608. SetPath(account_id, kOnboardingCompletedVersion, absl::nullopt);
  609. }
  610. void KnownUser::SetPendingOnboardingScreen(const AccountId& account_id,
  611. const std::string& screen) {
  612. SetStringPref(account_id, kPendingOnboardingScreen, screen);
  613. }
  614. void KnownUser::RemovePendingOnboardingScreen(const AccountId& account_id) {
  615. SetPath(account_id, kPendingOnboardingScreen, absl::nullopt);
  616. }
  617. std::string KnownUser::GetPendingOnboardingScreen(const AccountId& account_id) {
  618. if (const std::string* screen =
  619. FindStringPath(account_id, kPendingOnboardingScreen)) {
  620. return *screen;
  621. }
  622. // Return empty string if no screen is pending.
  623. return std::string();
  624. }
  625. bool KnownUser::UserExists(const AccountId& account_id) {
  626. return FindPrefs(account_id);
  627. }
  628. void KnownUser::RemovePrefs(const AccountId& account_id) {
  629. if (!account_id.is_valid())
  630. return;
  631. ListPrefUpdate update(local_state_, kKnownUsers);
  632. base::Value::List& update_list = update->GetList();
  633. for (auto it = update_list.begin(); it != update_list.end(); ++it) {
  634. if (UserMatches(account_id, *it)) {
  635. update_list.erase(it);
  636. break;
  637. }
  638. }
  639. }
  640. void KnownUser::CleanEphemeralUsers() {
  641. ListPrefUpdate update(local_state_, kKnownUsers);
  642. update->GetList().EraseIf([](const auto& value) {
  643. if (!value.is_dict())
  644. return false;
  645. absl::optional<bool> is_ephemeral = value.FindBoolKey(kIsEphemeral);
  646. return is_ephemeral && *is_ephemeral;
  647. });
  648. }
  649. void KnownUser::CleanObsoletePrefs() {
  650. ListPrefUpdate update(local_state_, kKnownUsers);
  651. for (base::Value& user_entry : update.Get()->GetListDeprecated()) {
  652. if (!user_entry.is_dict())
  653. continue;
  654. for (const std::string& key : kObsoleteKeys)
  655. user_entry.RemoveKey(key);
  656. }
  657. }
  658. // static
  659. void KnownUser::RegisterPrefs(PrefRegistrySimple* registry) {
  660. registry->RegisterListPref(kKnownUsers);
  661. }
  662. // --- Legacy interface ---
  663. namespace known_user {
  664. AccountId GetAccountId(const std::string& user_email,
  665. const std::string& id,
  666. const AccountType& account_type) {
  667. DCHECK((id.empty() && account_type == AccountType::UNKNOWN) ||
  668. (!id.empty() && account_type != AccountType::UNKNOWN));
  669. PrefService* local_state = GetLocalStateLegacy();
  670. if (local_state) {
  671. return KnownUser(local_state).GetAccountId(user_email, id, account_type);
  672. }
  673. // The handling of the local-state-not-initialized case is pretty complex - it
  674. // is KnownUser::GetAccountId with all queries assuming to return false.
  675. // This should be come unnecessary when all callers are migrated to the
  676. // KnownUser class interface (https://crbug.com/1150434) and thus responsible
  677. // to pass a valid |local_state| pointer.
  678. // In tests empty accounts are possible.
  679. if (user_email.empty() && id.empty() &&
  680. account_type == AccountType::UNKNOWN) {
  681. return EmptyAccountId();
  682. }
  683. AccountId result(EmptyAccountId());
  684. // UserManager is usually NULL in unit tests.
  685. if (account_type == AccountType::UNKNOWN && UserManager::IsInitialized() &&
  686. UserManager::Get()->GetPlatformKnownUserId(user_email, id, &result)) {
  687. return result;
  688. }
  689. const std::string sanitized_email =
  690. user_email.empty()
  691. ? std::string()
  692. : gaia::CanonicalizeEmail(gaia::SanitizeEmail(user_email));
  693. std::string stored_email;
  694. switch (account_type) {
  695. case AccountType::GOOGLE:
  696. return AccountId::FromUserEmailGaiaId(sanitized_email, id);
  697. case AccountType::ACTIVE_DIRECTORY:
  698. return AccountId::AdFromUserEmailObjGuid(sanitized_email, id);
  699. case AccountType::UNKNOWN:
  700. return AccountId::FromUserEmail(sanitized_email);
  701. }
  702. NOTREACHED();
  703. return EmptyAccountId();
  704. }
  705. std::vector<AccountId> GetKnownAccountIds() {
  706. PrefService* local_state = GetLocalStateLegacy();
  707. // Local State may not be initialized in tests.
  708. if (!local_state)
  709. return {};
  710. return KnownUser(local_state).GetKnownAccountIds();
  711. }
  712. } // namespace known_user
  713. } // namespace user_manager