Commit a8fa4cae authored by rsimha@chromium.org's avatar rsimha@chromium.org

[sync] Auto-heal sync credential cache on startup, and no longer rely on NOTIFICATION_PREF_CHANGED

CredentialCacheService listens for initial sync configuration during
sign in by directly observing sync preferences in the pref store. This
is not good because sync preferences are not always re-written
during sign in, and we cannot rely on NOTIFICATION_PREF_CHANGED.

In addition, if during startup, we find an older version of a credential
cache with some fields missing (like the last_updated_time), we could
run into bugs due to the missing fields.

This patch does the following:

1) Makes CredentialCacheService listen to the notification
   NOTIFICATION_SYNC_CONFIGURE_START for sign-in, restart and
   reconfigure scenarios.
2) No longer relies on NOTIFICATION_PREF_CHANGED for detecting
   changes to sync datatype preferences.
2) Freshly writes any missing sync credentials during startup to
   auto-heal the cache in case chrome crashed during a previous run,
   or if a signed-in user upgraded chrome from an older version that
   didn't support credential caching or was missing some newer fields.
3) Adds caching support for both sync encryption tokens:
   kSyncEncryptionBootstrapToken and kSyncKeystoreEncryptionBootstrapToken,
   and makes the required logic changes to sign in / reconfigure with
   one or the other.
4) Modifies PackAndUpdateStringPref and UpdateBooleanPref to only
   update the cache if the new value being written is different from the
   existing value.
5) Other misc. changes to support the design described above.

BUG=142550, 143214
TEST=Sign in to sync, sign out, exit chrome, delete the credential cache from the profile directory or merely delete some fields, and sign in again. All sync preferences must get written to the credential cache.

