OLD | NEW |
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 13 matching lines...) Expand all Loading... |
24 #include "build/build_config.h" | 24 #include "build/build_config.h" |
25 #include "chrome/browser/about_flags.h" | 25 #include "chrome/browser/about_flags.h" |
26 #include "chrome/browser/browser_process.h" | 26 #include "chrome/browser/browser_process.h" |
27 #include "chrome/browser/defaults.h" | 27 #include "chrome/browser/defaults.h" |
28 #include "chrome/browser/net/chrome_cookie_notification_details.h" | 28 #include "chrome/browser/net/chrome_cookie_notification_details.h" |
29 #include "chrome/browser/pref_service_flags_storage.h" | 29 #include "chrome/browser/pref_service_flags_storage.h" |
30 #include "chrome/browser/prefs/pref_service_syncable.h" | 30 #include "chrome/browser/prefs/pref_service_syncable.h" |
31 #include "chrome/browser/profiles/profile.h" | 31 #include "chrome/browser/profiles/profile.h" |
32 #include "chrome/browser/signin/about_signin_internals.h" | 32 #include "chrome/browser/signin/about_signin_internals.h" |
33 #include "chrome/browser/signin/about_signin_internals_factory.h" | 33 #include "chrome/browser/signin/about_signin_internals_factory.h" |
| 34 #include "chrome/browser/signin/profile_oauth2_token_service.h" |
| 35 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" |
34 #include "chrome/browser/signin/signin_manager.h" | 36 #include "chrome/browser/signin/signin_manager.h" |
35 #include "chrome/browser/signin/signin_manager_factory.h" | 37 #include "chrome/browser/signin/signin_manager_factory.h" |
36 #include "chrome/browser/signin/token_service.h" | 38 #include "chrome/browser/signin/token_service.h" |
37 #include "chrome/browser/signin/token_service_factory.h" | 39 #include "chrome/browser/signin/token_service_factory.h" |
38 #include "chrome/browser/sync/backend_migrator.h" | 40 #include "chrome/browser/sync/backend_migrator.h" |
39 #include "chrome/browser/sync/glue/change_processor.h" | 41 #include "chrome/browser/sync/glue/change_processor.h" |
40 #include "chrome/browser/sync/glue/chrome_encryptor.h" | 42 #include "chrome/browser/sync/glue/chrome_encryptor.h" |
41 #include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" | 43 #include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" |
42 #include "chrome/browser/sync/glue/data_type_controller.h" | 44 #include "chrome/browser/sync/glue/data_type_controller.h" |
43 #include "chrome/browser/sync/glue/device_info.h" | 45 #include "chrome/browser/sync/glue/device_info.h" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 typedef GoogleServiceAuthError AuthError; | 107 typedef GoogleServiceAuthError AuthError; |
106 | 108 |
107 const char* ProfileSyncService::kSyncServerUrl = | 109 const char* ProfileSyncService::kSyncServerUrl = |
108 "https://clients4.google.com/chrome-sync"; | 110 "https://clients4.google.com/chrome-sync"; |
109 | 111 |
110 const char* ProfileSyncService::kDevServerUrl = | 112 const char* ProfileSyncService::kDevServerUrl = |
111 "https://clients4.google.com/chrome-sync/dev"; | 113 "https://clients4.google.com/chrome-sync/dev"; |
112 | 114 |
113 static const int kSyncClearDataTimeoutInSeconds = 60; // 1 minute. | 115 static const int kSyncClearDataTimeoutInSeconds = 60; // 1 minute. |
114 | 116 |
115 static const char* kRelevantTokenServices[] = { | 117 static const char* kOAuth2Scopes[] = { |
116 GaiaConstants::kSyncService | 118 GaiaConstants::kChromeSyncOAuth2Scope, |
| 119 // GoogleTalk scope is needed for notifications. |
| 120 GaiaConstants::kGoogleTalkOAuth2Scope |
117 }; | 121 }; |
118 static const int kRelevantTokenServicesCount = | 122 |
119 arraysize(kRelevantTokenServices); | |
120 | 123 |
121 static const char* kSyncUnrecoverableErrorHistogram = | 124 static const char* kSyncUnrecoverableErrorHistogram = |
122 "Sync.UnrecoverableErrors"; | 125 "Sync.UnrecoverableErrors"; |
123 | 126 |
124 // Helper to check if the given token service is relevant for sync. | 127 const net::BackoffEntry::Policy kRequestAccessTokenBackoffPolicy = { |
125 static bool IsTokenServiceRelevant(const std::string& service) { | 128 // Number of initial errors (in sequence) to ignore before applying |
126 for (int i = 0; i < kRelevantTokenServicesCount; ++i) { | 129 // exponential back-off rules. |
127 if (service == kRelevantTokenServices[i]) | 130 0, |
128 return true; | 131 |
129 } | 132 // Initial delay for exponential back-off in ms. |
130 return false; | 133 2000, |
131 } | 134 |
| 135 // Factor by which the waiting time will be multiplied. |
| 136 2, |
| 137 |
| 138 // Fuzzing percentage. ex: 10% will spread requests randomly |
| 139 // between 90%-100% of the calculated time. |
| 140 0.2, // 20% |
| 141 |
| 142 // Maximum amount of time we are willing to delay our request in ms. |
| 143 // TODO(pavely): crbug.com/246686 ProfileSyncService should retry |
| 144 // RequestAccessToken on connection state change after backoff |
| 145 1000 * 3600 * 4, // 4 hours. |
| 146 |
| 147 // Time to keep an entry from being discarded even when it |
| 148 // has no significant state, -1 to never discard. |
| 149 -1, |
| 150 |
| 151 // Don't use initial delay unless the last request was an error. |
| 152 false, |
| 153 }; |
132 | 154 |
133 bool ShouldShowActionOnUI( | 155 bool ShouldShowActionOnUI( |
134 const syncer::SyncProtocolError& error) { | 156 const syncer::SyncProtocolError& error) { |
135 return (error.action != syncer::UNKNOWN_ACTION && | 157 return (error.action != syncer::UNKNOWN_ACTION && |
136 error.action != syncer::DISABLE_SYNC_ON_CLIENT && | 158 error.action != syncer::DISABLE_SYNC_ON_CLIENT && |
137 error.action != syncer::STOP_SYNC_FOR_DISABLED_ACCOUNT); | 159 error.action != syncer::STOP_SYNC_FOR_DISABLED_ACCOUNT); |
138 } | 160 } |
139 | 161 |
140 ProfileSyncService::ProfileSyncService(ProfileSyncComponentsFactory* factory, | 162 ProfileSyncService::ProfileSyncService(ProfileSyncComponentsFactory* factory, |
141 Profile* profile, | 163 Profile* profile, |
(...skipping 15 matching lines...) Expand all Loading... |
157 signin_(signin_manager), | 179 signin_(signin_manager), |
158 unrecoverable_error_reason_(ERROR_REASON_UNSET), | 180 unrecoverable_error_reason_(ERROR_REASON_UNSET), |
159 weak_factory_(this), | 181 weak_factory_(this), |
160 expect_sync_configuration_aborted_(false), | 182 expect_sync_configuration_aborted_(false), |
161 encrypted_types_(syncer::SyncEncryptionHandler::SensitiveTypes()), | 183 encrypted_types_(syncer::SyncEncryptionHandler::SensitiveTypes()), |
162 encrypt_everything_(false), | 184 encrypt_everything_(false), |
163 encryption_pending_(false), | 185 encryption_pending_(false), |
164 auto_start_enabled_(start_behavior == AUTO_START), | 186 auto_start_enabled_(start_behavior == AUTO_START), |
165 configure_status_(DataTypeManager::UNKNOWN), | 187 configure_status_(DataTypeManager::UNKNOWN), |
166 setup_in_progress_(false), | 188 setup_in_progress_(false), |
167 invalidator_state_(syncer::DEFAULT_INVALIDATION_ERROR) { | 189 invalidator_state_(syncer::DEFAULT_INVALIDATION_ERROR), |
| 190 request_access_token_backoff_(&kRequestAccessTokenBackoffPolicy) { |
168 // By default, dev, canary, and unbranded Chromium users will go to the | 191 // By default, dev, canary, and unbranded Chromium users will go to the |
169 // development servers. Development servers have more features than standard | 192 // development servers. Development servers have more features than standard |
170 // sync servers. Users with officially-branded Chrome stable and beta builds | 193 // sync servers. Users with officially-branded Chrome stable and beta builds |
171 // will go to the standard sync servers. | 194 // will go to the standard sync servers. |
172 // | 195 // |
173 // GetChannel hits the registry on Windows. See http://crbug.com/70380. | 196 // GetChannel hits the registry on Windows. See http://crbug.com/70380. |
174 base::ThreadRestrictions::ScopedAllowIO allow_io; | 197 base::ThreadRestrictions::ScopedAllowIO allow_io; |
175 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); | 198 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); |
176 if (channel == chrome::VersionInfo::CHANNEL_STABLE || | 199 if (channel == chrome::VersionInfo::CHANNEL_STABLE || |
177 channel == chrome::VersionInfo::CHANNEL_BETA) { | 200 channel == chrome::VersionInfo::CHANNEL_BETA) { |
(...skipping 11 matching lines...) Expand all Loading... |
189 | 212 |
190 bool ProfileSyncService::IsSyncEnabledAndLoggedIn() { | 213 bool ProfileSyncService::IsSyncEnabledAndLoggedIn() { |
191 // Exit if sync is disabled. | 214 // Exit if sync is disabled. |
192 if (IsManaged() || sync_prefs_.IsStartSuppressed()) | 215 if (IsManaged() || sync_prefs_.IsStartSuppressed()) |
193 return false; | 216 return false; |
194 | 217 |
195 // Sync is logged in if there is a non-empty effective username. | 218 // Sync is logged in if there is a non-empty effective username. |
196 return !GetEffectiveUsername().empty(); | 219 return !GetEffectiveUsername().empty(); |
197 } | 220 } |
198 | 221 |
199 bool ProfileSyncService::IsSyncTokenAvailable() { | 222 bool ProfileSyncService::IsOAuthRefreshTokenAvailable() { |
200 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 223 // Function name doesn't reflect which token is checked. Function checks |
201 if (!token_service) | 224 // refresh token when use_oauth2_token_ is true (all platforms except android) |
202 return false; | 225 // and sync token otherwise (for android). |
203 return token_service->HasTokenForService(GaiaConstants::kSyncService); | 226 // TODO(pavely): Remove "else" part once use_oauth2_token_ is gone. |
| 227 if (use_oauth2_token_) { |
| 228 ProfileOAuth2TokenService* token_service = |
| 229 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); |
| 230 if (!token_service) |
| 231 return false; |
| 232 return token_service->RefreshTokenIsAvailable(); |
| 233 } else { |
| 234 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
| 235 if (!token_service) |
| 236 return false; |
| 237 return token_service->HasTokenForService(GaiaConstants::kSyncService); |
| 238 } |
204 } | 239 } |
205 | 240 |
206 void ProfileSyncService::Initialize() { | 241 void ProfileSyncService::Initialize() { |
207 DCHECK(!invalidator_registrar_.get()); | 242 DCHECK(!invalidator_registrar_.get()); |
208 invalidator_registrar_.reset(new syncer::InvalidatorRegistrar()); | 243 invalidator_registrar_.reset(new syncer::InvalidatorRegistrar()); |
209 | 244 |
210 InitSettings(); | 245 InitSettings(); |
211 | 246 |
212 // We clear this here (vs Shutdown) because we want to remember that an error | 247 // We clear this here (vs Shutdown) because we want to remember that an error |
213 // happened on shutdown so we can display details (message, location) about it | 248 // happened on shutdown so we can display details (message, location) about it |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 return; | 306 return; |
272 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 307 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
273 if (!token_service) | 308 if (!token_service) |
274 return; | 309 return; |
275 // Don't start the backend if the token service hasn't finished loading tokens | 310 // Don't start the backend if the token service hasn't finished loading tokens |
276 // yet. Note if the backend is started before the sync token has been loaded, | 311 // yet. Note if the backend is started before the sync token has been loaded, |
277 // GetCredentials() will return bogus credentials. On auto_start platforms | 312 // GetCredentials() will return bogus credentials. On auto_start platforms |
278 // (like ChromeOS) we don't start sync until tokens are loaded, because the | 313 // (like ChromeOS) we don't start sync until tokens are loaded, because the |
279 // user can be "signed in" on those platforms long before the tokens get | 314 // user can be "signed in" on those platforms long before the tokens get |
280 // loaded, and we don't want to generate spurious auth errors. | 315 // loaded, and we don't want to generate spurious auth errors. |
281 if (!IsSyncTokenAvailable() && | 316 if (!IsOAuthRefreshTokenAvailable() && |
282 !(!auto_start_enabled_ && token_service->TokensLoadedFromDB())) { | 317 !(!auto_start_enabled_ && token_service->TokensLoadedFromDB())) { |
283 return; | 318 return; |
284 } | 319 } |
285 | 320 |
| 321 if (use_oauth2_token_) { |
| 322 // If we got here then tokens are loaded and user logged in and sync is |
| 323 // enabled. If OAuth refresh token is not available then something is wrong. |
| 324 // When PSS requests access token, OAuth2TokenService will return error and |
| 325 // PSS will show error to user asking to reauthenticate. |
| 326 UMA_HISTOGRAM_BOOLEAN("Sync.RefreshTokenAvailable", |
| 327 IsOAuthRefreshTokenAvailable()); |
| 328 } |
| 329 |
286 // If sync setup has completed we always start the backend. If the user is in | 330 // If sync setup has completed we always start the backend. If the user is in |
287 // the process of setting up now, we should start the backend to download | 331 // the process of setting up now, we should start the backend to download |
288 // account control state / encryption information). If autostart is enabled, | 332 // account control state / encryption information). If autostart is enabled, |
289 // but we haven't completed sync setup, we try to start sync anyway, since | 333 // but we haven't completed sync setup, we try to start sync anyway, since |
290 // it's possible we crashed/shutdown after logging in but before the backend | 334 // it's possible we crashed/shutdown after logging in but before the backend |
291 // finished initializing the last time. | 335 // finished initializing the last time. |
292 // | 336 // |
293 // However, the only time we actually need to start sync _immediately_ is if | 337 // However, the only time we actually need to start sync _immediately_ is if |
294 // we haven't completed sync setup and the user is in the process of setting | 338 // we haven't completed sync setup and the user is in the process of setting |
295 // up - either they just signed in (for the first time) on an auto-start | 339 // up - either they just signed in (for the first time) on an auto-start |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 if (!value.empty()) { | 443 if (!value.empty()) { |
400 GURL custom_sync_url(value); | 444 GURL custom_sync_url(value); |
401 if (custom_sync_url.is_valid()) { | 445 if (custom_sync_url.is_valid()) { |
402 sync_service_url_ = custom_sync_url; | 446 sync_service_url_ = custom_sync_url; |
403 } else { | 447 } else { |
404 LOG(WARNING) << "The following sync URL specified at the command-line " | 448 LOG(WARNING) << "The following sync URL specified at the command-line " |
405 << "is invalid: " << value; | 449 << "is invalid: " << value; |
406 } | 450 } |
407 } | 451 } |
408 } | 452 } |
| 453 |
| 454 use_oauth2_token_ = !command_line.HasSwitch( |
| 455 switches::kSyncDisableOAuth2Token); |
409 } | 456 } |
410 | 457 |
411 SyncCredentials ProfileSyncService::GetCredentials() { | 458 SyncCredentials ProfileSyncService::GetCredentials() { |
412 SyncCredentials credentials; | 459 SyncCredentials credentials; |
413 credentials.email = GetEffectiveUsername(); | 460 credentials.email = GetEffectiveUsername(); |
414 DCHECK(!credentials.email.empty()); | 461 DCHECK(!credentials.email.empty()); |
415 TokenService* service = TokenServiceFactory::GetForProfile(profile_); | 462 if (use_oauth2_token_) { |
416 if (service->HasTokenForService(GaiaConstants::kSyncService)) { | 463 credentials.sync_token = access_token_; |
417 credentials.sync_token = service->GetTokenForService( | |
418 GaiaConstants::kSyncService); | |
419 credentials.sync_token_time = | |
420 AboutSigninInternalsFactory::GetForProfile(profile_)-> | |
421 GetTokenTime(GaiaConstants::kSyncService); | |
422 UMA_HISTOGRAM_BOOLEAN("Sync.CredentialsLost", false); | |
423 } else { | 464 } else { |
424 // We've lost our sync credentials (crbug.com/121755), so just make up some | 465 TokenService* service = TokenServiceFactory::GetForProfile(profile_); |
425 // invalid credentials so the backend will generate an auth error. | 466 if (service->HasTokenForService(GaiaConstants::kSyncService)) { |
426 UMA_HISTOGRAM_BOOLEAN("Sync.CredentialsLost", true); | 467 credentials.sync_token = service->GetTokenForService( |
| 468 GaiaConstants::kSyncService); |
| 469 } |
| 470 } |
| 471 |
| 472 if (credentials.sync_token.empty()) |
427 credentials.sync_token = "credentials_lost"; | 473 credentials.sync_token = "credentials_lost"; |
428 } | |
429 return credentials; | 474 return credentials; |
430 } | 475 } |
431 | 476 |
432 void ProfileSyncService::InitializeBackend(bool delete_stale_data) { | 477 void ProfileSyncService::InitializeBackend(bool delete_stale_data) { |
433 if (!backend_) { | 478 if (!backend_) { |
434 NOTREACHED(); | 479 NOTREACHED(); |
435 return; | 480 return; |
436 } | 481 } |
437 | 482 |
438 SyncCredentials credentials = GetCredentials(); | 483 SyncCredentials credentials = GetCredentials(); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
485 | 530 |
486 void ProfileSyncService::StartUp(StartUpDeferredOption deferred_option) { | 531 void ProfileSyncService::StartUp(StartUpDeferredOption deferred_option) { |
487 // Don't start up multiple times. | 532 // Don't start up multiple times. |
488 if (backend_) { | 533 if (backend_) { |
489 DVLOG(1) << "Skipping bringing up backend host."; | 534 DVLOG(1) << "Skipping bringing up backend host."; |
490 return; | 535 return; |
491 } | 536 } |
492 | 537 |
493 DCHECK(IsSyncEnabledAndLoggedIn()); | 538 DCHECK(IsSyncEnabledAndLoggedIn()); |
494 | 539 |
| 540 if (use_oauth2_token_ && access_token_.empty()) { |
| 541 RequestAccessToken(); |
| 542 return; |
| 543 } |
| 544 |
495 if (start_up_time_.is_null()) { | 545 if (start_up_time_.is_null()) { |
496 start_up_time_ = base::Time::Now(); | 546 start_up_time_ = base::Time::Now(); |
497 last_synced_time_ = sync_prefs_.GetLastSyncedTime(); | 547 last_synced_time_ = sync_prefs_.GetLastSyncedTime(); |
498 | 548 |
499 #if defined(OS_CHROMEOS) | 549 #if defined(OS_CHROMEOS) |
500 std::string bootstrap_token = sync_prefs_.GetEncryptionBootstrapToken(); | 550 std::string bootstrap_token = sync_prefs_.GetEncryptionBootstrapToken(); |
501 if (bootstrap_token.empty()) { | 551 if (bootstrap_token.empty()) { |
502 sync_prefs_.SetEncryptionBootstrapToken( | 552 sync_prefs_.SetEncryptionBootstrapToken( |
503 sync_prefs_.GetSpareBootstrapToken()); | 553 sync_prefs_.GetSpareBootstrapToken()); |
504 } | 554 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
632 // If |backend_| is NULL, save the acknowledgements to replay when | 682 // If |backend_| is NULL, save the acknowledgements to replay when |
633 // it's created and initialized. | 683 // it's created and initialized. |
634 ack_replay_queue_.push_back(std::make_pair(id, ack_handle)); | 684 ack_replay_queue_.push_back(std::make_pair(id, ack_handle)); |
635 } | 685 } |
636 } | 686 } |
637 | 687 |
638 syncer::InvalidatorState ProfileSyncService::GetInvalidatorState() const { | 688 syncer::InvalidatorState ProfileSyncService::GetInvalidatorState() const { |
639 return invalidator_registrar_->GetInvalidatorState(); | 689 return invalidator_registrar_->GetInvalidatorState(); |
640 } | 690 } |
641 | 691 |
| 692 void ProfileSyncService::OnGetTokenSuccess( |
| 693 const OAuth2TokenService::Request* request, |
| 694 const std::string& access_token, |
| 695 const base::Time& expiration_time) { |
| 696 DCHECK_EQ(access_token_request_, request); |
| 697 access_token_request_.reset(); |
| 698 // Reset backoff time after successful response. |
| 699 request_access_token_backoff_.Reset(); |
| 700 access_token_ = access_token; |
| 701 if (backend_) |
| 702 backend_->UpdateCredentials(GetCredentials()); |
| 703 else |
| 704 TryStart(); |
| 705 } |
| 706 |
| 707 void ProfileSyncService::OnGetTokenFailure( |
| 708 const OAuth2TokenService::Request* request, |
| 709 const GoogleServiceAuthError& error) { |
| 710 DCHECK_EQ(access_token_request_, request); |
| 711 DCHECK_NE(error.state(), GoogleServiceAuthError::NONE); |
| 712 access_token_request_.reset(); |
| 713 switch (error.state()) { |
| 714 case GoogleServiceAuthError::CONNECTION_FAILED: |
| 715 case GoogleServiceAuthError::SERVICE_UNAVAILABLE: { |
| 716 // Transient error. Retry after some time. |
| 717 request_access_token_backoff_.InformOfRequest(false); |
| 718 request_access_token_retry_timer_.Start( |
| 719 FROM_HERE, |
| 720 request_access_token_backoff_.GetTimeUntilRelease(), |
| 721 base::Bind(&ProfileSyncService::RequestAccessToken, |
| 722 weak_factory_.GetWeakPtr())); |
| 723 break; |
| 724 } |
| 725 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: { |
| 726 // Report time since token was issued for invalid credentials error. |
| 727 // TODO(pavely): crbug.com/246817 Collect UMA histogram for auth token |
| 728 // rejections from invalidation service. |
| 729 base::Time auth_token_time = |
| 730 AboutSigninInternalsFactory::GetForProfile(profile_)-> |
| 731 GetTokenTime(GaiaConstants::kGaiaOAuth2LoginRefreshToken); |
| 732 if (!auth_token_time.is_null()) { |
| 733 base::TimeDelta age = base::Time::Now() - auth_token_time; |
| 734 if (age < base::TimeDelta::FromHours(1)) { |
| 735 UMA_HISTOGRAM_CUSTOM_TIMES("Sync.AuthServerRejectedTokenAgeShort", |
| 736 age, |
| 737 base::TimeDelta::FromSeconds(1), |
| 738 base::TimeDelta::FromHours(1), |
| 739 50); |
| 740 } |
| 741 UMA_HISTOGRAM_COUNTS("Sync.AuthServerRejectedTokenAgeLong", |
| 742 age.InDays()); |
| 743 } |
| 744 // Fallthrough. |
| 745 } |
| 746 default: { |
| 747 // Show error to user. |
| 748 UpdateAuthErrorState(error); |
| 749 } |
| 750 } |
| 751 } |
| 752 |
642 void ProfileSyncService::EmitInvalidationForTest( | 753 void ProfileSyncService::EmitInvalidationForTest( |
643 const invalidation::ObjectId& id, | 754 const invalidation::ObjectId& id, |
644 const std::string& payload) { | 755 const std::string& payload) { |
645 syncer::ObjectIdSet notify_ids; | 756 syncer::ObjectIdSet notify_ids; |
646 notify_ids.insert(id); | 757 notify_ids.insert(id); |
647 | 758 |
648 const syncer::ObjectIdInvalidationMap& invalidation_map = | 759 const syncer::ObjectIdInvalidationMap& invalidation_map = |
649 ObjectIdSetToInvalidationMap(notify_ids, payload); | 760 ObjectIdSetToInvalidationMap(notify_ids, payload); |
650 OnIncomingInvalidation(invalidation_map); | 761 OnIncomingInvalidation(invalidation_map); |
651 } | 762 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
711 is_auth_in_progress_ = false; | 822 is_auth_in_progress_ = false; |
712 backend_initialized_ = false; | 823 backend_initialized_ = false; |
713 // NULL if we're called from Shutdown(). | 824 // NULL if we're called from Shutdown(). |
714 if (invalidator_registrar_) | 825 if (invalidator_registrar_) |
715 UpdateInvalidatorRegistrarState(); | 826 UpdateInvalidatorRegistrarState(); |
716 cached_passphrase_.clear(); | 827 cached_passphrase_.clear(); |
717 encryption_pending_ = false; | 828 encryption_pending_ = false; |
718 encrypt_everything_ = false; | 829 encrypt_everything_ = false; |
719 encrypted_types_ = syncer::SyncEncryptionHandler::SensitiveTypes(); | 830 encrypted_types_ = syncer::SyncEncryptionHandler::SensitiveTypes(); |
720 passphrase_required_reason_ = syncer::REASON_PASSPHRASE_NOT_REQUIRED; | 831 passphrase_required_reason_ = syncer::REASON_PASSPHRASE_NOT_REQUIRED; |
721 start_up_time_ = base::Time(); | 832 request_access_token_retry_timer_.Stop(); |
722 // Revert to "no auth error". | 833 // Revert to "no auth error". |
723 if (last_auth_error_.state() != GoogleServiceAuthError::NONE) | 834 if (last_auth_error_.state() != GoogleServiceAuthError::NONE) |
724 UpdateAuthErrorState(GoogleServiceAuthError::AuthErrorNone()); | 835 UpdateAuthErrorState(GoogleServiceAuthError::AuthErrorNone()); |
725 | 836 |
726 if (sync_global_error_) { | 837 if (sync_global_error_) { |
727 GlobalErrorServiceFactory::GetForProfile(profile_)->RemoveGlobalError( | 838 GlobalErrorServiceFactory::GetForProfile(profile_)->RemoveGlobalError( |
728 sync_global_error_.get()); | 839 sync_global_error_.get()); |
729 RemoveObserver(sync_global_error_.get()); | 840 RemoveObserver(sync_global_error_.get()); |
730 sync_global_error_.reset(NULL); | 841 sync_global_error_.reset(NULL); |
731 } | 842 } |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1064 default: | 1175 default: |
1065 NOTREACHED(); | 1176 NOTREACHED(); |
1066 return AuthError(AuthError::CONNECTION_FAILED); | 1177 return AuthError(AuthError::CONNECTION_FAILED); |
1067 } | 1178 } |
1068 } | 1179 } |
1069 | 1180 |
1070 } // namespace | 1181 } // namespace |
1071 | 1182 |
1072 void ProfileSyncService::OnConnectionStatusChange( | 1183 void ProfileSyncService::OnConnectionStatusChange( |
1073 syncer::ConnectionStatus status) { | 1184 syncer::ConnectionStatus status) { |
1074 const GoogleServiceAuthError auth_error = | 1185 if (use_oauth2_token_ && status == syncer::CONNECTION_AUTH_ERROR) { |
1075 ConnectionStatusToAuthError(status); | 1186 // Sync or Tango server returned error indicating that access token is |
1076 DVLOG(1) << "Connection status change: " << auth_error.ToString(); | 1187 // invalid. It could be either expired or access is revoked. Let's request |
1077 UpdateAuthErrorState(auth_error); | 1188 // another access token and if access is revoked then request for token will |
| 1189 // fail with corresponding error. |
| 1190 RequestAccessToken(); |
| 1191 } else { |
| 1192 const GoogleServiceAuthError auth_error = |
| 1193 ConnectionStatusToAuthError(status); |
| 1194 DVLOG(1) << "Connection status change: " << auth_error.ToString(); |
| 1195 UpdateAuthErrorState(auth_error); |
| 1196 } |
1078 } | 1197 } |
1079 | 1198 |
1080 void ProfileSyncService::OnStopSyncingPermanently() { | 1199 void ProfileSyncService::OnStopSyncingPermanently() { |
1081 sync_prefs_.SetStartSuppressed(true); | 1200 sync_prefs_.SetStartSuppressed(true); |
1082 DisableForUser(); | 1201 DisableForUser(); |
1083 } | 1202 } |
1084 | 1203 |
1085 void ProfileSyncService::OnPassphraseRequired( | 1204 void ProfileSyncService::OnPassphraseRequired( |
1086 syncer::PassphraseRequiredReason reason, | 1205 syncer::PassphraseRequiredReason reason, |
1087 const sync_pb::EncryptedData& pending_keys) { | 1206 const sync_pb::EncryptedData& pending_keys) { |
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1791 } | 1910 } |
1792 } | 1911 } |
1793 | 1912 |
1794 // If we get here, we don't have pending keys (or at least, the passphrase | 1913 // If we get here, we don't have pending keys (or at least, the passphrase |
1795 // doesn't decrypt them) - just try to re-encrypt using the encryption | 1914 // doesn't decrypt them) - just try to re-encrypt using the encryption |
1796 // passphrase. | 1915 // passphrase. |
1797 if (!IsUsingSecondaryPassphrase()) | 1916 if (!IsUsingSecondaryPassphrase()) |
1798 SetEncryptionPassphrase(passphrase, IMPLICIT); | 1917 SetEncryptionPassphrase(passphrase, IMPLICIT); |
1799 } | 1918 } |
1800 | 1919 |
| 1920 void ProfileSyncService::RequestAccessToken() { |
| 1921 // Only one active request at a time. |
| 1922 if (access_token_request_ != NULL) |
| 1923 return; |
| 1924 request_access_token_retry_timer_.Stop(); |
| 1925 OAuth2TokenService::ScopeSet oauth2_scopes; |
| 1926 for (size_t i = 0; i < arraysize(kOAuth2Scopes); i++) |
| 1927 oauth2_scopes.insert(kOAuth2Scopes[i]); |
| 1928 OAuth2TokenService* token_service = |
| 1929 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); |
| 1930 // Invalidate previous token, otherwise token service will return the same |
| 1931 // token again. |
| 1932 token_service->InvalidateToken(oauth2_scopes, access_token_); |
| 1933 access_token_.clear(); |
| 1934 access_token_request_ = token_service->StartRequest(oauth2_scopes, this); |
| 1935 } |
| 1936 |
1801 void ProfileSyncService::SetEncryptionPassphrase(const std::string& passphrase, | 1937 void ProfileSyncService::SetEncryptionPassphrase(const std::string& passphrase, |
1802 PassphraseType type) { | 1938 PassphraseType type) { |
1803 // This should only be called when the backend has been initialized. | 1939 // This should only be called when the backend has been initialized. |
1804 DCHECK(sync_initialized()); | 1940 DCHECK(sync_initialized()); |
1805 DCHECK(!(type == IMPLICIT && IsUsingSecondaryPassphrase())) << | 1941 DCHECK(!(type == IMPLICIT && IsUsingSecondaryPassphrase())) << |
1806 "Data is already encrypted using an explicit passphrase"; | 1942 "Data is already encrypted using an explicit passphrase"; |
1807 DCHECK(!(type == EXPLICIT && | 1943 DCHECK(!(type == EXPLICIT && |
1808 passphrase_required_reason_ == syncer::REASON_DECRYPTION)) << | 1944 passphrase_required_reason_ == syncer::REASON_DECRYPTION)) << |
1809 "Can not set explicit passphrase when decryption is needed."; | 1945 "Can not set explicit passphrase when decryption is needed."; |
1810 | 1946 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1870 DisableForUser(); | 2006 DisableForUser(); |
1871 } else { | 2007 } else { |
1872 // Sync is no longer disabled by policy. Try starting it up if appropriate. | 2008 // Sync is no longer disabled by policy. Try starting it up if appropriate. |
1873 TryStart(); | 2009 TryStart(); |
1874 } | 2010 } |
1875 } | 2011 } |
1876 | 2012 |
1877 void ProfileSyncService::Observe(int type, | 2013 void ProfileSyncService::Observe(int type, |
1878 const content::NotificationSource& source, | 2014 const content::NotificationSource& source, |
1879 const content::NotificationDetails& details) { | 2015 const content::NotificationDetails& details) { |
| 2016 const char* sync_token_service = use_oauth2_token_ ? |
| 2017 GaiaConstants::kGaiaOAuth2LoginRefreshToken : GaiaConstants::kSyncService; |
1880 switch (type) { | 2018 switch (type) { |
1881 case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: { | 2019 case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: { |
1882 const GoogleServiceSigninSuccessDetails* successful = | 2020 const GoogleServiceSigninSuccessDetails* successful = |
1883 content::Details<const GoogleServiceSigninSuccessDetails>( | 2021 content::Details<const GoogleServiceSigninSuccessDetails>( |
1884 details).ptr(); | 2022 details).ptr(); |
1885 if (!sync_prefs_.IsStartSuppressed() && | 2023 if (!sync_prefs_.IsStartSuppressed() && |
1886 !successful->password.empty()) { | 2024 !successful->password.empty()) { |
1887 cached_passphrase_ = successful->password; | 2025 cached_passphrase_ = successful->password; |
1888 // Try to consume the passphrase we just cached. If the sync backend | 2026 // Try to consume the passphrase we just cached. If the sync backend |
1889 // is not running yet, the passphrase will remain cached until the | 2027 // is not running yet, the passphrase will remain cached until the |
1890 // backend starts up. | 2028 // backend starts up. |
1891 ConsumeCachedPassphraseIfPossible(); | 2029 ConsumeCachedPassphraseIfPossible(); |
1892 } | 2030 } |
1893 #if defined(OS_CHROMEOS) | 2031 #if defined(OS_CHROMEOS) |
1894 RefreshSpareBootstrapToken(successful->password); | 2032 RefreshSpareBootstrapToken(successful->password); |
1895 #endif | 2033 #endif |
1896 if (!sync_initialized() || | 2034 if (!sync_initialized() || |
1897 GetAuthError().state() != AuthError::NONE) { | 2035 GetAuthError().state() != AuthError::NONE) { |
1898 // Track the fact that we're still waiting for auth to complete. | 2036 // Track the fact that we're still waiting for auth to complete. |
1899 is_auth_in_progress_ = true; | 2037 is_auth_in_progress_ = true; |
1900 } | 2038 } |
1901 break; | 2039 break; |
1902 } | 2040 } |
1903 case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: { | 2041 case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: { |
| 2042 // TODO(atwilson): sync shouldn't report refresh token request failures. |
| 2043 // TokenService should do that instead. |
1904 const TokenService::TokenRequestFailedDetails& token_details = | 2044 const TokenService::TokenRequestFailedDetails& token_details = |
1905 *(content::Details<const TokenService::TokenRequestFailedDetails>( | 2045 *(content::Details<const TokenService::TokenRequestFailedDetails>( |
1906 details).ptr()); | 2046 details).ptr()); |
1907 if (IsTokenServiceRelevant(token_details.service()) && | 2047 if (token_details.service() == sync_token_service && |
1908 !IsSyncTokenAvailable()) { | 2048 !IsOAuthRefreshTokenAvailable()) { |
1909 // The additional check around IsSyncTokenAvailable() above prevents us | 2049 // The additional check around IsOAuthRefreshTokenAvailable() above |
1910 // sounding the alarm if we actually have a valid token but a refresh | 2050 // prevents us sounding the alarm if we actually have a valid token but |
1911 // attempt by TokenService failed for any variety of reasons (e.g. flaky | 2051 // a refresh attempt by TokenService failed for any variety of reasons |
1912 // network). It's possible the token we do have is also invalid, but in | 2052 // (e.g. flaky network). It's possible the token we do have is also |
1913 // that case we should already have (or can expect) an auth error sent | 2053 // invalid, but in that case we should already have (or can expect) an |
1914 // from the sync backend. | 2054 // auth error sent from the sync backend. |
1915 AuthError error(AuthError::INVALID_GAIA_CREDENTIALS); | 2055 AuthError error(AuthError::INVALID_GAIA_CREDENTIALS); |
1916 UpdateAuthErrorState(error); | 2056 UpdateAuthErrorState(error); |
1917 } | 2057 } |
1918 break; | 2058 break; |
1919 } | 2059 } |
1920 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { | 2060 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { |
| 2061 // TODO(atwilson): Listen for notifications on OAuth2TokenService |
| 2062 // (crbug.com/243737) |
1921 const TokenService::TokenAvailableDetails& token_details = | 2063 const TokenService::TokenAvailableDetails& token_details = |
1922 *(content::Details<const TokenService::TokenAvailableDetails>( | 2064 *(content::Details<const TokenService::TokenAvailableDetails>( |
1923 details).ptr()); | 2065 details).ptr()); |
1924 if (!IsTokenServiceRelevant(token_details.service())) | 2066 if (token_details.service() != sync_token_service) |
1925 break; | 2067 break; |
1926 } // Fall through. | 2068 } // Fall through. |
1927 case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: { | 2069 case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: { |
1928 // This notification gets fired when TokenService loads the tokens | 2070 // This notification gets fired when TokenService loads the tokens |
1929 // from storage. | 2071 // from storage. |
1930 // Initialize the backend if sync is enabled. If the sync token was | 2072 // Initialize the backend if sync is enabled. If the sync token was |
1931 // not loaded, GetCredentials() will generate invalid credentials to | 2073 // not loaded, GetCredentials() will generate invalid credentials to |
1932 // cause the backend to generate an auth error (crbug.com/121755). | 2074 // cause the backend to generate an auth error (crbug.com/121755). |
1933 if (backend_) | 2075 if (backend_) { |
1934 backend_->UpdateCredentials(GetCredentials()); | 2076 if (use_oauth2_token_) |
1935 else | 2077 RequestAccessToken(); |
| 2078 else |
| 2079 backend_->UpdateCredentials(GetCredentials()); |
| 2080 } else { |
1936 TryStart(); | 2081 TryStart(); |
| 2082 } |
1937 break; | 2083 break; |
1938 } | 2084 } |
1939 case chrome::NOTIFICATION_TOKENS_CLEARED: { | 2085 case chrome::NOTIFICATION_TOKENS_CLEARED: { |
1940 // GetCredentials() will generate invalid credentials to cause the backend | 2086 // GetCredentials() will generate invalid credentials to cause the backend |
1941 // to generate an auth error. | 2087 // to generate an auth error. |
| 2088 access_token_.clear(); |
1942 if (backend_) | 2089 if (backend_) |
1943 backend_->UpdateCredentials(GetCredentials()); | 2090 backend_->UpdateCredentials(GetCredentials()); |
1944 break; | 2091 break; |
1945 } | 2092 } |
1946 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: | 2093 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: |
1947 sync_disabled_by_admin_ = false; | 2094 sync_disabled_by_admin_ = false; |
1948 DisableForUser(); | 2095 DisableForUser(); |
1949 break; | 2096 break; |
1950 default: { | 2097 default: { |
1951 NOTREACHED(); | 2098 NOTREACHED(); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2068 std::string ProfileSyncService::GetEffectiveUsername() { | 2215 std::string ProfileSyncService::GetEffectiveUsername() { |
2069 #if defined(ENABLE_MANAGED_USERS) | 2216 #if defined(ENABLE_MANAGED_USERS) |
2070 if (ManagedUserService::ProfileIsManaged(profile_)) { | 2217 if (ManagedUserService::ProfileIsManaged(profile_)) { |
2071 DCHECK_EQ(std::string(), signin_->GetAuthenticatedUsername()); | 2218 DCHECK_EQ(std::string(), signin_->GetAuthenticatedUsername()); |
2072 return ManagedUserService::GetManagedUserPseudoEmail(); | 2219 return ManagedUserService::GetManagedUserPseudoEmail(); |
2073 } | 2220 } |
2074 #endif | 2221 #endif |
2075 | 2222 |
2076 return signin_->GetAuthenticatedUsername(); | 2223 return signin_->GetAuthenticatedUsername(); |
2077 } | 2224 } |
2078 | |
OLD | NEW |