Index: components/user_manager/user_manager_base.cc |
diff --git a/components/user_manager/user_manager_base.cc b/components/user_manager/user_manager_base.cc |
index 30fe4559b1880c57b96b9c7797f508bcfc3b24c6..30d0c29147c9375fab39e72c4efa8c10d058b0ab 100644 |
--- a/components/user_manager/user_manager_base.cc |
+++ b/components/user_manager/user_manager_base.cc |
@@ -54,6 +54,13 @@ const char kUserOAuthTokenStatus[] = "OAuthTokenStatus"; |
// authentication against GAIA should be enforced during the next sign-in. |
const char kUserForceOnlineSignin[] = "UserForceOnlineSignin"; |
+// A dictionary that maps user IDs to a flag indicating whether session |
+// initialization has been completed at least once on this session. If the |
+// flag is set to false (or the user ID is missing from the dictionary) then |
+// the session did not complete initialization and the next signin should |
+// require a network connection (for example, to register for policy). |
+const char kUserSessionInitialized[] = "UserSessionInitialized"; |
emaxx
2017/02/23 21:45:25
To me, the name sounds a bit misleading: the flag
Andrew T Wilson (Slow)
2017/02/24 16:15:15
Yeah, the problem is that profile initialization i
emaxx
2017/02/24 17:54:09
But the notification to set this new flag is set e
|
+ |
// A dictionary that maps user ID to the user type. |
const char kUserType[] = "UserType"; |
@@ -82,6 +89,7 @@ void UserManagerBase::RegisterPrefs(PrefRegistrySimple* registry) { |
registry->RegisterDictionaryPref(kUserDisplayEmail); |
registry->RegisterDictionaryPref(kUserOAuthTokenStatus); |
registry->RegisterDictionaryPref(kUserForceOnlineSignin); |
+ registry->RegisterDictionaryPref(kUserSessionInitialized); |
registry->RegisterDictionaryPref(kUserType); |
registry->RegisterStringPref(kLastActiveUser, std::string()); |
@@ -263,6 +271,26 @@ void UserManagerBase::OnSessionStarted() { |
GetLocalState()->CommitPendingWrite(); |
} |
+void UserManagerBase::OnSessionInitialized(User* user) { |
+ DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
+ |
+ // Mark the user as having an initialized session. |
+ user->set_session_initialized(true); |
+ |
+ // Do not update local state if data stored or cached outside the user's |
emaxx
2017/02/23 21:45:25
I'm curious how then is the flag preserved for the
Andrew T Wilson (Slow)
2017/02/24 16:15:15
Great catch. I suspect the way to deal with this i
emaxx
2017/02/24 17:54:09
Could you please drop a note regarding ephemeral u
|
+ // cryptohome is to be treated as ephemeral. |
+ if (IsUserNonCryptohomeDataEphemeral(user->GetAccountId())) |
+ return; |
+ |
+ { |
+ DictionaryPrefUpdate user_session_initialized(GetLocalState(), |
+ kUserSessionInitialized); |
+ user_session_initialized->SetBooleanWithoutPathExpansion( |
Alexander Alekseev
2017/02/24 09:58:11
We have known_user database for this.
Could you us
Andrew T Wilson (Slow)
2017/02/24 16:15:15
Done.
|
+ user->GetAccountId().GetUserEmail(), true); |
emaxx
2017/02/23 21:45:25
The docs for AccountId prescribe to use GetAccount
Andrew T Wilson (Slow)
2017/02/24 16:15:15
I'm now just using known_user, so I think we're OK
|
+ } |
+ GetLocalState()->CommitPendingWrite(); |
+} |
+ |
void UserManagerBase::RemoveUser(const AccountId& account_id, |
RemoveUserDelegate* delegate) { |
DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
@@ -782,8 +810,24 @@ void UserManagerBase::EnsureUsersLoaded() { |
std::set<AccountId> regular_users_set; |
ParseUserList(*prefs_regular_users, device_local_accounts_set, ®ular_users, |
®ular_users_set); |
+ |
+ // If there is no stored SessionInitialized state, this either means this is |
+ // the first boot on a new device or this is a migration from an older device |
+ // that was not tracking SessionInitialized state. If there are already users |
emaxx
2017/02/23 21:45:25
It's not clear how this will work in the following
Andrew T Wilson (Slow)
2017/02/24 16:15:15
I don't think this can really happen - very very e
emaxx
2017/02/24 17:54:09
Acknowledged. And looks like the existing tests ve
|
+ // on the device then we know this is a migration, so we will mark all of |
+ // the sessions as initialized. |
+ const bool mark_user_sessions_initialized = |
emaxx
2017/02/23 21:45:25
Maybe reorganize the migration code so that it for
Andrew T Wilson (Slow)
2017/02/24 16:15:15
Moved migration code to known_user::IsSessionIniti
|
+ !local_state->HasPrefPath(kUserSessionInitialized); |
+ |
for (std::vector<AccountId>::const_iterator it = regular_users.begin(); |
it != regular_users.end(); ++it) { |
+ if (mark_user_sessions_initialized) { |
+ LOG(WARNING) << "Migrating existing user to session_initialized=true"; |
emaxx
2017/02/23 21:45:25
nit: Maybe also log something that specifies the u
emaxx
2017/02/23 21:45:25
nit: Isn't the INFO level better here? Because thi
Andrew T Wilson (Slow)
2017/02/24 16:15:15
Yes, but should be a one-off per user. So it's a w
Andrew T Wilson (Slow)
2017/02/24 16:15:15
Intentionally not doing this since I believe loggi
|
+ DictionaryPrefUpdate user_session_initialized(GetLocalState(), |
+ kUserSessionInitialized); |
+ user_session_initialized->SetBooleanWithoutPathExpansion( |
+ it->GetUserEmail(), true); |
+ } |
User* user = nullptr; |
if (IsSupervisedAccountId(*it)) { |
user = User::CreateSupervisedUser(*it); |
@@ -799,6 +843,7 @@ void UserManagerBase::EnsureUsersLoaded() { |
const AccountId account_id = user->GetAccountId(); |
user->set_oauth_token_status(LoadUserOAuthStatus(*it)); |
user->set_force_online_signin(LoadForceOnlineSignin(*it)); |
+ user->set_session_initialized(LoadSessionInitialized(*it)); |
user->set_using_saml(known_user::IsUsingSAML(*it)); |
users_.push_back(user); |
@@ -821,6 +866,9 @@ void UserManagerBase::EnsureUsersLoaded() { |
} |
} |
+ if (mark_user_sessions_initialized) |
+ local_state->CommitPendingWrite(); |
+ |
user_loading_stage_ = STAGE_LOADED; |
PerformPostUserListLoadingActions(); |
@@ -883,6 +931,11 @@ void UserManagerBase::RegularUserLoggedIn(const AccountId& account_id) { |
active_user_->set_oauth_token_status(LoadUserOAuthStatus(account_id)); |
SaveUserDisplayName(active_user_->GetAccountId(), |
base::UTF8ToUTF16(active_user_->GetAccountName(true))); |
+ DictionaryPrefUpdate user_session_initialized(GetLocalState(), |
+ kUserSessionInitialized); |
+ user_session_initialized->SetBooleanWithoutPathExpansion( |
+ active_user_->GetAccountId().GetUserEmail(), |
+ active_user_->session_initialized()); |
} |
AddUserRecord(active_user_); |
@@ -939,6 +992,20 @@ bool UserManagerBase::LoadForceOnlineSignin(const AccountId& account_id) const { |
return force_online_signin; |
} |
+bool UserManagerBase::LoadSessionInitialized( |
+ const AccountId& account_id) const { |
+ DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
+ |
+ const base::DictionaryValue* prefs_session_initialized = |
+ GetLocalState()->GetDictionary(kUserSessionInitialized); |
+ bool session_initialized = false; |
+ if (prefs_session_initialized) { |
+ prefs_session_initialized->GetBooleanWithoutPathExpansion( |
+ account_id.GetUserEmail(), &session_initialized); |
+ } |
+ return session_initialized; |
+} |
+ |
void UserManagerBase::RemoveNonCryptohomeData(const AccountId& account_id) { |
PrefService* prefs = GetLocalState(); |
DictionaryPrefUpdate prefs_display_name_update(prefs, kUserDisplayName); |
@@ -961,6 +1028,11 @@ void UserManagerBase::RemoveNonCryptohomeData(const AccountId& account_id) { |
prefs_force_online_update->RemoveWithoutPathExpansion( |
account_id.GetUserEmail(), nullptr); |
+ DictionaryPrefUpdate prefs_session_initialized(prefs, |
+ kUserSessionInitialized); |
+ prefs_session_initialized->RemoveWithoutPathExpansion( |
+ account_id.GetUserEmail(), nullptr); |
+ |
known_user::RemovePrefs(account_id); |
const AccountId last_active_user = |