Review URL: https://chromiumcodereview.appspot.com/10829310

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@152157 0039d316-1c4b-4281-b951-d872f2087c98
parent 3295f031
......@@ -70,6 +70,8 @@ CredentialCacheService::~CredentialCacheService() {
}
void CredentialCacheService::Shutdown() {
if (local_store_.get())
local_store_->CommitPendingWrite();
local_store_observer_.release();
local_store_.release();
alternate_store_observer_.release();
......@@ -84,36 +86,60 @@ void CredentialCacheService::Observe(
DCHECK(local_store_.get());
switch (type) {
case chrome::NOTIFICATION_PREF_CHANGED: {
// One of the two sync encryption tokens has changed. Update its value in
// the local cache.
const std::string pref_name =
*(content::Details<const std::string>(details).ptr());
if (pref_name == prefs::kSyncEncryptionBootstrapToken) {
PackAndUpdateStringPref(pref_name,
sync_prefs_.GetEncryptionBootstrapToken());
} else if (pref_name == prefs::kSyncKeystoreEncryptionBootstrapToken) {
PackAndUpdateStringPref(
pref_name,
sync_prefs_.GetKeystoreEncryptionBootstrapToken());
} else {
UpdateBooleanPref(pref_name,
profile_->GetPrefs()->GetBoolean(pref_name.c_str()));
NOTREACHED() "Invalid pref name " << pref_name << ".";
}
break;
}
case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT:
case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: {
// The user has signed out. Write blank values to the google username,
// encryption tokens and token service credentials in the local cache.
PackAndUpdateStringPref(prefs::kGoogleServicesUsername, std::string());
if (HasPref(local_store_, prefs::kSyncEncryptionBootstrapToken)) {
PackAndUpdateStringPref(prefs::kSyncEncryptionBootstrapToken,
std::string());
}
if (HasPref(local_store_, prefs::kSyncKeystoreEncryptionBootstrapToken)) {
PackAndUpdateStringPref(prefs::kSyncKeystoreEncryptionBootstrapToken,
std::string());
}
PackAndUpdateStringPref(GaiaConstants::kGaiaLsid, std::string());
PackAndUpdateStringPref(GaiaConstants::kGaiaSid, std::string());
break;
}
case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: {
// The user has signed in. Write the new value of the google username to
// the local cache.
SigninManager* signin = SigninManagerFactory::GetForProfile(profile_);
PackAndUpdateStringPref(prefs::kGoogleServicesUsername,
signin->GetAuthenticatedUsername());
break;
}
case chrome::NOTIFICATION_SYNC_CONFIGURE_START: {
// We have detected a sync sign in, auto-start or reconfigure. Write the
// latest sync preferences to the local cache.
WriteSyncPrefsToLocalCache();
break;
}
case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: {
// If there is no existing local credential cache, and the token service
// already has valid credentials as a result of the user having signed in,
// write them to the cache. Used in cases where the user was already
// signed in and then upgraded from a version of chrome that didn't
// support credential caching.
if (local_store_.get() &&
local_store_->IsInitializationComplete() &&
local_store_->GetReadError() ==
JsonPrefStore::PREF_READ_ERROR_NO_FILE) {
// The token service has been fully initialized. Update the token service
// credentials in the local cache. This is a no-op if the cache already
// contains the latest values.
TokenService* token_service =
TokenServiceFactory::GetForProfile(profile_);
if (token_service->AreCredentialsValid()) {
......@@ -122,11 +148,11 @@ void CredentialCacheService::Observe(
PackAndUpdateStringPref(GaiaConstants::kGaiaLsid, credentials.lsid);
PackAndUpdateStringPref(GaiaConstants::kGaiaSid, credentials.sid);
}
}
break;
}
case chrome::NOTIFICATION_TOKEN_SERVICE_CREDENTIALS_UPDATED: {
// The token service has new credentials. Write them to the local cache.
const TokenService::CredentialsUpdatedDetails& token_details =
*(content::Details<const TokenService::CredentialsUpdatedDetails>(
details).ptr());
......@@ -136,6 +162,7 @@ void CredentialCacheService::Observe(
}
case chrome::NOTIFICATION_TOKENS_CLEARED: {
// Tokens have been cleared. Blank out lsid and sid in the local cache.
PackAndUpdateStringPref(GaiaConstants::kGaiaLsid, std::string());
PackAndUpdateStringPref(GaiaConstants::kGaiaSid, std::string());
break;
......@@ -155,7 +182,8 @@ void CredentialCacheService::ReadCachedCredentialsFromAlternateProfile() {
if (HasUserSignedOut())
return;
// Sanity check the alternate credential cache. If any string credentials
// Sanity check the alternate credential cache. Note that it is sufficient to
// have just one of the two sync encryption tokens. If any string credentials
// are outright missing even though the file exists, something is awry with
// the alternate profile store. There is no sense in flagging an error as the
// problem lies in a different profile directory. There is nothing to do now.
......@@ -164,7 +192,9 @@ void CredentialCacheService::ReadCachedCredentialsFromAlternateProfile() {
if (!HasPref(alternate_store_, prefs::kGoogleServicesUsername) ||
!HasPref(alternate_store_, GaiaConstants::kGaiaLsid) ||
!HasPref(alternate_store_, GaiaConstants::kGaiaSid) ||
!HasPref(alternate_store_, prefs::kSyncEncryptionBootstrapToken) ||
!(HasPref(alternate_store_, prefs::kSyncEncryptionBootstrapToken) ||
HasPref(alternate_store_,
prefs::kSyncKeystoreEncryptionBootstrapToken)) ||
!HasPref(alternate_store_, prefs::kSyncKeepEverythingSynced)) {
VLOG(1) << "Could not find cached credentials in \""
<< GetCredentialPathInAlternateProfile().value() << "\".";
......@@ -172,33 +202,46 @@ void CredentialCacheService::ReadCachedCredentialsFromAlternateProfile() {
return;
}
// Extract cached credentials from the alternate credential cache.
std::string google_services_username =
// Extract the google username, lsid and sid from the alternate credential
// cache.
std::string alternate_google_services_username =
GetAndUnpackStringPref(alternate_store_, prefs::kGoogleServicesUsername);
std::string lsid =
std::string alternate_lsid =
GetAndUnpackStringPref(alternate_store_, GaiaConstants::kGaiaLsid);
std::string sid =
std::string alternate_sid =
GetAndUnpackStringPref(alternate_store_, GaiaConstants::kGaiaSid);
std::string encryption_bootstrap_token =
// Extract the sync encryption tokens from the alternate credential cache.
// Both tokens may not be found, since only one of them is used at any time.
std::string alternate_encryption_bootstrap_token;
if (HasPref(alternate_store_, prefs::kSyncEncryptionBootstrapToken)) {
alternate_encryption_bootstrap_token =
GetAndUnpackStringPref(alternate_store_,
prefs::kSyncEncryptionBootstrapToken);
}
std::string alternate_keystore_encryption_bootstrap_token;
if (HasPref(alternate_store_, prefs::kSyncKeystoreEncryptionBootstrapToken)) {
alternate_keystore_encryption_bootstrap_token =
GetAndUnpackStringPref(alternate_store_,
prefs::kSyncKeystoreEncryptionBootstrapToken);
}
// Sign out of sync if the alternate profile has signed out the same user.
// There is no need to schedule any more reads of the alternate profile
// cache because we only apply cached credentials for first-time sign-ins.
if (ShouldSignOutOfSync(google_services_username)) {
if (ShouldSignOutOfSync(alternate_google_services_username)) {
VLOG(1) << "User has signed out on the other profile. Signing out.";
InitiateSignOut();
return;
}
// Extract cached sync prefs from the alternate credential cache.
bool keep_everything_synced =
bool alternate_keep_everything_synced =
GetBooleanPref(alternate_store_, prefs::kSyncKeepEverythingSynced);
ProfileSyncService* service =
ProfileSyncServiceFactory::GetForProfile(profile_);
ModelTypeSet registered_types = service->GetRegisteredDataTypes();
ModelTypeSet preferred_types;
ModelTypeSet alternate_preferred_types;
for (ModelTypeSet::Iterator it = registered_types.First();
it.Good();
it.Inc()) {
......@@ -216,32 +259,47 @@ void CredentialCacheService::ReadCachedCredentialsFromAlternateProfile() {
continue;
}
if (GetBooleanPref(alternate_store_, datatype_pref_name))
preferred_types.Put(it.Get());
alternate_preferred_types.Put(it.Get());
}
// Reconfigure if sync settings or credentials have changed in the alternate
// profile, but for the same user that is signed in to the local profile.
if (MayReconfigureSync(google_services_username)) {
if (HaveSyncPrefsChanged(keep_everything_synced, preferred_types)) {
// Reconfigure if sync settings, encryption tokens or token service
// credentials have changed in the alternate profile, but for the same user
// that is signed in to the local profile.
if (MayReconfigureSync(alternate_google_services_username)) {
if (HaveSyncPrefsChanged(alternate_keep_everything_synced,
alternate_preferred_types)) {
VLOG(1) << "Sync prefs have changed in other profile. Reconfiguring.";
service->OnUserChoseDatatypes(keep_everything_synced, preferred_types);
service->OnUserChoseDatatypes(alternate_keep_everything_synced,
alternate_preferred_types);
}
if (HaveTokenServiceCredentialsChanged(lsid, sid)) {
if (HaveSyncEncryptionTokensChanged(
alternate_encryption_bootstrap_token,
alternate_keystore_encryption_bootstrap_token)) {
VLOG(1) << "Sync encryption tokens have changed in other profile.";
sync_prefs_.SetEncryptionBootstrapToken(
alternate_encryption_bootstrap_token);
sync_prefs_.SetKeystoreEncryptionBootstrapToken(
alternate_keystore_encryption_bootstrap_token);
}
if (HaveTokenServiceCredentialsChanged(alternate_lsid, alternate_sid)) {
VLOG(1) << "Token service credentials have changed in other profile.";
UpdateTokenServiceCredentials(lsid, sid);
UpdateTokenServiceCredentials(alternate_lsid, alternate_sid);
}
}
// Sign in if we notice new cached credentials in the alternate profile.
if (ShouldSignInToSync(google_services_username,
lsid,
sid,
encryption_bootstrap_token)) {
InitiateSignInWithCachedCredentials(google_services_username,
encryption_bootstrap_token,
keep_everything_synced,
preferred_types);
UpdateTokenServiceCredentials(lsid, sid);
if (ShouldSignInToSync(alternate_google_services_username,
alternate_lsid,
alternate_sid,
alternate_encryption_bootstrap_token,
alternate_keystore_encryption_bootstrap_token)) {
InitiateSignInWithCachedCredentials(
alternate_google_services_username,
alternate_encryption_bootstrap_token,
alternate_keystore_encryption_bootstrap_token,
alternate_keep_everything_synced,
alternate_preferred_types);
UpdateTokenServiceCredentials(alternate_lsid, alternate_sid);
}
// Schedule the next read from the alternate credential cache so that we can
......@@ -249,19 +307,7 @@ void CredentialCacheService::ReadCachedCredentialsFromAlternateProfile() {
ScheduleNextReadFromAlternateCredentialCache();
}
void CredentialCacheService::WriteExistingSyncPrefsToLocalCache() {
// If the local user is already signed in and there is no local credential
// cache file, write all the existing sync prefs to the local cache.
DCHECK(local_store_.get() &&
local_store_->GetReadError() ==
JsonPrefStore::PREF_READ_ERROR_NO_FILE);
SigninManager* signin = SigninManagerFactory::GetForProfile(profile_);
if (!signin->GetAuthenticatedUsername().empty() &&
!HasPref(local_store_, prefs::kGoogleServicesUsername)) {
PackAndUpdateStringPref(prefs::kGoogleServicesUsername,
signin->GetAuthenticatedUsername());
PackAndUpdateStringPref(prefs::kSyncEncryptionBootstrapToken,
sync_prefs_.GetEncryptionBootstrapToken());
void CredentialCacheService::WriteSyncPrefsToLocalCache() {
UpdateBooleanPref(prefs::kSyncKeepEverythingSynced,
sync_prefs_.HasKeepEverythingSynced());
ProfileSyncService* service =
......@@ -276,7 +322,6 @@ void CredentialCacheService::WriteExistingSyncPrefsToLocalCache() {
datatype_pref_name,
profile_->GetPrefs()->GetBoolean(datatype_pref_name.c_str()));
}
}
}
void CredentialCacheService::ScheduleNextReadFromAlternateCredentialCache() {
......@@ -364,6 +409,10 @@ void CredentialCacheService::PackAndUpdateStringPref(
const std::string& pref_name,
const std::string& new_value) {
DCHECK(local_store_.get());
if (HasPref(local_store_, pref_name) &&
GetAndUnpackStringPref(local_store_, pref_name) == new_value) {
return;
}
if (!HasUserSignedOut()) {
local_store_->SetValueSilently(pref_name, PackCredential(new_value));
} else {
......@@ -377,6 +426,10 @@ void CredentialCacheService::PackAndUpdateStringPref(
void CredentialCacheService::UpdateBooleanPref(const std::string& pref_name,
bool new_value) {
DCHECK(local_store_.get());
if (HasPref(local_store_, pref_name) &&
GetBooleanPref(local_store_, pref_name) == new_value) {
return;
}
if (!HasUserSignedOut()) {
local_store_->SetValueSilently(pref_name,
base::Value::CreateBooleanValue(new_value));
......@@ -434,15 +487,48 @@ CredentialCacheService::LocalStoreObserver::~LocalStoreObserver() {
void CredentialCacheService::LocalStoreObserver::OnInitializationCompleted(
bool succeeded) {
// If there is no existing local credential cache, write any existing sync
// prefs to the local cache. This could happen if the user was already signed
// in and restarts chrome after upgrading from an older version that didn't
// support credential caching. Note that |succeeded| will be true even if
// the local cache file wasn't found, so long as its parent dir was found.
// Note that |succeeded| will be true even if the local cache file wasn't
// found, so long as its parent dir (the chrome profile directory) was found.
// If |succeeded| is false, it means that the chrome profile directory is
// missing. In this case, there's nothing we can do other than DCHECK.
DCHECK(succeeded);
if (local_store_->GetReadError() == JsonPrefStore::PREF_READ_ERROR_NO_FILE) {
service_->WriteExistingSyncPrefsToLocalCache();
// During startup, we do a precautionary write of the google username,
// encryption tokens and sync prefs to the local cache in order to recover
// from the following cases:
// 1) There is no local credential cache, but the user is signed in. This
// could happen if a signed-in user restarts chrome after upgrading from
// an older version that didn't support credential caching.
// 2) There is a local credential cache, but we missed writing sync credential
// updates to it in the past due to a crash, or due to the user exiting
// chrome in the midst of a sign in, sign out or reconfigure.
// Note: If the local credential cache was already up-to-date, the operations
// below will be no-ops, and won't change the cache's last updated time. Also,
// if the user is not signed in and there is no local credential cache, we
// don't want to create a cache with empty values.
SigninManager* signin =
SigninManagerFactory::GetForProfile(service_->profile_);
if ((local_store_->GetReadError() == JsonPrefStore::PREF_READ_ERROR_NO_FILE &&
!signin->GetAuthenticatedUsername().empty()) ||
(local_store_->GetReadError() == JsonPrefStore::PREF_READ_ERROR_NONE)) {
service_->PackAndUpdateStringPref(prefs::kGoogleServicesUsername,
signin->GetAuthenticatedUsername());
if (!service_->sync_prefs_.GetEncryptionBootstrapToken().empty()) {
service_->PackAndUpdateStringPref(
prefs::kSyncEncryptionBootstrapToken,
service_->sync_prefs_.GetEncryptionBootstrapToken());
}
if (!service_->sync_prefs_.GetKeystoreEncryptionBootstrapToken().empty()) {
service_->PackAndUpdateStringPref(
prefs::kSyncKeystoreEncryptionBootstrapToken,
service_->sync_prefs_.GetKeystoreEncryptionBootstrapToken());
}
service_->WriteSyncPrefsToLocalCache();
}
// Now that the local credential cache is ready, start listening for events
// associated with various sync config changes.
service_->StartListeningForSyncConfigChanges();
}
void CredentialCacheService::LocalStoreObserver::OnPrefValueChanged(
......@@ -504,7 +590,9 @@ void CredentialCacheService::InitializeLocalCredentialCacheWriter() {
content::BrowserThread::FILE));
local_store_observer_ = new LocalStoreObserver(this, local_store_);
local_store_->ReadPrefsAsync(NULL);
}
void CredentialCacheService::StartListeningForSyncConfigChanges() {
// Register for notifications for google sign in and sign out.
registrar_.Add(this,
chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
......@@ -513,19 +601,19 @@ void CredentialCacheService::InitializeLocalCredentialCacheWriter() {
chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
content::Source<Profile>(profile_));
// Register for notifications for updates to various sync settings, which are
// stored in the PrefStore.
// Register for notifications for sync configuration changes that could occur
// during sign in or reconfiguration.
ProfileSyncService* service =
ProfileSyncServiceFactory::GetForProfile(profile_);
registrar_.Add(this,
chrome::NOTIFICATION_SYNC_CONFIGURE_START,
content::Source<ProfileSyncService>(service));
// Register for notifications for updates to the sync encryption tokens, which
// are stored in the PrefStore.
pref_registrar_.Init(profile_->GetPrefs());
pref_registrar_.Add(prefs::kSyncEncryptionBootstrapToken, this);
pref_registrar_.Add(prefs::kSyncKeepEverythingSynced, this);
ModelTypeSet all_types = syncer::ModelTypeSet::All();
for (ModelTypeSet::Iterator it = all_types.First(); it.Good(); it.Inc()) {
if (it.Get() == NIGORI) // The NIGORI preference is not persisted.
continue;
pref_registrar_.Add(
browser_sync::SyncPrefs::GetPrefNameForDataType(it.Get()),
this);
}
pref_registrar_.Add(prefs::kSyncKeystoreEncryptionBootstrapToken, this);
// Register for notifications for updates to lsid and sid, which are stored in
// the TokenService.
......@@ -567,30 +655,46 @@ bool CredentialCacheService::HasUserSignedOut() {
void CredentialCacheService::InitiateSignInWithCachedCredentials(
const std::string& google_services_username,
const std::string& encryption_bootstrap_token,
const std::string& keystore_encryption_bootstrap_token,
bool keep_everything_synced,
ModelTypeSet preferred_types) {
// Update the google username in the SigninManager and PrefStore.
// Update the google username in the SigninManager and PrefStore. Also update
// its value in the local credential cache, since we will not send out
// NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL in this case.
ProfileSyncService* service =
ProfileSyncServiceFactory::GetForProfile(profile_);
service->signin()->SetAuthenticatedUsername(google_services_username);
profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
google_services_username);
PackAndUpdateStringPref(prefs::kGoogleServicesUsername,
service->signin()->GetAuthenticatedUsername());
// Update sync encryption tokens after making sure at least one of them is
// non-empty.
DCHECK(!encryption_bootstrap_token.empty() ||
!keystore_encryption_bootstrap_token.empty());
if (!encryption_bootstrap_token.empty()) {
sync_prefs_.SetEncryptionBootstrapToken(encryption_bootstrap_token);
}
if (!keystore_encryption_bootstrap_token.empty()) {
sync_prefs_.SetKeystoreEncryptionBootstrapToken(
keystore_encryption_bootstrap_token);
}
// Update the sync preferences.
sync_prefs_.SetStartSuppressed(false);
sync_prefs_.SetSyncSetupCompleted();
sync_prefs_.SetEncryptionBootstrapToken(encryption_bootstrap_token);
sync_prefs_.SetKeepEverythingSynced(keep_everything_synced);
sync_prefs_.SetPreferredDataTypes(service->GetRegisteredDataTypes(),
preferred_types);
}
void CredentialCacheService::UpdateTokenServiceCredentials(
const std::string& lsid,
const std::string& sid) {
const std::string& alternate_lsid,
const std::string& alternate_sid) {
GaiaAuthConsumer::ClientLoginResult login_result;
login_result.lsid = lsid;
login_result.sid = sid;
login_result.lsid = alternate_lsid;
login_result.sid = alternate_sid;
TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
token_service->UpdateCredentials(login_result);
DCHECK(token_service->AreCredentialsValid());
......@@ -604,29 +708,51 @@ void CredentialCacheService::InitiateSignOut() {
}
bool CredentialCacheService::HaveSyncPrefsChanged(
bool keep_everything_synced,
ModelTypeSet preferred_types) const {
bool alternate_keep_everything_synced,
ModelTypeSet alternate_preferred_types) const {
ProfileSyncService* service =
ProfileSyncServiceFactory::GetForProfile(profile_);
ModelTypeSet local_preferred_types =
sync_prefs_.GetPreferredDataTypes(service->GetRegisteredDataTypes());
return
(keep_everything_synced != sync_prefs_.HasKeepEverythingSynced()) ||
!Difference(preferred_types, local_preferred_types).Empty();
(alternate_keep_everything_synced !=
sync_prefs_.HasKeepEverythingSynced()) ||
!alternate_preferred_types.Equals(local_preferred_types);
}
bool CredentialCacheService::HaveSyncEncryptionTokensChanged(
const std::string& alternate_encryption_bootstrap_token,
const std::string& alternate_keystore_encryption_bootstrap_token) {
std::string local_encryption_bootstrap_token;
if (HasPref(local_store_, prefs::kSyncEncryptionBootstrapToken)) {
local_encryption_bootstrap_token =
GetAndUnpackStringPref(local_store_,
prefs::kSyncEncryptionBootstrapToken);
}
std::string local_keystore_encryption_bootstrap_token;
if (HasPref(local_store_, prefs::kSyncKeystoreEncryptionBootstrapToken)) {
local_keystore_encryption_bootstrap_token =
GetAndUnpackStringPref(local_store_,
prefs::kSyncKeystoreEncryptionBootstrapToken);
}
return (local_encryption_bootstrap_token !=
alternate_encryption_bootstrap_token) ||
(local_keystore_encryption_bootstrap_token !=
alternate_keystore_encryption_bootstrap_token);
}
bool CredentialCacheService::HaveTokenServiceCredentialsChanged(
const std::string& lsid,
const std::string& sid) {
const std::string& alternate_lsid,
const std::string& alternate_sid) {
std::string local_lsid =
GetAndUnpackStringPref(local_store_, GaiaConstants::kGaiaLsid);
std::string local_sid =
GetAndUnpackStringPref(local_store_, GaiaConstants::kGaiaSid);
return local_lsid != lsid || local_sid != sid;
return local_lsid != alternate_lsid || local_sid != alternate_sid;
}
bool CredentialCacheService::ShouldSignOutOfSync(
const std::string& google_services_username) {
const std::string& alternate_google_services_username) {
// We must sign out of sync iff:
// 1) The user is signed in to the local profile.
// 2) The user has never signed out of the local profile in the past.
......@@ -637,14 +763,14 @@ bool CredentialCacheService::ShouldSignOutOfSync(
ProfileSyncServiceFactory::GetForProfile(profile_);
return !service->signin()->GetAuthenticatedUsername().empty() &&
!HasUserSignedOut() &&
google_services_username.empty() &&
alternate_google_services_username.empty() &&
!service->setup_in_progress() &&
(GetLastUpdatedTime(alternate_store_) >
GetLastUpdatedTime(local_store_));
}
bool CredentialCacheService::MayReconfigureSync(
const std::string& google_services_username) {
const std::string& alternate_google_services_username) {
// We may attempt to reconfigure sync iff:
// 1) The user is signed in to the local profile.
// 2) The user has never signed out of the local profile in the past.
......@@ -655,7 +781,7 @@ bool CredentialCacheService::MayReconfigureSync(
ProfileSyncServiceFactory::GetForProfile(profile_);
return !service->signin()->GetAuthenticatedUsername().empty() &&
!HasUserSignedOut() &&
(google_services_username ==
(alternate_google_services_username ==
service->signin()->GetAuthenticatedUsername()) &&
!service->setup_in_progress() &&
(GetLastUpdatedTime(alternate_store_) >
......@@ -663,10 +789,11 @@ bool CredentialCacheService::MayReconfigureSync(
}
bool CredentialCacheService::ShouldSignInToSync(
const std::string& google_services_username,
const std::string& lsid,
const std::string& sid,
const std::string& encryption_bootstrap_token) {
const std::string& alternate_google_services_username,
const std::string& alternate_lsid,
const std::string& alternate_sid,
const std::string& alternate_encryption_bootstrap_token,
const std::string& alternate_keystore_encryption_bootstrap_token) {
// We should sign in with cached credentials from the alternate profile iff:
// 1) The user is not currently signed in to the local profile.
// 2) The user has never signed out of the local profile in the past.
......@@ -676,10 +803,11 @@ bool CredentialCacheService::ShouldSignInToSync(
ProfileSyncServiceFactory::GetForProfile(profile_);
return service->signin()->GetAuthenticatedUsername().empty() &&
!HasUserSignedOut() &&
!google_services_username.empty() &&
!lsid.empty() &&
!sid.empty() &&
!encryption_bootstrap_token.empty() &&
!alternate_google_services_username.empty() &&
!alternate_lsid.empty() &&
!alternate_sid.empty() &&
!(alternate_encryption_bootstrap_token.empty() &&
alternate_keystore_encryption_bootstrap_token.empty()) &&
!service->setup_in_progress();
}
......
......@@ -56,12 +56,9 @@ class CredentialCacheService : public ProfileKeyedService,
// to the local profile if the load was successful.
void ReadCachedCredentialsFromAlternateProfile();
// Populates a new local credential cache file if the user is already signed
// in to the local profile, and there is no existing local credential cache.
// Used in scenarios where a user upgraded from an older version of Chrome
// that didn't support credential caching. This method is a no-op if local
// sync prefs have already been written to the local cache.
void WriteExistingSyncPrefsToLocalCache();
// Writes kSyncKeepEverythingSynced and the sync preferences for individual
// datatypes to the local cache.
void WriteSyncPrefsToLocalCache();
// Resets |alternate_store_| and schedules the next read from the alternate
// credential cache.
......@@ -87,12 +84,15 @@ class CredentialCacheService : public ProfileKeyedService,
void WriteLastUpdatedTime();
// Updates the value of |pref_name| to |new_value|, unless the user has signed
// out, in which case we write an empty string value to |pref_name|.
// out, in which case we write an empty string value to |pref_name|. This
// method is a no-op if |new_value| is the same as the value found in the
// local cache.
void PackAndUpdateStringPref(const std::string& pref_name,
const std::string& new_value);
// Updates the value of |pref_name| to |new_value|, unless the user has signed
// out, in which case we write "false" to |pref_name|.
// out, in which case we write "false" to |pref_name|. This method is a no-op
// if |new_value| is the same as the value found in the local cache.
void UpdateBooleanPref(const std::string& pref_name, bool new_value);
// Returns the time at which the credential cache represented by |store| was
......@@ -181,6 +181,10 @@ class CredentialCacheService : public ProfileKeyedService,
// Initializes the JsonPrefStore object for the local profile directory.
void InitializeLocalCredentialCacheWriter();
// Registers for notifications for events like sync sign in, sign out,
// (re)configuration, encryption and changes to the token service credentials.
void StartListeningForSyncConfigChanges();
// Returns true if there is an empty value for kGoogleServicesUsername in the
// credential cache for the local profile (indicating that the user first
// signed in and then signed out). Returns false if there's no value at all
......@@ -196,59 +200,76 @@ class CredentialCacheService : public ProfileKeyedService,
// Initiates sync sign in using credentials read from the alternate profile by
// persisting |google_services_username|, |encryption_bootstrap_token|,
// |keep_everything_synced| and |preferred_types| to the local pref store, and
// preparing ProfileSyncService for sign in.
// |keystore_encryption_bootstrap_token|, |keep_everything_synced| and
// |preferred_types| to the local pref store, and preparing ProfileSyncService
// for sign in.
void InitiateSignInWithCachedCredentials(
const std::string& google_services_username,
const std::string& encryption_bootstrap_token,
const std::string& keystore_encryption_bootstrap_token,
bool keep_everything_synced,
ModelTypeSet preferred_types);
// Updates the TokenService credentials with |lsid| and |sid| and triggers the
// minting of new tokens for all Chrome services. ProfileSyncService is
// automatically notified when tokens are minted, and goes on to consume the
// updated credentials.
void UpdateTokenServiceCredentials(const std::string& lsid,
const std::string& sid);
// Updates the TokenService credentials with |alternate_lsid| and
// |alternate_sid| and triggers the minting of new tokens for all Chrome
// services. ProfileSyncService is automatically notified when tokens are
// minted, and goes on to consume the updated credentials.
void UpdateTokenServiceCredentials(const std::string& alternate_lsid,
const std::string& alternate_sid);
// Initiates a sign out of sync. Called when we notice that the user has
// signed out from the alternate mode by reading its credential cache.
void InitiateSignOut();
// Compares the sync preferences in the local profile with values that were
// read from the alternate profile -- |keep_everything_synced| and
// |preferred_types|. Returns true if the prefs have changed, and false
// otherwise.
bool HaveSyncPrefsChanged(bool keep_everything_synced,
ModelTypeSet preferred_types) const;
// read from the alternate profile -- |alternate_keep_everything_synced| and
// |alternate_preferred_types|. Returns true if the prefs have changed, and
// false otherwise.
bool HaveSyncPrefsChanged(bool alternate_keep_everything_synced,
ModelTypeSet alternate_preferred_types) const;
// Compares the sync encryption tokens in the local profile with values that
// were read from the alternate profile --
// |alternate_encryption_bootstrap_token| and
// |alternate_keystore_encryption_bootstrap_token|. Returns true if the tokens
// have changed, and false otherwise.
bool HaveSyncEncryptionTokensChanged(
const std::string& alternate_encryption_bootstrap_token,
const std::string& alternate_keystore_encryption_bootstrap_token);
// Compares the token service credentials in the local profile with values
// that were read from the alternate profile -- |lsid| and |sid|. Returns true
// if the credentials have changed, and false otherwise.
bool HaveTokenServiceCredentialsChanged(const std::string& lsid,
const std::string& sid);
// that were read from the alternate profile -- |alternate_lsid| and
// |alternate_sid|. Returns true if the credentials have changed, and false
// otherwise.
bool HaveTokenServiceCredentialsChanged(const std::string& alternate_lsid,
const std::string& alternate_sid);
// Determines if the user must be signed out of the local profile or not.
// Called when updated settings are noticed in the alternate credential cache
// for |google_services_username|. Returns true if we should sign out, and
// false if not.
bool ShouldSignOutOfSync(const std::string& google_services_username);
// for |alternate_google_services_username|. Returns true if we should sign
// out, and false if not.
bool ShouldSignOutOfSync(
const std::string& alternate_google_services_username);
// Determines if sync settings may be reconfigured or not. Called when
// updated settings are noticed in the alternate credential cache for
// |google_services_username|. Returns true if we may reconfigure, and false
// if not.
bool MayReconfigureSync(const std::string& google_services_username);
// |alternate_google_services_username|. Returns true if we may reconfigure,
// and false if not.
bool MayReconfigureSync(
const std::string& alternate_google_services_username);
// Determines if the user must be signed in to the local profile or not.
// Called when updated settings are noticed in the alternate credential cache
// for |google_services_username|, with new values for |lsid|, |sid| and
// |encryption_bootstrap_token|. Returns true if we should sign in, and
// false if not.
bool ShouldSignInToSync(const std::string& google_services_username,
const std::string& lsid,
const std::string& sid,
const std::string& encryption_bootstrap_token);
// for |alternate_google_services_username|, with new values for
// |alternate_lsid|, |alternate_sid|, |alternate_encryption_bootstrap_token|
// and |alternate_keystore_encryption_bootstrap_token|. Returns true if we
// should sign in, and false if not.
bool ShouldSignInToSync(
const std::string& alternate_google_services_username,
const std::string& alternate_lsid,
const std::string& alternate_sid,
const std::string& alternate_encryption_bootstrap_token,
const std::string& alternate_keystore_encryption_bootstrap_token);
// Profile for which credentials are being cached.
Profile* profile_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment