Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Side by Side Diff: chrome/browser/sync/profile_sync_service.cc

Issue 10335015: Treat SyncCredentialsLost as an auth error (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: git try Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/sync/profile_sync_service.h" 5 #include "chrome/browser/sync/profile_sync_service.h"
6 6
7 #include <cstddef> 7 #include <cstddef>
8 #include <map> 8 #include <map>
9 #include <set> 9 #include <set>
10 #include <utility> 10 #include <utility>
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 sync_service_url_ = GURL(kSyncServerUrl); 151 sync_service_url_ = GURL(kSyncServerUrl);
152 } 152 }
153 #endif 153 #endif
154 } 154 }
155 155
156 ProfileSyncService::~ProfileSyncService() { 156 ProfileSyncService::~ProfileSyncService() {
157 sync_prefs_.RemoveSyncPrefObserver(this); 157 sync_prefs_.RemoveSyncPrefObserver(this);
158 Shutdown(); 158 Shutdown();
159 } 159 }
160 160
161 bool ProfileSyncService::AreCredentialsAvailable() { 161 bool ProfileSyncService::IsSyncEnabledAndLoggedIn() {
162 if (IsManaged()) { 162 // Exit if sync is disabled.
163 return false; 163 if (IsManaged() || sync_prefs_.IsStartSuppressed())
164 }
165
166 // If we have start suppressed, then basically just act like we have no
167 // credentials (login is required to fix this, since we need the user's
168 // passphrase to encrypt/decrypt anyway).
169 // TODO(sync): Revisit this when we move to a server-based keystore.
170 if (sync_prefs_.IsStartSuppressed())
171 return false; 164 return false;
172 165
173 // CrOS user is always logged in. Chrome uses signin_ to check logged in. 166 // Sync is logged in if there is a non-empty authenticated username.
174 if (signin_->GetAuthenticatedUsername().empty()) 167 return !signin_->GetAuthenticatedUsername().empty();
175 return false; 168 }
176 169
170 bool ProfileSyncService::IsSyncTokenAvailable() {
177 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); 171 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
178 if (!token_service) 172 if (!token_service)
179 return false; 173 return false;
180
181 // TODO(chron): Verify CrOS unit test behavior.
182 return token_service->HasTokenForService(GaiaConstants::kSyncService); 174 return token_service->HasTokenForService(GaiaConstants::kSyncService);
183 } 175 }
184 176
185 void ProfileSyncService::Initialize() { 177 void ProfileSyncService::Initialize() {
186 InitSettings(); 178 InitSettings();
187 179
188 // We clear this here (vs Shutdown) because we want to remember that an error 180 // We clear this here (vs Shutdown) because we want to remember that an error
189 // happened on shutdown so we can display details (message, location) about it 181 // happened on shutdown so we can display details (message, location) about it
190 // in about:sync. 182 // in about:sync.
191 ClearStaleErrors(); 183 ClearStaleErrors();
192 184
193 sync_prefs_.AddSyncPrefObserver(this); 185 sync_prefs_.AddSyncPrefObserver(this);
194 186
195 // For now, the only thing we can do through policy is to turn sync off. 187 // For now, the only thing we can do through policy is to turn sync off.
196 if (IsManaged()) { 188 if (IsManaged()) {
197 DisableForUser(); 189 DisableForUser();
198 return; 190 return;
199 } 191 }
200 192
201 RegisterAuthNotifications(); 193 RegisterAuthNotifications();
202 194
203 if (!HasSyncSetupCompleted()) 195 if (!HasSyncSetupCompleted())
204 DisableForUser(); // Clean up in case of previous crash / setup abort. 196 DisableForUser(); // Clean up in case of previous crash / setup abort.
205 197
206 TryStart(); 198 TryStart();
207 } 199 }
208 200
209 void ProfileSyncService::TryStart() { 201 void ProfileSyncService::TryStart() {
210 if (!sync_prefs_.IsStartSuppressed() && AreCredentialsAvailable()) { 202 if (!IsSyncEnabledAndLoggedIn())
203 return;
204 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
205 if (!token_service)
206 return;
207 // Don't start the backend if the token service hasn't finished loading tokens
208 // yet (if the backend is started before the sync token has been loaded,
209 // GetCredentials() will return bogus credentials).
210 if (IsSyncTokenAvailable() || token_service->TokensLoadedFromDB()) {
211 if (HasSyncSetupCompleted() || auto_start_enabled_) { 211 if (HasSyncSetupCompleted() || auto_start_enabled_) {
212 // If sync setup has completed we always start the backend. 212 // If sync setup has completed we always start the backend.
213 // If autostart is enabled, but we haven't completed sync setup, we try to 213 // If autostart is enabled, but we haven't completed sync setup, we try to
214 // start sync anyway, since it's possible we crashed/shutdown after 214 // start sync anyway, since it's possible we crashed/shutdown after
215 // logging in but before the backend finished initializing the last time. 215 // logging in but before the backend finished initializing the last time.
216 // Note that if we haven't finished setting up sync, backend bring up will 216 // Note that if we haven't finished setting up sync, backend bring up will
217 // be done by the wizard. 217 // be done by the wizard.
218 StartUp(); 218 StartUp();
219 } 219 }
220 } else if (HasSyncSetupCompleted()) {
221 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
222 if (token_service && token_service->TokensLoadedFromDB() &&
223 !AreCredentialsAvailable()) {
224 // The token service has lost sync's tokens. We cannot recover from this
225 // without signing back in, which is not yet supported. For now, we
226 // trigger an unrecoverable error.
227 OnUnrecoverableError(FROM_HERE, "Sync credentials lost.");
228 }
229 } 220 }
230 } 221 }
231 222
232 void ProfileSyncService::StartSyncingWithServer() { 223 void ProfileSyncService::StartSyncingWithServer() {
233 if (backend_.get()) 224 if (backend_.get())
234 backend_->StartSyncingWithServer(); 225 backend_->StartSyncingWithServer();
235 } 226 }
236 227
237 void ProfileSyncService::RegisterAuthNotifications() { 228 void ProfileSyncService::RegisterAuthNotifications() {
238 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); 229 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 } 296 }
306 } 297 }
307 } 298 }
308 } 299 }
309 300
310 SyncCredentials ProfileSyncService::GetCredentials() { 301 SyncCredentials ProfileSyncService::GetCredentials() {
311 SyncCredentials credentials; 302 SyncCredentials credentials;
312 credentials.email = signin_->GetAuthenticatedUsername(); 303 credentials.email = signin_->GetAuthenticatedUsername();
313 DCHECK(!credentials.email.empty()); 304 DCHECK(!credentials.email.empty());
314 TokenService* service = TokenServiceFactory::GetForProfile(profile_); 305 TokenService* service = TokenServiceFactory::GetForProfile(profile_);
315 credentials.sync_token = service->GetTokenForService( 306 if (service->HasTokenForService(GaiaConstants::kSyncService)) {
316 GaiaConstants::kSyncService); 307 credentials.sync_token = service->GetTokenForService(
308 GaiaConstants::kSyncService);
309 UMA_HISTOGRAM_BOOLEAN("Sync.CredentialsLost", false);
310 } else {
311 // We've lost our sync credentials (crbug.com/121755), so just make up some
312 // invalid credentials so the backend will generate an auth error.
313 UMA_HISTOGRAM_BOOLEAN("Sync.CredentialsLost", true);
314 credentials.sync_token = "credentials_lost";
315 }
317 return credentials; 316 return credentials;
318 } 317 }
319 318
320 void ProfileSyncService::InitializeBackend(bool delete_stale_data) { 319 void ProfileSyncService::InitializeBackend(bool delete_stale_data) {
321 if (!backend_.get()) { 320 if (!backend_.get()) {
322 NOTREACHED(); 321 NOTREACHED();
323 return; 322 return;
324 } 323 }
325 324
326 syncable::ModelTypeSet initial_types; 325 syncable::ModelTypeSet initial_types;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 } 396 }
398 397
399 398
400 void ProfileSyncService::StartUp() { 399 void ProfileSyncService::StartUp() {
401 // Don't start up multiple times. 400 // Don't start up multiple times.
402 if (backend_.get()) { 401 if (backend_.get()) {
403 DVLOG(1) << "Skipping bringing up backend host."; 402 DVLOG(1) << "Skipping bringing up backend host.";
404 return; 403 return;
405 } 404 }
406 405
407 DCHECK(AreCredentialsAvailable()); 406 DCHECK(IsSyncEnabledAndLoggedIn());
408 407
409 last_synced_time_ = sync_prefs_.GetLastSyncedTime(); 408 last_synced_time_ = sync_prefs_.GetLastSyncedTime();
410 409
411 #if defined(OS_CHROMEOS) 410 #if defined(OS_CHROMEOS)
412 std::string bootstrap_token = sync_prefs_.GetEncryptionBootstrapToken(); 411 std::string bootstrap_token = sync_prefs_.GetEncryptionBootstrapToken();
413 if (bootstrap_token.empty()) { 412 if (bootstrap_token.empty()) {
414 sync_prefs_.SetEncryptionBootstrapToken( 413 sync_prefs_.SetEncryptionBootstrapToken(
415 sync_prefs_.GetSpareBootstrapToken()); 414 sync_prefs_.GetSpareBootstrapToken());
416 } 415 }
417 #endif 416 #endif
(...skipping 968 matching lines...) Expand 10 before | Expand all | Expand 10 after
1386 DCHECK(encrypted_types_.Has(syncable::PASSWORDS)); 1385 DCHECK(encrypted_types_.Has(syncable::PASSWORDS));
1387 // We may be called during the setup process before we're 1386 // We may be called during the setup process before we're
1388 // initialized. In this case, we default to the sensitive types. 1387 // initialized. In this case, we default to the sensitive types.
1389 return encrypted_types_; 1388 return encrypted_types_;
1390 } 1389 }
1391 1390
1392 void ProfileSyncService::OnSyncManagedPrefChange(bool is_sync_managed) { 1391 void ProfileSyncService::OnSyncManagedPrefChange(bool is_sync_managed) {
1393 NotifyObservers(); 1392 NotifyObservers();
1394 if (is_sync_managed) { 1393 if (is_sync_managed) {
1395 DisableForUser(); 1394 DisableForUser();
1396 } else if (HasSyncSetupCompleted() && AreCredentialsAvailable()) { 1395 } else if (HasSyncSetupCompleted() &&
1396 IsSyncEnabledAndLoggedIn() &&
1397 IsSyncTokenAvailable()) {
1398 // Previously-configured sync has been re-enabled, so start sync now.
1397 StartUp(); 1399 StartUp();
1398 } 1400 }
1399 } 1401 }
1400 1402
1401 void ProfileSyncService::Observe(int type, 1403 void ProfileSyncService::Observe(int type,
1402 const content::NotificationSource& source, 1404 const content::NotificationSource& source,
1403 const content::NotificationDetails& details) { 1405 const content::NotificationDetails& details) {
1404 switch (type) { 1406 switch (type) {
1405 case chrome::NOTIFICATION_SYNC_CONFIGURE_START: 1407 case chrome::NOTIFICATION_SYNC_CONFIGURE_START:
1406 case chrome::NOTIFICATION_SYNC_CONFIGURE_BLOCKED: 1408 case chrome::NOTIFICATION_SYNC_CONFIGURE_BLOCKED:
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1508 // Track the fact that we're still waiting for auth to complete. 1510 // Track the fact that we're still waiting for auth to complete.
1509 is_auth_in_progress_ = true; 1511 is_auth_in_progress_ = true;
1510 } 1512 }
1511 break; 1513 break;
1512 } 1514 }
1513 case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: { 1515 case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: {
1514 const TokenService::TokenRequestFailedDetails& token_details = 1516 const TokenService::TokenRequestFailedDetails& token_details =
1515 *(content::Details<const TokenService::TokenRequestFailedDetails>( 1517 *(content::Details<const TokenService::TokenRequestFailedDetails>(
1516 details).ptr()); 1518 details).ptr());
1517 if (IsTokenServiceRelevant(token_details.service()) && 1519 if (IsTokenServiceRelevant(token_details.service()) &&
1518 !AreCredentialsAvailable()) { 1520 !IsSyncTokenAvailable()) {
1519 // The additional check around AreCredentialsAvailable above prevents us 1521 // The additional check around IsSyncTokenAvailable() above prevents us
1520 // sounding the alarm if we actually have a valid token but a refresh 1522 // sounding the alarm if we actually have a valid token but a refresh
1521 // attempt by TokenService failed for any variety of reasons (e.g. flaky 1523 // attempt by TokenService failed for any variety of reasons (e.g. flaky
1522 // network). It's possible the token we do have is also invalid, but in 1524 // network). It's possible the token we do have is also invalid, but in
1523 // that case we should already have (or can expect) an auth error sent 1525 // that case we should already have (or can expect) an auth error sent
1524 // from the sync backend. 1526 // from the sync backend.
1525 GoogleServiceAuthError error( 1527 GoogleServiceAuthError error(
1526 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 1528 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
1527 UpdateAuthErrorState(error); 1529 UpdateAuthErrorState(error);
1528 } 1530 }
1529 break; 1531 break;
1530 } 1532 }
1531 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { 1533 case chrome::NOTIFICATION_TOKEN_AVAILABLE: {
1532 const TokenService::TokenAvailableDetails& token_details = 1534 const TokenService::TokenAvailableDetails& token_details =
1533 *(content::Details<const TokenService::TokenAvailableDetails>( 1535 *(content::Details<const TokenService::TokenAvailableDetails>(
1534 details).ptr()); 1536 details).ptr());
1535 if (IsTokenServiceRelevant(token_details.service()) && 1537 if (IsTokenServiceRelevant(token_details.service()) &&
1536 AreCredentialsAvailable()) { 1538 IsSyncEnabledAndLoggedIn() &&
1539 IsSyncTokenAvailable()) {
1537 if (backend_initialized_) 1540 if (backend_initialized_)
1538 backend_->UpdateCredentials(GetCredentials()); 1541 backend_->UpdateCredentials(GetCredentials());
1539 else if (!sync_prefs_.IsStartSuppressed()) 1542 else
1540 StartUp(); 1543 StartUp();
1541 } 1544 }
1542 break; 1545 break;
1543 } 1546 }
1544 case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: { 1547 case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: {
1545 // This notification gets fired when TokenService loads the tokens 1548 // This notification gets fired when TokenService loads the tokens
1546 // from storage. 1549 // from storage.
1547 if (AreCredentialsAvailable()) { 1550 if (IsSyncEnabledAndLoggedIn()) {
1548 // Initialize the backend if sync token was loaded. 1551 // Initialize the backend if sync is enabled. If the sync token was
1549 if (backend_initialized_) { 1552 // not loaded, GetCredentials() will generate invalid credentials to
1553 // cause the backend to generate an auth error (crbug.com/121755).
1554 if (backend_initialized_)
1550 backend_->UpdateCredentials(GetCredentials()); 1555 backend_->UpdateCredentials(GetCredentials());
1551 } 1556 else
1552 if (!sync_prefs_.IsStartSuppressed())
1553 StartUp(); 1557 StartUp();
1554 } else if (!auto_start_enabled_ &&
1555 !signin_->GetAuthenticatedUsername().empty() &&
1556 HasSyncSetupCompleted()) {
1557 // If not in auto-start / Chrome OS mode, and we have a username
1558 // without tokens, the user will need to signin again. At the moment
1559 // this is not supported, so we trigger an unrecoverable error.
1560 OnUnrecoverableError(FROM_HERE, "Sync credentials lost.");
1561 } 1558 }
1562 break; 1559 break;
1563 } 1560 }
1564 default: { 1561 default: {
1565 NOTREACHED(); 1562 NOTREACHED();
1566 } 1563 }
1567 } 1564 }
1568 } 1565 }
1569 1566
1570 void ProfileSyncService::AddObserver(Observer* observer) { 1567 void ProfileSyncService::AddObserver(Observer* observer) {
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1667 // See http://stackoverflow.com/questions/6224121/is-new-this-myclass-undefine d-behaviour-after-directly-calling-the-destru. 1664 // See http://stackoverflow.com/questions/6224121/is-new-this-myclass-undefine d-behaviour-after-directly-calling-the-destru.
1668 ProfileSyncService* old_this = this; 1665 ProfileSyncService* old_this = this;
1669 this->~ProfileSyncService(); 1666 this->~ProfileSyncService();
1670 new(old_this) ProfileSyncService( 1667 new(old_this) ProfileSyncService(
1671 new ProfileSyncComponentsFactoryImpl(profile, 1668 new ProfileSyncComponentsFactoryImpl(profile,
1672 CommandLine::ForCurrentProcess()), 1669 CommandLine::ForCurrentProcess()),
1673 profile, 1670 profile,
1674 signin, 1671 signin,
1675 behavior); 1672 behavior);
1676 } 1673 }
OLDNEW
« no previous file with comments | « chrome/browser/sync/profile_sync_service.h ('k') | chrome/browser/sync/profile_sync_service_mock.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698