| 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 30 matching lines...) Expand all Loading... |
| 41 #include "chrome/browser/sync/js/js_event_details.h" | 41 #include "chrome/browser/sync/js/js_event_details.h" |
| 42 #include "chrome/browser/sync/profile_sync_components_factory_impl.h" | 42 #include "chrome/browser/sync/profile_sync_components_factory_impl.h" |
| 43 #include "chrome/browser/sync/sync_global_error.h" | 43 #include "chrome/browser/sync/sync_global_error.h" |
| 44 #include "chrome/browser/sync/util/cryptographer.h" | 44 #include "chrome/browser/sync/util/cryptographer.h" |
| 45 #include "chrome/browser/sync/util/oauth.h" | 45 #include "chrome/browser/sync/util/oauth.h" |
| 46 #include "chrome/browser/ui/browser.h" | 46 #include "chrome/browser/ui/browser.h" |
| 47 #include "chrome/browser/ui/browser_list.h" | 47 #include "chrome/browser/ui/browser_list.h" |
| 48 #include "chrome/browser/ui/browser_window.h" | 48 #include "chrome/browser/ui/browser_window.h" |
| 49 #include "chrome/browser/ui/global_error_service.h" | 49 #include "chrome/browser/ui/global_error_service.h" |
| 50 #include "chrome/browser/ui/global_error_service_factory.h" | 50 #include "chrome/browser/ui/global_error_service_factory.h" |
| 51 #include "chrome/browser/ui/webui/signin/login_ui_service.h" |
| 52 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" |
| 51 #include "chrome/common/chrome_notification_types.h" | 53 #include "chrome/common/chrome_notification_types.h" |
| 52 #include "chrome/common/chrome_switches.h" | 54 #include "chrome/common/chrome_switches.h" |
| 53 #include "chrome/common/chrome_version_info.h" | 55 #include "chrome/common/chrome_version_info.h" |
| 54 #include "chrome/common/net/gaia/gaia_constants.h" | 56 #include "chrome/common/net/gaia/gaia_constants.h" |
| 55 #include "chrome/common/time_format.h" | 57 #include "chrome/common/time_format.h" |
| 56 #include "chrome/common/url_constants.h" | 58 #include "chrome/common/url_constants.h" |
| 57 #include "content/public/browser/notification_details.h" | 59 #include "content/public/browser/notification_details.h" |
| 58 #include "content/public/browser/notification_source.h" | 60 #include "content/public/browser/notification_source.h" |
| 59 #include "grit/generated_resources.h" | 61 #include "grit/generated_resources.h" |
| 60 #include "net/base/cookie_monster.h" | 62 #include "net/base/cookie_monster.h" |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 bool ProfileSyncService::AreCredentialsAvailable() { | 152 bool ProfileSyncService::AreCredentialsAvailable() { |
| 151 return AreCredentialsAvailable(false); | 153 return AreCredentialsAvailable(false); |
| 152 } | 154 } |
| 153 | 155 |
| 154 bool ProfileSyncService::AreCredentialsAvailable( | 156 bool ProfileSyncService::AreCredentialsAvailable( |
| 155 bool check_oauth_login_token) { | 157 bool check_oauth_login_token) { |
| 156 if (IsManaged()) { | 158 if (IsManaged()) { |
| 157 return false; | 159 return false; |
| 158 } | 160 } |
| 159 | 161 |
| 162 // If we have start suppressed, then basically just act like we have no |
| 163 // credentials (login is required to fix this, since we need the user's |
| 164 // passphrase to encrypt/decrypt anyway). |
| 165 // TODO(sync): Revisit this when we move to a server-based keystore. |
| 166 if (sync_prefs_.IsStartSuppressed()) |
| 167 return false; |
| 168 |
| 160 // CrOS user is always logged in. Chrome uses signin_ to check logged in. | 169 // CrOS user is always logged in. Chrome uses signin_ to check logged in. |
| 161 if (signin_->GetAuthenticatedUsername().empty()) | 170 if (signin_->GetAuthenticatedUsername().empty()) |
| 162 return false; | 171 return false; |
| 163 | 172 |
| 164 TokenService* token_service = profile()->GetTokenService(); | 173 TokenService* token_service = profile()->GetTokenService(); |
| 165 if (!token_service) | 174 if (!token_service) |
| 166 return false; | 175 return false; |
| 167 | 176 |
| 168 // TODO(chron): Verify CrOS unit test behavior. | 177 // TODO(chron): Verify CrOS unit test behavior. |
| 169 if (!token_service->HasTokenForService(browser_sync::SyncServiceName())) | 178 if (!token_service->HasTokenForService(browser_sync::SyncServiceName())) |
| (...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 if (!to_register.Empty() && HasSyncSetupCompleted() && migrator_.get()) { | 715 if (!to_register.Empty() && HasSyncSetupCompleted() && migrator_.get()) { |
| 707 DVLOG(1) << "Dynamically enabling new datatypes: " | 716 DVLOG(1) << "Dynamically enabling new datatypes: " |
| 708 << syncable::ModelTypeSetToString(to_register); | 717 << syncable::ModelTypeSetToString(to_register); |
| 709 OnMigrationNeededForTypes(to_register); | 718 OnMigrationNeededForTypes(to_register); |
| 710 } | 719 } |
| 711 } | 720 } |
| 712 } | 721 } |
| 713 | 722 |
| 714 void ProfileSyncService::UpdateAuthErrorState( | 723 void ProfileSyncService::UpdateAuthErrorState( |
| 715 const GoogleServiceAuthError& error) { | 724 const GoogleServiceAuthError& error) { |
| 725 is_auth_in_progress_ = false; |
| 716 last_auth_error_ = error; | 726 last_auth_error_ = error; |
| 717 // Protect against the in-your-face dialogs that pop out of nowhere. | |
| 718 // Require the user to click somewhere to run the setup wizard in the case | |
| 719 // of a steady-state auth failure. | |
| 720 if (WizardIsVisible()) { | |
| 721 wizard_.Step(last_auth_error_.state() == AuthError::NONE ? | |
| 722 SyncSetupWizard::GAIA_SUCCESS : SyncSetupWizard::GetLoginState()); | |
| 723 } else { | |
| 724 auth_error_time_ = base::TimeTicks::Now(); | |
| 725 } | |
| 726 | |
| 727 if (!auth_start_time_.is_null()) { | |
| 728 UMA_HISTOGRAM_TIMES("Sync.AuthorizationTimeInNetwork", | |
| 729 base::TimeTicks::Now() - auth_start_time_); | |
| 730 auth_start_time_ = base::TimeTicks(); | |
| 731 } | |
| 732 | 727 |
| 733 // Fan the notification out to interested UI-thread components. | 728 // Fan the notification out to interested UI-thread components. |
| 734 NotifyObservers(); | 729 NotifyObservers(); |
| 735 } | 730 } |
| 736 | 731 |
| 737 void ProfileSyncService::OnAuthError() { | 732 void ProfileSyncService::OnAuthError() { |
| 738 UpdateAuthErrorState(backend_->GetAuthError()); | 733 UpdateAuthErrorState(backend_->GetAuthError()); |
| 739 } | 734 } |
| 740 | 735 |
| 741 void ProfileSyncService::OnStopSyncingPermanently() { | 736 void ProfileSyncService::OnStopSyncingPermanently() { |
| 742 if (SetupInProgress()) { | 737 UpdateAuthErrorState( |
| 743 wizard_.Step(SyncSetupWizard::SETUP_ABORTED_BY_PENDING_CLEAR); | 738 GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE)); |
| 739 |
| 740 // If the wizard is visible, close it. |
| 741 if (WizardIsVisible()) { |
| 742 wizard_.Step(SyncSetupWizard::ABORT); |
| 744 expect_sync_configuration_aborted_ = true; | 743 expect_sync_configuration_aborted_ = true; |
| 745 } | 744 } |
| 746 sync_prefs_.SetStartSuppressed(true); | 745 sync_prefs_.SetStartSuppressed(true); |
| 747 DisableForUser(); | 746 DisableForUser(); |
| 748 } | 747 } |
| 749 | 748 |
| 750 void ProfileSyncService::OnClearServerDataTimeout() { | 749 void ProfileSyncService::OnClearServerDataTimeout() { |
| 751 if (clear_server_data_state_ != CLEAR_SUCCEEDED && | 750 if (clear_server_data_state_ != CLEAR_SUCCEEDED && |
| 752 clear_server_data_state_ != CLEAR_FAILED) { | 751 clear_server_data_state_ != CLEAR_FAILED) { |
| 753 clear_server_data_state_ = CLEAR_FAILED; | 752 clear_server_data_state_ = CLEAR_FAILED; |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 933 case browser_sync::DISABLE_SYNC_ON_CLIENT: | 932 case browser_sync::DISABLE_SYNC_ON_CLIENT: |
| 934 OnStopSyncingPermanently(); | 933 OnStopSyncingPermanently(); |
| 935 break; | 934 break; |
| 936 default: | 935 default: |
| 937 NOTREACHED(); | 936 NOTREACHED(); |
| 938 } | 937 } |
| 939 NotifyObservers(); | 938 NotifyObservers(); |
| 940 } | 939 } |
| 941 | 940 |
| 942 void ProfileSyncService::ShowLoginDialog() { | 941 void ProfileSyncService::ShowLoginDialog() { |
| 943 if (WizardIsVisible()) { | 942 // TODO(atwilson): Remove this API and have the callers directly call |
| 944 wizard_.Focus(); | 943 // LoginUIService. |
| 945 // Force the wizard to step to the login screen (which will only actually | 944 LoginUIServiceFactory::GetForProfile(profile_)->ShowLoginUI(); |
| 946 // happen if the transition is valid). | |
| 947 wizard_.Step(SyncSetupWizard::GetLoginState()); | |
| 948 return; | |
| 949 } | |
| 950 | |
| 951 if (!auth_error_time_.is_null()) { | |
| 952 UMA_HISTOGRAM_LONG_TIMES("Sync.ReauthorizationTime", | |
| 953 base::TimeTicks::Now() - auth_error_time_); | |
| 954 auth_error_time_ = base::TimeTicks(); // Reset auth_error_time_ to null. | |
| 955 } | |
| 956 | |
| 957 ShowSyncSetupWithWizard(SyncSetupWizard::GetLoginState()); | |
| 958 | |
| 959 NotifyObservers(); | |
| 960 } | 945 } |
| 961 | 946 |
| 962 void ProfileSyncService::ShowErrorUI() { | 947 void ProfileSyncService::ShowErrorUI() { |
| 963 if (WizardIsVisible()) { | 948 if (WizardIsVisible()) { |
| 964 wizard_.Focus(); | 949 wizard_.Focus(); |
| 965 return; | 950 return; |
| 966 } | 951 } |
| 967 | 952 |
| 968 if (last_auth_error_.state() != AuthError::NONE) | 953 // Figure out what kind of error we've encountered. There are only 3 kinds: |
| 954 // 1) auth error. |
| 955 // 2) server-initiated error |
| 956 // 3) passphrase error |
| 957 // Any other errors (such as unrecoverable error) should be handled by the UI |
| 958 // itself and should not result in a call to ShowErrorUI. |
| 959 if (last_auth_error_.state() != AuthError::NONE) { |
| 969 ShowLoginDialog(); | 960 ShowLoginDialog(); |
| 970 else if (ShouldShowActionOnUI(last_actionable_error_)) | 961 } else if (ShouldShowActionOnUI(last_actionable_error_)) { |
| 971 ShowSyncSetup(chrome::kPersonalOptionsSubPage); | 962 ShowSyncSetup(chrome::kPersonalOptionsSubPage); |
| 972 else | 963 } else { |
| 973 ShowSyncSetupWithWizard(SyncSetupWizard::NONFATAL_ERROR); | 964 // We should only get here for passphrase error. |
| 965 DCHECK(IsPassphraseRequired()); |
| 966 ShowSyncSetupWithWizard(SyncSetupWizard::ENTER_PASSPHRASE); |
| 967 } |
| 974 } | 968 } |
| 975 | 969 |
| 976 void ProfileSyncService::ShowConfigure(bool sync_everything) { | 970 void ProfileSyncService::ShowConfigure(bool sync_everything) { |
| 977 if (!sync_initialized()) { | 971 if (!sync_initialized()) { |
| 978 LOG(ERROR) << "Attempted to show sync configure before backend ready."; | 972 LOG(ERROR) << "Attempted to show sync configure before backend ready."; |
| 979 return; | 973 return; |
| 980 } | 974 } |
| 981 if (WizardIsVisible()) { | 975 if (WizardIsVisible()) { |
| 982 wizard_.Focus(); | 976 wizard_.Focus(); |
| 983 return; | 977 return; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1049 | 1043 |
| 1050 bool ProfileSyncService::sync_initialized() const { | 1044 bool ProfileSyncService::sync_initialized() const { |
| 1051 return backend_initialized_; | 1045 return backend_initialized_; |
| 1052 } | 1046 } |
| 1053 | 1047 |
| 1054 bool ProfileSyncService::unrecoverable_error_detected() const { | 1048 bool ProfileSyncService::unrecoverable_error_detected() const { |
| 1055 return unrecoverable_error_detected_; | 1049 return unrecoverable_error_detected_; |
| 1056 } | 1050 } |
| 1057 | 1051 |
| 1058 bool ProfileSyncService::UIShouldDepictAuthInProgress() const { | 1052 bool ProfileSyncService::UIShouldDepictAuthInProgress() const { |
| 1059 return is_auth_in_progress_; | 1053 return signin()->AuthInProgress(); |
| 1060 } | |
| 1061 | |
| 1062 void ProfileSyncService::SetUIShouldDepictAuthInProgress( | |
| 1063 bool auth_in_progress) { | |
| 1064 is_auth_in_progress_ = auth_in_progress; | |
| 1065 // TODO(atwilson): Figure out if we still need to track this or if we should | |
| 1066 // move this up to the UI (or break it out into two stats that track GAIA | |
| 1067 // auth and sync auth separately). | |
| 1068 if (is_auth_in_progress_) | |
| 1069 auth_start_time_ = base::TimeTicks::Now(); | |
| 1070 NotifyObservers(); | |
| 1071 } | 1054 } |
| 1072 | 1055 |
| 1073 bool ProfileSyncService::IsPassphraseRequired() const { | 1056 bool ProfileSyncService::IsPassphraseRequired() const { |
| 1074 return passphrase_required_reason_ != | 1057 return passphrase_required_reason_ != |
| 1075 sync_api::REASON_PASSPHRASE_NOT_REQUIRED; | 1058 sync_api::REASON_PASSPHRASE_NOT_REQUIRED; |
| 1076 } | 1059 } |
| 1077 | 1060 |
| 1078 // TODO(zea): Rename this IsPassphraseNeededFromUI and ensure it's used | 1061 // TODO(zea): Rename this IsPassphraseNeededFromUI and ensure it's used |
| 1079 // appropriately (see http://crbug.com/91379). | 1062 // appropriately (see http://crbug.com/91379). |
| 1080 bool ProfileSyncService::IsPassphraseRequiredForDecryption() const { | 1063 bool ProfileSyncService::IsPassphraseRequiredForDecryption() const { |
| (...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1437 *(content::Details<const GoogleServiceAuthError>(details).ptr()); | 1420 *(content::Details<const GoogleServiceAuthError>(details).ptr()); |
| 1438 UpdateAuthErrorState(error); | 1421 UpdateAuthErrorState(error); |
| 1439 break; | 1422 break; |
| 1440 } | 1423 } |
| 1441 case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: { | 1424 case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: { |
| 1442 const GoogleServiceSigninSuccessDetails* successful = | 1425 const GoogleServiceSigninSuccessDetails* successful = |
| 1443 content::Details<const GoogleServiceSigninSuccessDetails>( | 1426 content::Details<const GoogleServiceSigninSuccessDetails>( |
| 1444 details).ptr(); | 1427 details).ptr(); |
| 1445 // The user has submitted credentials, which indicates they don't | 1428 // The user has submitted credentials, which indicates they don't |
| 1446 // want to suppress start up anymore. | 1429 // want to suppress start up anymore. |
| 1430 // TODO(sync): Remove this when sync is no longer tied to browser signin. |
| 1431 // http://crbug/com/95269. |
| 1447 sync_prefs_.SetStartSuppressed(false); | 1432 sync_prefs_.SetStartSuppressed(false); |
| 1448 | 1433 |
| 1449 // Because we specify IMPLICIT to SetPassphrase, we know it won't override | 1434 // Because we specify IMPLICIT to SetPassphrase, we know it won't override |
| 1450 // an explicit one. Thus, we either update the implicit passphrase | 1435 // an explicit one. Thus, we either update the implicit passphrase |
| 1451 // (idempotent if the passphrase didn't actually change), or the user has | 1436 // (idempotent if the passphrase didn't actually change), or the user has |
| 1452 // an explicit passphrase set so this becomes a no-op. | 1437 // an explicit passphrase set so this becomes a no-op. |
| 1453 if (!successful->password.empty()) | 1438 if (!successful->password.empty()) |
| 1454 SetPassphrase(successful->password, IMPLICIT, INTERNAL); | 1439 SetPassphrase(successful->password, IMPLICIT, INTERNAL); |
| 1440 |
| 1441 if (!sync_initialized() || |
| 1442 GetAuthError().state() != GoogleServiceAuthError::NONE) { |
| 1443 // Track the fact that we're still waiting for auth to complete. |
| 1444 is_auth_in_progress_ = true; |
| 1445 } |
| 1455 break; | 1446 break; |
| 1456 } | 1447 } |
| 1457 case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: { | 1448 case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: { |
| 1458 const TokenService::TokenRequestFailedDetails& token_details = | 1449 const TokenService::TokenRequestFailedDetails& token_details = |
| 1459 *(content::Details<const TokenService::TokenRequestFailedDetails>( | 1450 *(content::Details<const TokenService::TokenRequestFailedDetails>( |
| 1460 details).ptr()); | 1451 details).ptr()); |
| 1461 if (IsTokenServiceRelevant(token_details.service())) { | 1452 if (IsTokenServiceRelevant(token_details.service())) { |
| 1462 GoogleServiceAuthError error( | 1453 GoogleServiceAuthError error( |
| 1463 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); | 1454 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); |
| 1464 UpdateAuthErrorState(error); | 1455 UpdateAuthErrorState(error); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1606 << "Unrecoverable error."; | 1597 << "Unrecoverable error."; |
| 1607 } else { | 1598 } else { |
| 1608 DVLOG(0) << "ConfigureDataTypeManager not invoked because backend is not " | 1599 DVLOG(0) << "ConfigureDataTypeManager not invoked because backend is not " |
| 1609 << "initialized"; | 1600 << "initialized"; |
| 1610 } | 1601 } |
| 1611 } | 1602 } |
| 1612 | 1603 |
| 1613 const FailedDatatypesHandler& ProfileSyncService::failed_datatypes_handler() { | 1604 const FailedDatatypesHandler& ProfileSyncService::failed_datatypes_handler() { |
| 1614 return failed_datatypes_handler_; | 1605 return failed_datatypes_handler_; |
| 1615 } | 1606 } |
| OLD | NEW |