summaryrefslogtreecommitdiff
path: root/chromium/components/signin
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-08-30 10:22:43 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-08-30 12:36:28 +0000
commit271a6c3487a14599023a9106329505597638d793 (patch)
treee040d58ffc86c1480b79ca8528020ca9ec919bf8 /chromium/components/signin
parent7b2ffa587235a47d4094787d72f38102089f402a (diff)
downloadqtwebengine-chromium-271a6c3487a14599023a9106329505597638d793.tar.gz
BASELINE: Update Chromium to 77.0.3865.59
Change-Id: I1e89a5f3b009a9519a6705102ad65c92fe736f21 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/components/signin')
-rw-r--r--chromium/components/signin/DEPS17
-rw-r--r--chromium/components/signin/OWNERS1
-rw-r--r--chromium/components/signin/core/browser/BUILD.gn218
-rw-r--r--chromium/components/signin/core/browser/DEPS13
-rw-r--r--chromium/components/signin/core/browser/about_signin_internals.cc117
-rw-r--r--chromium/components/signin/core/browser/about_signin_internals.h36
-rw-r--r--chromium/components/signin/core/browser/account_investigator.cc14
-rw-r--r--chromium/components/signin/core/browser/account_investigator.h16
-rw-r--r--chromium/components/signin/core/browser/account_investigator_unittest.cc32
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor.cc116
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor.h41
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor_delegate.cc54
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor_delegate.h35
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor_delegate_unittest.cc23
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor_unittest.cc621
-rw-r--r--chromium/components/signin/core/browser/android/BUILD.gn1
-rw-r--r--chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountIdProvider.java2
-rw-r--r--chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java53
-rw-r--r--chromium/components/signin/core/browser/chrome_connected_header_helper.cc2
-rw-r--r--chromium/components/signin/core/browser/chrome_connected_header_helper.h2
-rw-r--r--chromium/components/signin/core/browser/consistency_cookie_manager_android.cc6
-rw-r--r--chromium/components/signin/core/browser/consistency_cookie_manager_android.h8
-rw-r--r--chromium/components/signin/core/browser/consistency_cookie_manager_base.cc10
-rw-r--r--chromium/components/signin/core/browser/consistency_cookie_manager_base.h2
-rw-r--r--chromium/components/signin/core/browser/consistency_cookie_manager_unittest.cc26
-rw-r--r--chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc117
-rw-r--r--chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h49
-rw-r--r--chromium/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc33
-rw-r--r--chromium/components/signin/core/browser/dice_header_helper.cc2
-rw-r--r--chromium/components/signin/core/browser/dice_header_helper.h2
-rw-r--r--chromium/components/signin/core/browser/fake_profile_oauth2_token_service.cc205
-rw-r--r--chromium/components/signin/core/browser/identity_manager_wrapper.cc31
-rw-r--r--chromium/components/signin/core/browser/identity_manager_wrapper.h42
-rw-r--r--chromium/components/signin/core/browser/identity_utils.h40
-rw-r--r--chromium/components/signin/core/browser/identity_utils_unittest.cc101
-rw-r--r--chromium/components/signin/core/browser/mice_account_reconcilor_delegate.cc24
-rw-r--r--chromium/components/signin/core/browser/mice_account_reconcilor_delegate.h14
-rw-r--r--chromium/components/signin/core/browser/mice_account_reconcilor_delegate_unittest.cc19
-rw-r--r--chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.cc16
-rw-r--r--chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.h24
-rw-r--r--chromium/components/signin/core/browser/multilogin_parameters.cc28
-rw-r--r--chromium/components/signin/core/browser/multilogin_parameters.h33
-rw-r--r--chromium/components/signin/core/browser/oauth_multilogin_token_fetcher.h74
-rw-r--r--chromium/components/signin/core/browser/profile_oauth2_token_service.cc233
-rw-r--r--chromium/components/signin/core/browser/profile_oauth2_token_service.h133
-rw-r--r--chromium/components/signin/core/browser/resources/OWNERS2
-rw-r--r--chromium/components/signin/core/browser/resources/signin_index.html10
-rw-r--r--chromium/components/signin/core/browser/signin_error_controller.cc4
-rw-r--r--chromium/components/signin/core/browser/signin_error_controller.h12
-rw-r--r--chromium/components/signin/core/browser/signin_error_controller_unittest.cc45
-rw-r--r--chromium/components/signin/core/browser/signin_header_helper.cc26
-rw-r--r--chromium/components/signin/core/browser/signin_header_helper.h15
-rw-r--r--chromium/components/signin/core/browser/signin_header_helper_unittest.cc4
-rw-r--r--chromium/components/signin/core/browser/signin_investigator.cc26
-rw-r--r--chromium/components/signin/core/browser/signin_investigator.h21
-rw-r--r--chromium/components/signin/core/browser/signin_investigator_unittest.cc16
-rw-r--r--chromium/components/signin/core/browser/signin_manager.cc178
-rw-r--r--chromium/components/signin/core/browser/signin_manager.h118
-rw-r--r--chromium/components/signin/core/browser/signin_status_metrics_provider.cc9
-rw-r--r--chromium/components/signin/core/browser/signin_status_metrics_provider.h12
-rw-r--r--chromium/components/signin/core/browser/signin_status_metrics_provider_delegate.h4
-rw-r--r--chromium/components/signin/internal/identity_manager/BUILD.gn188
-rw-r--r--chromium/components/signin/internal/identity_manager/DEPS16
-rw-r--r--chromium/components/signin/internal/identity_manager/account_fetcher_service.cc (renamed from chromium/components/signin/core/browser/account_fetcher_service.cc)66
-rw-r--r--chromium/components/signin/internal/identity_manager/account_fetcher_service.h (renamed from chromium/components/signin/core/browser/account_fetcher_service.h)45
-rw-r--r--chromium/components/signin/internal/identity_manager/account_info_fetcher.cc (renamed from chromium/components/signin/core/browser/account_info_fetcher.cc)21
-rw-r--r--chromium/components/signin/internal/identity_manager/account_info_fetcher.h (renamed from chromium/components/signin/core/browser/account_info_fetcher.h)31
-rw-r--r--chromium/components/signin/internal/identity_manager/account_info_util.cc (renamed from chromium/components/signin/core/browser/account_info_util.cc)4
-rw-r--r--chromium/components/signin/internal/identity_manager/account_info_util.h (renamed from chromium/components/signin/core/browser/account_info_util.h)8
-rw-r--r--chromium/components/signin/internal/identity_manager/account_info_util_unittest.cc (renamed from chromium/components/signin/core/browser/account_info_util_unittest.cc)4
-rw-r--r--chromium/components/signin/internal/identity_manager/account_tracker_service.cc (renamed from chromium/components/signin/core/browser/account_tracker_service.cc)64
-rw-r--r--chromium/components/signin/internal/identity_manager/account_tracker_service.h (renamed from chromium/components/signin/core/browser/account_tracker_service.h)51
-rw-r--r--chromium/components/signin/internal/identity_manager/account_tracker_service_unittest.cc (renamed from chromium/components/signin/core/browser/account_tracker_service_unittest.cc)205
-rw-r--r--chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc66
-rw-r--r--chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h61
-rw-r--r--chromium/components/signin/internal/identity_manager/accounts_mutator_impl.cc116
-rw-r--r--chromium/components/signin/internal/identity_manager/accounts_mutator_impl.h75
-rw-r--r--chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.cc (renamed from chromium/components/signin/core/browser/child_account_info_fetcher_android.cc)16
-rw-r--r--chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.h (renamed from chromium/components/signin/core/browser/child_account_info_fetcher_android.h)11
-rw-r--r--chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.cc29
-rw-r--r--chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h31
-rw-r--r--chromium/components/signin/internal/identity_manager/diagnostics_provider_impl.cc44
-rw-r--r--chromium/components/signin/internal/identity_manager/diagnostics_provider_impl.h45
-rw-r--r--chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.cc101
-rw-r--r--chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h (renamed from chromium/components/signin/core/browser/fake_profile_oauth2_token_service.h)84
-rw-r--r--chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.cc170
-rw-r--r--chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.h87
-rw-r--r--chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc (renamed from chromium/components/signin/core/browser/gaia_cookie_manager_service.cc)187
-rw-r--r--chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.h (renamed from chromium/components/signin/core/browser/gaia_cookie_manager_service.h)140
-rw-r--r--chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service_unittest.cc (renamed from chromium/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc)189
-rw-r--r--chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc (renamed from chromium/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate.cc)192
-rw-r--r--chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.h (renamed from chromium/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate.h)67
-rw-r--r--chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc (renamed from chromium/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate_unittest.cc)342
-rw-r--r--chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android.cc (renamed from chromium/components/signin/core/browser/oauth2_token_service_delegate_android.cc)114
-rw-r--r--chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android.h (renamed from chromium/components/signin/core/browser/oauth2_token_service_delegate_android.h)64
-rw-r--r--chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android_unittest.cc (renamed from chromium/components/signin/core/browser/oauth2_token_service_delegate_android_unittest.cc)34
-rw-r--r--chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.cc (renamed from chromium/components/signin/core/browser/oauth_multilogin_helper.cc)109
-rw-r--r--chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.h (renamed from chromium/components/signin/core/browser/oauth_multilogin_helper.h)33
-rw-r--r--chromium/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc (renamed from chromium/components/signin/core/browser/oauth_multilogin_helper_unittest.cc)108
-rw-r--r--chromium/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.cc (renamed from chromium/components/signin/core/browser/oauth_multilogin_token_fetcher.cc)40
-rw-r--r--chromium/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.h84
-rw-r--r--chromium/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher_unittest.cc (renamed from chromium/components/signin/core/browser/oauth_multilogin_token_fetcher_unittest.cc)130
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_manager.cc (renamed from chromium/components/signin/core/browser/signin_manager_base.cc)248
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_manager.h (renamed from chromium/components/signin/core/browser/signin_manager_base.h)183
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_manager_unittest.cc (renamed from chromium/components/signin/core/browser/signin_manager_unittest.cc)244
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.cc90
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.h50
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_policy_manager.h29
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl.cc107
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl.h62
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl_unittest.cc75
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.cc476
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.h320
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc214
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.h68
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.cc136
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h188
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.cc (renamed from chromium/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos.cc)98
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.h (renamed from chromium/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos.h)33
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos_unittest.cc (renamed from chromium/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos_unittest.cc)140
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h (renamed from chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h)79
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.mm (renamed from chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.mm)153
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios_unittest.mm (renamed from chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate_unittest.mm)64
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_unittest.cc57
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_unittest.cc824
-rw-r--r--chromium/components/signin/internal/identity_manager/ubertoken_fetcher_impl.cc (renamed from chromium/components/signin/core/browser/ubertoken_fetcher_impl.cc)21
-rw-r--r--chromium/components/signin/internal/identity_manager/ubertoken_fetcher_impl.h (renamed from chromium/components/signin/core/browser/ubertoken_fetcher_impl.h)47
-rw-r--r--chromium/components/signin/internal/identity_manager/ubertoken_fetcher_impl_unittest.cc (renamed from chromium/components/signin/core/browser/ubertoken_fetcher_impl_unittest.cc)27
-rw-r--r--chromium/components/signin/ios/DEPS2
-rw-r--r--chromium/components/signin/ios/browser/BUILD.gn50
-rw-r--r--chromium/components/signin/ios/browser/DEPS10
-rw-r--r--chromium/components/signin/ios/browser/account_consistency_service.h16
-rw-r--r--chromium/components/signin/ios/browser/account_consistency_service.mm15
-rw-r--r--chromium/components/signin/ios/browser/account_consistency_service_unittest.mm29
-rw-r--r--chromium/components/signin/ios/browser/active_state_manager_impl.mm2
-rw-r--r--chromium/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.mm83
-rw-r--r--chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.mm28
-rw-r--r--chromium/components/signin/ios/browser/wait_for_network_callback_helper_unittest.cc13
-rw-r--r--chromium/components/signin/public/base/BUILD.gn93
-rw-r--r--chromium/components/signin/public/base/DEPS3
-rw-r--r--chromium/components/signin/public/base/account_consistency_method.cc (renamed from chromium/components/signin/core/browser/account_consistency_method.cc)2
-rw-r--r--chromium/components/signin/public/base/account_consistency_method.h (renamed from chromium/components/signin/core/browser/account_consistency_method.h)6
-rw-r--r--chromium/components/signin/public/base/avatar_icon_util.cc (renamed from chromium/components/signin/core/browser/avatar_icon_util.cc)2
-rw-r--r--chromium/components/signin/public/base/avatar_icon_util.h (renamed from chromium/components/signin/core/browser/avatar_icon_util.h)6
-rw-r--r--chromium/components/signin/public/base/avatar_icon_util_unittest.cc (renamed from chromium/components/signin/core/browser/avatar_icon_util_unittest.cc)2
-rw-r--r--chromium/components/signin/public/base/device_id_helper.cc (renamed from chromium/components/signin/core/browser/device_id_helper.cc)6
-rw-r--r--chromium/components/signin/public/base/device_id_helper.h (renamed from chromium/components/signin/core/browser/device_id_helper.h)6
-rw-r--r--chromium/components/signin/public/base/device_id_helper_unittest.cc (renamed from chromium/components/signin/core/browser/device_id_helper_unittest.cc)12
-rw-r--r--chromium/components/signin/public/base/list_accounts_test_utils.cc (renamed from chromium/components/signin/core/browser/list_accounts_test_utils.cc)15
-rw-r--r--chromium/components/signin/public/base/list_accounts_test_utils.h (renamed from chromium/components/signin/core/browser/list_accounts_test_utils.h)11
-rw-r--r--chromium/components/signin/public/base/signin_client.cc (renamed from chromium/components/signin/core/browser/signin_client.cc)2
-rw-r--r--chromium/components/signin/public/base/signin_client.h (renamed from chromium/components/signin/core/browser/signin_client.h)16
-rw-r--r--chromium/components/signin/public/base/signin_metrics.cc (renamed from chromium/components/signin/core/browser/signin_metrics.cc)31
-rw-r--r--chromium/components/signin/public/base/signin_metrics.h (renamed from chromium/components/signin/core/browser/signin_metrics.h)18
-rw-r--r--chromium/components/signin/public/base/signin_metrics_unittest.cc (renamed from chromium/components/signin/core/browser/signin_metrics_unittest.cc)6
-rw-r--r--chromium/components/signin/public/base/signin_pref_names.cc (renamed from chromium/components/signin/core/browser/signin_pref_names.cc)6
-rw-r--r--chromium/components/signin/public/base/signin_pref_names.h (renamed from chromium/components/signin/core/browser/signin_pref_names.h)7
-rw-r--r--chromium/components/signin/public/base/signin_switches.cc (renamed from chromium/components/signin/core/browser/signin_switches.cc)2
-rw-r--r--chromium/components/signin/public/base/signin_switches.h (renamed from chromium/components/signin/core/browser/signin_switches.h)8
-rw-r--r--chromium/components/signin/public/base/test_signin_client.cc (renamed from chromium/components/signin/core/browser/test_signin_client.cc)20
-rw-r--r--chromium/components/signin/public/base/test_signin_client.h (renamed from chromium/components/signin/core/browser/test_signin_client.h)13
-rw-r--r--chromium/components/signin/public/identity_manager/BUILD.gn133
-rw-r--r--chromium/components/signin/public/identity_manager/DEPS3
-rw-r--r--chromium/components/signin/public/identity_manager/README.md38
-rw-r--r--chromium/components/signin/public/identity_manager/access_token_fetcher.cc190
-rw-r--r--chromium/components/signin/public/identity_manager/access_token_fetcher.h151
-rw-r--r--chromium/components/signin/public/identity_manager/access_token_fetcher_unittest.cc612
-rw-r--r--chromium/components/signin/public/identity_manager/access_token_info.cc15
-rw-r--r--chromium/components/signin/public/identity_manager/access_token_info.h42
-rw-r--r--chromium/components/signin/public/identity_manager/account_info.cc (renamed from chromium/components/signin/core/browser/account_info.cc)9
-rw-r--r--chromium/components/signin/public/identity_manager/account_info.h (renamed from chromium/components/signin/core/browser/account_info.h)10
-rw-r--r--chromium/components/signin/public/identity_manager/account_info_unittest.cc (renamed from chromium/components/signin/core/browser/account_info_unittest.cc)2
-rw-r--r--chromium/components/signin/public/identity_manager/accounts_cookie_mutator.h75
-rw-r--r--chromium/components/signin/public/identity_manager/accounts_cookie_mutator_unittest.cc422
-rw-r--r--chromium/components/signin/public/identity_manager/accounts_in_cookie_jar_info.cc30
-rw-r--r--chromium/components/signin/public/identity_manager/accounts_in_cookie_jar_info.h37
-rw-r--r--chromium/components/signin/public/identity_manager/accounts_mutator.h82
-rw-r--r--chromium/components/signin/public/identity_manager/accounts_mutator_unittest.cc683
-rw-r--r--chromium/components/signin/public/identity_manager/device_accounts_synchronizer.h41
-rw-r--r--chromium/components/signin/public/identity_manager/diagnostics_provider.h39
-rw-r--r--chromium/components/signin/public/identity_manager/diagnostics_provider_unittest.cc80
-rw-r--r--chromium/components/signin/public/identity_manager/identity_manager.cc705
-rw-r--r--chromium/components/signin/public/identity_manager/identity_manager.h703
-rw-r--r--chromium/components/signin/public/identity_manager/identity_manager_builder.cc173
-rw-r--r--chromium/components/signin/public/identity_manager/identity_manager_builder.h92
-rw-r--r--chromium/components/signin/public/identity_manager/identity_manager_unittest.cc2290
-rw-r--r--chromium/components/signin/public/identity_manager/identity_test_environment.cc505
-rw-r--r--chromium/components/signin/public/identity_manager/identity_test_environment.h370
-rw-r--r--chromium/components/signin/public/identity_manager/identity_test_environment_unittest.cc57
-rw-r--r--chromium/components/signin/public/identity_manager/identity_test_utils.cc376
-rw-r--r--chromium/components/signin/public/identity_manager/identity_test_utils.h187
-rw-r--r--chromium/components/signin/public/identity_manager/identity_utils.cc (renamed from chromium/components/signin/core/browser/identity_utils.cc)25
-rw-r--r--chromium/components/signin/public/identity_manager/identity_utils.h28
-rw-r--r--chromium/components/signin/public/identity_manager/identity_utils_unittest.cc97
-rw-r--r--chromium/components/signin/public/identity_manager/ios/BUILD.gn32
-rw-r--r--chromium/components/signin/public/identity_manager/ios/device_accounts_provider.h (renamed from chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h)23
-rw-r--r--chromium/components/signin/public/identity_manager/ios/device_accounts_provider.mm26
-rw-r--r--chromium/components/signin/public/identity_manager/ios/fake_device_accounts_provider.h (renamed from chromium/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.h)27
-rw-r--r--chromium/components/signin/public/identity_manager/ios/fake_device_accounts_provider.mm73
-rw-r--r--chromium/components/signin/public/identity_manager/load_credentials_state.h25
-rw-r--r--chromium/components/signin/public/identity_manager/objc/BUILD.gn15
-rw-r--r--chromium/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h75
-rw-r--r--chromium/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.mm77
-rw-r--r--chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.cc125
-rw-r--r--chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.h105
-rw-r--r--chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher_unittest.cc401
-rw-r--r--chromium/components/signin/public/identity_manager/primary_account_mutator.h87
-rw-r--r--chromium/components/signin/public/identity_manager/primary_account_mutator_unittest.cc499
-rw-r--r--chromium/components/signin/public/identity_manager/set_accounts_in_cookie_result.h (renamed from chromium/components/signin/core/browser/set_accounts_in_cookie_result.h)6
-rw-r--r--chromium/components/signin/public/identity_manager/test_identity_manager_observer.cc229
-rw-r--r--chromium/components/signin/public/identity_manager/test_identity_manager_observer.h135
-rw-r--r--chromium/components/signin/public/identity_manager/ubertoken_fetcher.cc (renamed from chromium/components/signin/core/browser/ubertoken_fetcher.cc)2
-rw-r--r--chromium/components/signin/public/identity_manager/ubertoken_fetcher.h (renamed from chromium/components/signin/core/browser/ubertoken_fetcher.h)6
-rw-r--r--chromium/components/signin/public/webdata/BUILD.gn38
-rw-r--r--chromium/components/signin/public/webdata/token_service_table.cc (renamed from chromium/components/signin/core/browser/webdata/token_service_table.cc)20
-rw-r--r--chromium/components/signin/public/webdata/token_service_table.h (renamed from chromium/components/signin/core/browser/webdata/token_service_table.h)9
-rw-r--r--chromium/components/signin/public/webdata/token_service_table_unittest.cc (renamed from chromium/components/signin/core/browser/webdata/token_service_table_unittest.cc)2
-rw-r--r--chromium/components/signin/public/webdata/token_web_data.cc (renamed from chromium/components/signin/core/browser/webdata/token_web_data.cc)42
-rw-r--r--chromium/components/signin/public/webdata/token_web_data.h (renamed from chromium/components/signin/core/browser/webdata/token_web_data.h)11
219 files changed, 17184 insertions, 4442 deletions
diff --git a/chromium/components/signin/DEPS b/chromium/components/signin/DEPS
index 63cf12deb31..8001065552e 100644
--- a/chromium/components/signin/DEPS
+++ b/chromium/components/signin/DEPS
@@ -1,20 +1,25 @@
include_rules = [
+ "+chromeos/components/account_manager",
"+components/content_settings",
"+components/google/core",
+ "+components/image_fetcher/core",
"+components/keyed_service/core",
"+components/os_crypt",
"+components/prefs",
"+components/sync_preferences",
+ # Subdirectories of //components/signin must explicitly allow deps on each
+ # other based on the conceptual deps structure.
+ "-components/signin",
+ "+components/signin/public",
+ "+components/user_manager",
"+components/webdata/common",
"+crypto",
"+google_apis/gaia",
"+grit", # For generated headers
"+net",
+ "+services/identity/public",
+ "+services/network/public",
+ "+services/network/test",
"+sql",
+ "+ui/gfx",
]
-
-specific_include_rules = {
- "test_signin_client\.h": [
- "+services/network/test"
- ]
-}
diff --git a/chromium/components/signin/OWNERS b/chromium/components/signin/OWNERS
index 184a152c6fd..e4b8e297b87 100644
--- a/chromium/components/signin/OWNERS
+++ b/chromium/components/signin/OWNERS
@@ -1,6 +1,7 @@
bsazonov@chromium.org
droger@chromium.org
msarda@chromium.org
+sdefresne@chromium.org
# TEAM: chrome-signin@chromium.org
# COMPONENT: Services>SignIn
diff --git a/chromium/components/signin/core/browser/BUILD.gn b/chromium/components/signin/core/browser/BUILD.gn
index d2700ec7b52..4221020aca2 100644
--- a/chromium/components/signin/core/browser/BUILD.gn
+++ b/chromium/components/signin/core/browser/BUILD.gn
@@ -2,136 +2,13 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//build/buildflag_header.gni")
import("//components/signin/features.gni")
if (is_android) {
import("//build/config/android/rules.gni")
}
-buildflag_header("signin_buildflags") {
- header = "signin_buildflags.h"
- flags = [
- "ENABLE_DICE_SUPPORT=$enable_dice_support",
- "ENABLE_MIRROR=$enable_mirror",
- ]
-}
-
-# This target contains code that will be shared between the Identity Service
-# implementation and its client library/clients. Currently, this code is used
-# both by IdentityManager and by its clients.
-static_library("shared") {
- sources = [
- "account_consistency_method.cc",
- "account_consistency_method.h",
- "account_info.cc",
- "account_info.h",
- "account_info_util.cc",
- "account_info_util.h",
- "avatar_icon_util.cc",
- "avatar_icon_util.h",
- "identity_utils.cc",
- "identity_utils.h",
- "set_accounts_in_cookie_result.h",
- "signin_metrics.cc",
- "signin_metrics.h",
- "signin_pref_names.cc",
- "signin_pref_names.h",
- "signin_switches.cc",
- "signin_switches.h",
- "ubertoken_fetcher.cc",
- "ubertoken_fetcher.h",
- ]
- deps = [
- ":signin_buildflags",
- "//components/account_id",
- "//components/prefs:prefs",
- "//third_party/icu:icui18n",
- "//third_party/re2",
- "//ui/gfx",
- "//url",
- ]
- public_deps = [
- "//base",
-
- # TODO(blundell): Analyze this dependency.
- "//google_apis",
- ]
-}
-
-# This target contains what will become the core of the Identity Service
-# implementation. It currently forms the core of the IdentityManager
-# implementation (//services/identity/public/cpp/identity_manager.*). We are
-# actively converting the codebase away from using the code in this target
-# directly to using IdentityManager (tracked in https://crbug.com/796544). Do
-# not add code to this target without consulting with blundell@chromium.org.
-static_library("internals") {
- sources = [
- "account_fetcher_service.cc",
- "account_fetcher_service.h",
- "account_info_fetcher.cc",
- "account_info_fetcher.h",
- "account_tracker_service.cc",
- "account_tracker_service.h",
- "child_account_info_fetcher_android.cc",
- "child_account_info_fetcher_android.h",
- "device_id_helper.cc",
- "device_id_helper.h",
- "gaia_cookie_manager_service.cc",
- "gaia_cookie_manager_service.h",
- "oauth2_token_service_delegate_android.cc",
- "oauth2_token_service_delegate_android.h",
- "oauth_multilogin_helper.cc",
- "oauth_multilogin_helper.h",
- "oauth_multilogin_token_fetcher.cc",
- "oauth_multilogin_token_fetcher.h",
- "profile_oauth2_token_service.cc",
- "profile_oauth2_token_service.h",
- "profile_oauth2_token_service_delegate_chromeos.cc",
- "profile_oauth2_token_service_delegate_chromeos.h",
- "signin_client.cc",
- "signin_client.h",
- "signin_manager.cc",
- "signin_manager.h",
- "signin_manager_base.cc",
- "signin_manager_base.h",
- "ubertoken_fetcher_impl.cc",
- "ubertoken_fetcher_impl.h",
- ]
-
- if (is_chromeos) {
- sources -= [ "signin_manager.cc" ]
- }
-
- deps = [
- ":shared",
- ":signin_buildflags",
- "//base",
- "//components/image_fetcher/core",
- "//components/keyed_service/core",
- "//components/prefs",
- "//google_apis",
- "//net",
- "//services/network/public/cpp",
- "//services/network/public/mojom",
- "//ui/gfx",
- ]
-
- if (is_android) {
- deps += [ "android:jni_headers" ]
- }
-
- if (is_chromeos) {
- deps += [
- "//chromeos/components/account_manager",
-
- # TODO(crbug.com/816954): Remove this line when Account Manager is
- # launched.
- "//chromeos/constants",
- ]
- }
-}
-
+# This target contains code that is used by clients of //components/signin.
static_library("browser") {
sources = [
"about_signin_internals.cc",
@@ -152,14 +29,12 @@ static_library("browser") {
"dice_account_reconcilor_delegate.h",
"dice_header_helper.cc",
"dice_header_helper.h",
- "identity_manager_wrapper.cc",
- "identity_manager_wrapper.h",
"mice_account_reconcilor_delegate.cc",
"mice_account_reconcilor_delegate.h",
"mirror_account_reconcilor_delegate.cc",
"mirror_account_reconcilor_delegate.h",
- "mutable_profile_oauth2_token_service_delegate.cc",
- "mutable_profile_oauth2_token_service_delegate.h",
+ "multilogin_parameters.cc",
+ "multilogin_parameters.h",
"signin_error_controller.cc",
"signin_error_controller.h",
"signin_header_helper.cc",
@@ -174,24 +49,18 @@ static_library("browser") {
"signin_status_metrics_provider_base.h",
"signin_status_metrics_provider_delegate.cc",
"signin_status_metrics_provider_delegate.h",
- "webdata/token_service_table.cc",
- "webdata/token_service_table.h",
- "webdata/token_web_data.cc",
- "webdata/token_web_data.h",
]
configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
public_deps = [
- ":internals",
- ":shared",
- ":signin_buildflags",
"//base",
- "//components/account_id",
"//components/content_settings/core/browser",
"//components/content_settings/core/common",
"//components/keyed_service/core",
"//components/prefs",
+ "//components/signin/public/base",
+ "//components/signin/public/base:signin_buildflags",
"//google_apis",
"//net",
"//services/network/public/cpp",
@@ -203,9 +72,9 @@ static_library("browser") {
"//components/google/core/browser",
"//components/metrics",
"//components/os_crypt",
+ "//components/signin/public/identity_manager",
"//components/webdata/common",
"//crypto",
- "//services/identity/public/cpp",
"//services/network/public/cpp",
"//skia",
"//sql",
@@ -237,104 +106,51 @@ static_library("browser") {
}
}
-# This target contains test support that backs the test support for
-# IdentityManager (and eventually likely for the Identity Service). We are
-# actively converting the codebase away from using the code in this target
-# directly to using IdentityManager (tracked in https://crbug.com/796544). Do
-# not add code to this target without consulting with blundell@chromium.org.
-static_library("internals_test_support") {
- testonly = true
- sources = [
- "fake_profile_oauth2_token_service.cc",
- "fake_profile_oauth2_token_service.h",
-
- # TODO(https://crbug.com/907782): Move list_accounts_test_utils to
- # //services/identity/public/cpp once FakeGCMS no longer depends on it.
- "list_accounts_test_utils.cc",
- "list_accounts_test_utils.h",
- "test_signin_client.cc",
- "test_signin_client.h",
- ]
-
- deps = [
- "//base/test:test_support",
- "//components/prefs",
- "//google_apis:test_support",
- ]
-
- public_deps = [
- ":internals",
- ":shared",
- "//base",
- "//services/network:test_support",
- ]
-}
-
source_set("unit_tests") {
testonly = true
sources = [
- "account_info_unittest.cc",
- "account_info_util_unittest.cc",
"account_investigator_unittest.cc",
"account_reconcilor_delegate_unittest.cc",
"account_reconcilor_unittest.cc",
- "account_tracker_service_unittest.cc",
- "avatar_icon_util_unittest.cc",
- "device_id_helper_unittest.cc",
"dice_account_reconcilor_delegate_unittest.cc",
- "gaia_cookie_manager_service_unittest.cc",
"mice_account_reconcilor_delegate_unittest.cc",
- "mutable_profile_oauth2_token_service_delegate_unittest.cc",
- "oauth_multilogin_helper_unittest.cc",
- "oauth_multilogin_token_fetcher_unittest.cc",
- "profile_oauth2_token_service_delegate_chromeos_unittest.cc",
"signin_error_controller_unittest.cc",
"signin_header_helper_unittest.cc",
"signin_investigator_unittest.cc",
- "signin_manager_unittest.cc",
- "signin_metrics_unittest.cc",
"signin_status_metrics_provider_unittest.cc",
- "ubertoken_fetcher_impl_unittest.cc",
- "webdata/token_service_table_unittest.cc",
]
deps = [
":browser",
- ":internals_test_support",
- ":signin_buildflags",
+ "//base",
"//base/test:test_support",
"//components/content_settings/core/browser",
- "//components/image_fetcher/core",
- "//components/image_fetcher/core:test_support",
- "//components/os_crypt:test_support",
"//components/prefs",
"//components/prefs:test_support",
- "//components/sync_preferences",
+ "//components/signin/public/base",
+ "//components/signin/public/base:signin_buildflags",
+ "//components/signin/public/base:test_support",
+ "//components/signin/public/identity_manager",
+ "//components/signin/public/identity_manager:test_support",
"//components/sync_preferences:test_support",
- "//components/webdata/common",
- "//google_apis:test_support",
+ "//google_apis",
"//net:test_support",
- "//services/identity/public/cpp:test_support",
+ "//net/traffic_annotation:test_support",
+ "//services/network:test_support",
"//testing/gmock",
"//testing/gtest",
- "//ui/gfx:test_support",
+ "//url",
]
if (is_chromeos) {
sources -= [
"account_investigator_unittest.cc",
- "signin_manager_unittest.cc",
"signin_status_metrics_provider_unittest.cc",
]
-
- deps += [ "//chromeos/components/account_manager" ]
}
if (is_android) {
- sources += [
- "consistency_cookie_manager_unittest.cc",
- "oauth2_token_service_delegate_android_unittest.cc",
- ]
+ sources += [ "consistency_cookie_manager_unittest.cc" ]
}
if (!enable_dice_support) {
diff --git a/chromium/components/signin/core/browser/DEPS b/chromium/components/signin/core/browser/DEPS
index 6aa48343a03..d9ef433896d 100644
--- a/chromium/components/signin/core/browser/DEPS
+++ b/chromium/components/signin/core/browser/DEPS
@@ -1,16 +1,3 @@
include_rules = [
- "+chromeos/components/account_manager",
- # TODO(crbug.com/816954): Remove this line when Account Manager is
- # launched.
- "+chromeos/constants",
- "+components/account_id",
- "+components/image_fetcher/core",
"+components/metrics",
- "+jni",
- "+mojo/public",
- "+services/identity/public",
- "+services/network/public",
- "+services/network/test",
- "+third_party/re2",
- "+ui/gfx",
]
diff --git a/chromium/components/signin/core/browser/about_signin_internals.cc b/chromium/components/signin/core/browser/about_signin_internals.cc
index b3e4d988d4c..3032fad8753 100644
--- a/chromium/components/signin/core/browser/about_signin_internals.cc
+++ b/chromium/components/signin/core/browser/about_signin_internals.cc
@@ -11,21 +11,20 @@
#include "base/command_line.h"
#include "base/hash/hash.h"
-#include "base/i18n/time_formatting.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
+#include "base/time/time_to_iso8601.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/signin_client.h"
-#include "components/signin/core/browser/signin_switches.h"
-#include "google_apis/gaia/oauth2_token_service_delegate.h"
+#include "components/signin/public/base/signin_client.h"
+#include "components/signin/public/base/signin_switches.h"
+#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
+#include "components/signin/public/identity_manager/diagnostics_provider.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/load_credentials_state.h"
#include "net/base/backoff_entry.h"
-#include "services/identity/public/cpp/accounts_in_cookie_jar_info.h"
-#include "services/identity/public/cpp/diagnostics_provider.h"
-#include "services/identity/public/cpp/identity_manager.h"
namespace {
@@ -62,10 +61,6 @@ std::string GetGaiaCookiesStateAsString(const GaiaCookiesState state) {
}
}
-std::string GetTimeStr(base::Time time) {
- return base::UTF16ToUTF8(base::TimeFormatShortDateAndTime(time));
-}
-
base::ListValue* AddSection(base::ListValue* parent_list,
const std::string& title) {
auto section = std::make_unique<base::DictionaryValue>();
@@ -117,24 +112,27 @@ std::string SigninStatusFieldToLabel(
}
std::string TokenServiceLoadCredentialsStateToLabel(
- OAuth2TokenServiceDelegate::LoadCredentialsState state) {
+ signin::LoadCredentialsState state) {
switch (state) {
- case OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_NOT_STARTED:
+ case signin::LoadCredentialsState::LOAD_CREDENTIALS_NOT_STARTED:
return "Load credentials not started";
- case OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_IN_PROGRESS:
+ case signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS:
return "Load credentials in progress";
- case OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS:
+ case signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS:
return "Load credentials finished with success";
- case OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_FINISHED_WITH_DB_ERRORS:
+ case signin::LoadCredentialsState::
+ LOAD_CREDENTIALS_FINISHED_WITH_DB_CANNOT_BE_OPENED:
+ return "Load credentials failed with datase cannot be opened error";
+ case signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_DB_ERRORS:
return "Load credentials failed with database errors";
- case OAuth2TokenServiceDelegate::
+ case signin::LoadCredentialsState::
LOAD_CREDENTIALS_FINISHED_WITH_DECRYPT_ERRORS:
return "Load credentials failed with decrypt errors";
- case OAuth2TokenServiceDelegate::
+ case signin::LoadCredentialsState::
LOAD_CREDENTIALS_FINISHED_WITH_NO_TOKEN_FOR_PRIMARY_ACCOUNT:
return "Load credentials failed with no refresh token for signed in "
"account";
- case OAuth2TokenServiceDelegate::
+ case signin::LoadCredentialsState::
LOAD_CREDENTIALS_FINISHED_WITH_UNKNOWN_ERRORS:
return "Load credentials failed with unknown errors";
}
@@ -159,10 +157,12 @@ std::string SigninStatusFieldToLabel(
}
#endif // !defined (OS_CHROMEOS)
+// It's quite unfortunate that |time| is saved in prefs as a string instead of
+// base::Time because any change of the format would create inconsistency.
void SetPref(PrefService* prefs,
signin_internals_util::TimedSigninStatusField field,
- const std::string& time,
- const std::string& value) {
+ const std::string& value,
+ const std::string& time) {
std::string value_pref = SigninStatusFieldToString(field) + ".value";
std::string time_pref = SigninStatusFieldToString(field) + ".time";
prefs->SetString(value_pref, value);
@@ -171,8 +171,8 @@ void SetPref(PrefService* prefs,
void GetPref(PrefService* prefs,
signin_internals_util::TimedSigninStatusField field,
- std::string* time,
- std::string* value) {
+ std::string* value,
+ std::string* time) {
std::string value_pref = SigninStatusFieldToString(field) + ".value";
std::string time_pref = SigninStatusFieldToString(field) + ".time";
*value = prefs->GetString(value_pref);
@@ -206,7 +206,7 @@ std::string GetAccountConsistencyDescription(
} // anonymous namespace
AboutSigninInternals::AboutSigninInternals(
- identity::IdentityManager* identity_manager,
+ signin::IdentityManager* identity_manager,
SigninErrorController* signin_error_controller,
signin::AccountConsistencyMethod account_consistency)
: identity_manager_(identity_manager),
@@ -231,8 +231,6 @@ signin_internals_util::TimedSigninStatusField& operator++(
// static
void AboutSigninInternals::RegisterPrefs(PrefRegistrySimple* user_prefs) {
- // SigninManager information for about:signin-internals.
-
// TODO(rogerta): leaving untimed fields here for now because legacy
// profiles still have these prefs. In three or four version from M43
// we can probably remove them.
@@ -271,8 +269,7 @@ void AboutSigninInternals::NotifyTimedSigninFieldValueChanged(
field_index < signin_status_.timed_signin_fields.size());
base::Time now = base::Time::NowFromSystemTime();
- std::string time_as_str =
- base::UTF16ToUTF8(base::TimeFormatShortDateAndTime(now));
+ std::string time_as_str = base::TimeToISO8601(now);
TimedSigninStatusValue timed_value(value, time_as_str);
signin_status_.timed_signin_fields[field_index] = timed_value;
@@ -301,7 +298,7 @@ void AboutSigninInternals::RefreshSigninPrefs() {
i < signin_internals_util::TIMED_FIELDS_END; ++i) {
std::string time_str;
std::string value_str;
- GetPref(pref_service, i, &time_str, &value_str);
+ GetPref(pref_service, i, &value_str, &time_str);
TimedSigninStatusValue value(value_str, time_str);
signin_status_
.timed_signin_fields[i - signin_internals_util::TIMED_FIELDS_BEGIN] =
@@ -362,7 +359,7 @@ std::unique_ptr<base::DictionaryValue> AboutSigninInternals::GetSigninStatus() {
}
void AboutSigninInternals::OnAccessTokenRequested(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& consumer_id,
const identity::ScopeSet& scopes) {
TokenInfo* token = signin_status_.FindToken(account_id, consumer_id, scopes);
@@ -377,7 +374,7 @@ void AboutSigninInternals::OnAccessTokenRequested(
}
void AboutSigninInternals::OnAccessTokenRequestCompleted(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& consumer_id,
const identity::ScopeSet& scopes,
GoogleServiceAuthError error,
@@ -396,7 +393,7 @@ void AboutSigninInternals::OnAccessTokenRequestCompleted(
}
void AboutSigninInternals::OnRefreshTokenUpdatedForAccountFromSource(
- const std::string& account_id,
+ const CoreAccountId& account_id,
bool is_refresh_token_valid,
const std::string& source) {
RefreshTokenEvent event;
@@ -410,7 +407,7 @@ void AboutSigninInternals::OnRefreshTokenUpdatedForAccountFromSource(
}
void AboutSigninInternals::OnRefreshTokenRemovedForAccountFromSource(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& source) {
RefreshTokenEvent event;
event.account_id = account_id;
@@ -421,7 +418,7 @@ void AboutSigninInternals::OnRefreshTokenRemovedForAccountFromSource(
void AboutSigninInternals::OnRefreshTokensLoaded() {
RefreshTokenEvent event;
- event.account_id = "All accounts";
+ // event.account_id = CoreAccountId("All accounts");
event.type = AboutSigninInternals::RefreshTokenEventType::kAllTokensLoaded;
signin_status_.AddRefreshTokenEvent(event);
NotifyObservers();
@@ -432,7 +429,7 @@ void AboutSigninInternals::OnEndBatchOfRefreshTokenStateChanges() {
}
void AboutSigninInternals::OnAccessTokenRemovedFromCache(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const identity::ScopeSet& scopes) {
for (const std::unique_ptr<TokenInfo>& token :
signin_status_.token_info_map[account_id]) {
@@ -468,7 +465,7 @@ void AboutSigninInternals::OnPrimaryAccountCleared(
}
void AboutSigninInternals::OnAccountsInCookieUpdated(
- const identity::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+ const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
const GoogleServiceAuthError& error) {
if (error.state() != GoogleServiceAuthError::NONE)
return;
@@ -524,14 +521,14 @@ AboutSigninInternals::TokenInfo::ToValue() const {
scopes_str += *it + "<br/>";
}
token_info->SetString("scopes", scopes_str);
- token_info->SetString("request_time", GetTimeStr(request_time));
+ token_info->SetString("request_time", base::TimeToISO8601(request_time));
if (removed_) {
token_info->SetString("status", "Token was revoked.");
} else if (!receive_time.is_null()) {
if (error == GoogleServiceAuthError::AuthErrorNone()) {
bool token_expired = expiration_time < base::Time::Now();
- std::string expiration_time_string = GetTimeStr(expiration_time);
+ std::string expiration_time_string = base::TimeToISO8601(expiration_time);
if (expiration_time.is_null()) {
token_expired = false;
expiration_time_string = "Expiration time not available";
@@ -540,7 +537,7 @@ AboutSigninInternals::TokenInfo::ToValue() const {
if (token_expired)
status_str = "<p style=\"color: #ffffff; background-color: #ff0000\">";
base::StringAppendF(&status_str, "Received token at %s. Expire at %s",
- GetTimeStr(receive_time).c_str(),
+ base::TimeToISO8601(receive_time).c_str(),
expiration_time_string.c_str());
if (token_expired)
base::StringAppendF(&status_str, "</p>");
@@ -579,7 +576,7 @@ AboutSigninInternals::SigninStatus::SigninStatus()
AboutSigninInternals::SigninStatus::~SigninStatus() {}
AboutSigninInternals::TokenInfo* AboutSigninInternals::SigninStatus::FindToken(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& consumer_id,
const identity::ScopeSet& scopes) {
for (const std::unique_ptr<TokenInfo>& token : token_info_map[account_id]) {
@@ -599,7 +596,7 @@ void AboutSigninInternals::SigninStatus::AddRefreshTokenEvent(
std::unique_ptr<base::DictionaryValue>
AboutSigninInternals::SigninStatus::ToValue(
- identity::IdentityManager* identity_manager,
+ signin::IdentityManager* identity_manager,
SigninErrorController* signin_error_controller,
SigninClient* signin_client,
signin::AccountConsistencyMethod account_consistency) {
@@ -616,7 +613,7 @@ AboutSigninInternals::SigninStatus::ToValue(
AddSectionEntry(
basic_info, "Signin Status",
identity_manager->HasPrimaryAccount() ? "Signed In" : "Not Signed In");
- OAuth2TokenServiceDelegate::LoadCredentialsState load_tokens_state =
+ signin::LoadCredentialsState load_tokens_state =
identity_manager->GetDiagnosticsProvider()
->GetDetailedStateOfLoadingOfRefreshTokens();
AddSectionEntry(basic_info, "TokenService Load Status",
@@ -629,7 +626,7 @@ AboutSigninInternals::SigninStatus::ToValue(
CoreAccountInfo account_info = identity_manager->GetPrimaryAccountInfo();
AddSectionEntry(basic_info,
SigninStatusFieldToLabel(signin_internals_util::ACCOUNT_ID),
- account_info.account_id);
+ account_info.account_id.id);
AddSectionEntry(basic_info,
SigninStatusFieldToLabel(signin_internals_util::GAIA_ID),
account_info.gaia);
@@ -637,7 +634,7 @@ AboutSigninInternals::SigninStatus::ToValue(
SigninStatusFieldToLabel(signin_internals_util::USERNAME),
account_info.email);
if (signin_error_controller->HasError()) {
- const std::string error_account_id =
+ const CoreAccountId error_account_id =
signin_error_controller->error_account_id();
const base::Optional<AccountInfo> error_account_info =
identity_manager
@@ -645,7 +642,7 @@ AboutSigninInternals::SigninStatus::ToValue(
error_account_id);
AddSectionEntry(basic_info, "Auth Error",
signin_error_controller->auth_error().ToString());
- AddSectionEntry(basic_info, "Auth Error Account Id", error_account_id);
+ AddSectionEntry(basic_info, "Auth Error Account Id", error_account_id.id);
// The error_account_info optional should never be unset when we reach
// this line (as we should have a refresh token, even if in an error
@@ -684,15 +681,8 @@ AboutSigninInternals::SigninStatus::ToValue(
if (cookie_requests_delay > base::TimeDelta()) {
base::Time next_retry_time =
base::Time::NowFromSystemTime() + cookie_requests_delay;
-
- std::string next_retry_time_as_str =
- base::UTF16ToUTF8(
- base::TimeFormatShortDateAndTime(next_retry_time));
-
- AddSectionEntry(detailed_info,
- "Cookie Manager Next Retry",
- next_retry_time_as_str,
- "");
+ AddSectionEntry(detailed_info, "Cookie Manager Next Retry",
+ base::TimeToISO8601(next_retry_time), "");
}
base::TimeDelta token_requests_delay =
@@ -702,15 +692,8 @@ AboutSigninInternals::SigninStatus::ToValue(
if (token_requests_delay > base::TimeDelta()) {
base::Time next_retry_time =
base::Time::NowFromSystemTime() + token_requests_delay;
-
- std::string next_retry_time_as_str =
- base::UTF16ToUTF8(
- base::TimeFormatShortDateAndTime(next_retry_time));
-
- AddSectionEntry(detailed_info,
- "Token Service Next Retry",
- next_retry_time_as_str,
- "");
+ AddSectionEntry(detailed_info, "Token Service Next Retry",
+ base::TimeToISO8601(next_retry_time), "");
}
#endif // !defined(OS_CHROMEOS)
@@ -718,7 +701,7 @@ AboutSigninInternals::SigninStatus::ToValue(
// Token information for all services.
auto token_info = std::make_unique<base::ListValue>();
for (auto it = token_info_map.begin(); it != token_info_map.end(); ++it) {
- base::ListValue* token_details = AddSection(token_info.get(), it->first);
+ base::ListValue* token_details = AddSection(token_info.get(), it->first.id);
std::sort(it->second.begin(), it->second.end(), TokenInfo::LessThan);
for (const std::unique_ptr<TokenInfo>& token : it->second)
token_details->Append(token->ToValue());
@@ -755,8 +738,8 @@ AboutSigninInternals::SigninStatus::ToValue(
auto refresh_token_events_value = std::make_unique<base::ListValue>();
for (const auto& event : refresh_token_events) {
auto entry = std::make_unique<base::DictionaryValue>();
- entry->SetString("accountId", event.account_id);
- entry->SetString("timestamp", GetTimeStr(event.timestamp));
+ entry->SetString("accountId", event.account_id.id);
+ entry->SetString("timestamp", base::TimeToISO8601(event.timestamp));
entry->SetString("type", event.GetTypeAsString());
entry->SetString("source", event.source);
refresh_token_events_value->Append(std::move(entry));
diff --git a/chromium/components/signin/core/browser/about_signin_internals.h b/chromium/components/signin/core/browser/about_signin_internals.h
index ccfd208c6f8..9b34c7d9895 100644
--- a/chromium/components/signin/core/browser/about_signin_internals.h
+++ b/chromium/components/signin/core/browser/about_signin_internals.h
@@ -17,13 +17,13 @@
#include "base/values.h"
#include "components/content_settings/core/browser/content_settings_observer.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "components/signin/core/browser/signin_client.h"
#include "components/signin/core/browser/signin_error_controller.h"
#include "components/signin/core/browser/signin_internals_util.h"
-#include "services/identity/public/cpp/identity_manager.h"
+#include "components/signin/public/base/signin_client.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
#include "services/identity/public/cpp/scope_set.h"
-namespace identity {
+namespace signin {
struct AccountsInCookieJarInfo;
}
@@ -39,8 +39,8 @@ using TimedSigninStatusValue = std::pair<std::string, std::string>;
class AboutSigninInternals : public KeyedService,
public content_settings::Observer,
SigninErrorController::Observer,
- identity::IdentityManager::Observer,
- identity::IdentityManager::DiagnosticsObserver {
+ signin::IdentityManager::Observer,
+ signin::IdentityManager::DiagnosticsObserver {
public:
class Observer {
public:
@@ -52,7 +52,7 @@ class AboutSigninInternals : public KeyedService,
virtual void OnCookieAccountsFetched(const base::DictionaryValue* info) = 0;
};
- AboutSigninInternals(identity::IdentityManager* identity_manager,
+ AboutSigninInternals(signin::IdentityManager* identity_manager,
SigninErrorController* signin_error_controller,
signin::AccountConsistencyMethod account_consistency);
~AboutSigninInternals() override;
@@ -92,9 +92,9 @@ class AboutSigninInternals : public KeyedService,
// }
std::unique_ptr<base::DictionaryValue> GetSigninStatus();
- // identity::IdentityManager::Observer implementations.
+ // signin::IdentityManager::Observer implementations.
void OnAccountsInCookieUpdated(
- const identity::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+ const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
const GoogleServiceAuthError& error) override;
private:
@@ -131,7 +131,7 @@ class AboutSigninInternals : public KeyedService,
std::string GetTypeAsString() const;
const base::Time timestamp;
- std::string account_id;
+ CoreAccountId account_id;
RefreshTokenEventType type;
std::string source;
};
@@ -143,7 +143,7 @@ class AboutSigninInternals : public KeyedService,
std::vector<TimedSigninStatusValue> timed_signin_fields;
// Map account id to tokens associated to the account.
- std::map<std::string, std::vector<std::unique_ptr<TokenInfo>>>
+ std::map<CoreAccountId, std::vector<std::unique_ptr<TokenInfo>>>
token_info_map;
// All the events that affected the refresh tokens.
@@ -152,7 +152,7 @@ class AboutSigninInternals : public KeyedService,
SigninStatus();
~SigninStatus();
- TokenInfo* FindToken(const std::string& account_id,
+ TokenInfo* FindToken(const CoreAccountId& account_id,
const std::string& consumer_id,
const identity::ScopeSet& scopes);
@@ -176,29 +176,29 @@ class AboutSigninInternals : public KeyedService,
// }],
// }
std::unique_ptr<base::DictionaryValue> ToValue(
- identity::IdentityManager* identity_manager,
+ signin::IdentityManager* identity_manager,
SigninErrorController* signin_error_controller,
SigninClient* signin_client,
signin::AccountConsistencyMethod account_consistency);
};
// IdentityManager::DiagnosticsObserver implementations.
- void OnAccessTokenRequested(const std::string& account_id,
+ void OnAccessTokenRequested(const CoreAccountId& account_id,
const std::string& consumer_id,
const identity::ScopeSet& scopes) override;
- void OnAccessTokenRequestCompleted(const std::string& account_id,
+ void OnAccessTokenRequestCompleted(const CoreAccountId& account_id,
const std::string& consumer_id,
const identity::ScopeSet& scopes,
GoogleServiceAuthError error,
base::Time expiration_time) override;
- void OnAccessTokenRemovedFromCache(const std::string& account_id,
+ void OnAccessTokenRemovedFromCache(const CoreAccountId& account_id,
const identity::ScopeSet& scopes) override;
void OnRefreshTokenUpdatedForAccountFromSource(
- const std::string& account_id,
+ const CoreAccountId& account_id,
bool is_refresh_token_valid,
const std::string& source) override;
void OnRefreshTokenRemovedForAccountFromSource(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& source) override;
// IdentityManager::Observer implementations.
@@ -225,7 +225,7 @@ class AboutSigninInternals : public KeyedService,
const std::string& resource_identifier) override;
// Weak pointer to the identity manager.
- identity::IdentityManager* identity_manager_;
+ signin::IdentityManager* identity_manager_;
// Weak pointer to the client.
SigninClient* client_;
diff --git a/chromium/components/signin/core/browser/account_investigator.cc b/chromium/components/signin/core/browser/account_investigator.cc
index eaa7f06d29a..ba15883762a 100644
--- a/chromium/components/signin/core/browser/account_investigator.cc
+++ b/chromium/components/signin/core/browser/account_investigator.cc
@@ -13,11 +13,11 @@
#include "base/time/time.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/signin_metrics.h"
-#include "components/signin/core/browser/signin_pref_names.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/google_service_auth_error.h"
-#include "services/identity/public/cpp/accounts_in_cookie_jar_info.h"
using base::Time;
using base::TimeDelta;
@@ -43,7 +43,7 @@ const TimeDelta AccountInvestigator::kPeriodicReportingInterval =
AccountInvestigator::AccountInvestigator(
PrefService* pref_service,
- identity::IdentityManager* identity_manager)
+ signin::IdentityManager* identity_manager)
: pref_service_(pref_service), identity_manager_(identity_manager) {}
AccountInvestigator::~AccountInvestigator() {}
@@ -74,7 +74,7 @@ void AccountInvestigator::Shutdown() {
}
void AccountInvestigator::OnAccountsInCookieUpdated(
- const identity::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+ const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
const GoogleServiceAuthError& error) {
if (error != GoogleServiceAuthError::AuthErrorNone()) {
// If we are pending periodic reporting, leave the flag set, and we will
@@ -135,12 +135,12 @@ std::string AccountInvestigator::HashAccounts(
std::transform(std::begin(signed_in_accounts), std::end(signed_in_accounts),
std::back_inserter(sorted_ids),
[](const ListedAccount& account) {
- return std::string(kSignedInHashPrefix) + account.id;
+ return std::string(kSignedInHashPrefix) + account.id.id;
});
std::transform(std::begin(signed_out_accounts), std::end(signed_out_accounts),
std::back_inserter(sorted_ids),
[](const ListedAccount& account) {
- return std::string(kSignedOutHashPrefix) + account.id;
+ return std::string(kSignedOutHashPrefix) + account.id.id;
});
std::sort(sorted_ids.begin(), sorted_ids.end());
std::ostringstream stream;
diff --git a/chromium/components/signin/core/browser/account_investigator.h b/chromium/components/signin/core/browser/account_investigator.h
index 0d8acc738fa..0a7b9538bab 100644
--- a/chromium/components/signin/core/browser/account_investigator.h
+++ b/chromium/components/signin/core/browser/account_investigator.h
@@ -11,7 +11,7 @@
#include "base/macros.h"
#include "base/timer/timer.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "services/identity/public/cpp/identity_manager.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
struct CoreAccountInfo;
class PrefRegistrySimple;
@@ -21,9 +21,9 @@ namespace base {
class Time;
} // namespace base
-namespace identity {
+namespace signin {
struct AccountsInCookieJarInfo;
-} // namespace identity
+} // namespace signin
namespace signin_metrics {
enum class AccountRelation;
@@ -35,7 +35,7 @@ enum class ReportingType;
// is to watch for changes in relation between Chrome and content area accounts
// and emit metrics about their relation.
class AccountInvestigator : public KeyedService,
- public identity::IdentityManager::Observer {
+ public signin::IdentityManager::Observer {
public:
// The targeted interval to perform periodic reporting. If chrome is not
// active at the end of an interval, reporting will be done as soon as
@@ -43,7 +43,7 @@ class AccountInvestigator : public KeyedService,
static const base::TimeDelta kPeriodicReportingInterval;
AccountInvestigator(PrefService* pref_service,
- identity::IdentityManager* identity_manager);
+ signin::IdentityManager* identity_manager);
~AccountInvestigator() override;
static void RegisterPrefs(PrefRegistrySimple* registry);
@@ -54,9 +54,9 @@ class AccountInvestigator : public KeyedService,
// KeyedService:
void Shutdown() override;
- // identity::IdentityManager::Observer:
+ // signin::IdentityManager::Observer:
void OnAccountsInCookieUpdated(
- const identity::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+ const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
const GoogleServiceAuthError& error) override;
private:
@@ -109,7 +109,7 @@ class AccountInvestigator : public KeyedService,
signin_metrics::ReportingType type);
PrefService* pref_service_;
- identity::IdentityManager* identity_manager_;
+ signin::IdentityManager* identity_manager_;
// Handles invoking our periodic logic at the right time. As part of our
// handling of this call we reset the timer for the next loop.
diff --git a/chromium/components/signin/core/browser/account_investigator_unittest.cc b/chromium/components/signin/core/browser/account_investigator_unittest.cc
index e6f5b19c144..c752ee46940 100644
--- a/chromium/components/signin/core/browser/account_investigator_unittest.cc
+++ b/chromium/components/signin/core/browser/account_investigator_unittest.cc
@@ -5,20 +5,18 @@
#include "components/signin/core/browser/account_investigator.h"
#include <map>
-#include <string>
-#include <vector>
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_task_environment.h"
-#include "base/timer/timer.h"
#include "components/prefs/pref_registry_simple.h"
-#include "components/signin/core/browser/signin_metrics.h"
-#include "components/signin/core/browser/signin_pref_names.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/google_service_auth_error.h"
-#include "services/identity/public/cpp/identity_test_environment.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -39,7 +37,7 @@ class AccountInvestigatorTest : public testing::Test {
~AccountInvestigatorTest() override { investigator_.Shutdown(); }
- identity::IdentityTestEnvironment* identity_test_env() {
+ signin::IdentityTestEnvironment* identity_test_env() {
return &identity_test_env_;
}
PrefService* pref_service() { return &prefs_; }
@@ -138,7 +136,7 @@ class AccountInvestigatorTest : public testing::Test {
base::test::ScopedTaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable prefs_;
network::TestURLLoaderFactory test_url_loader_factory_;
- identity::IdentityTestEnvironment identity_test_env_;
+ signin::IdentityTestEnvironment identity_test_env_;
AccountInvestigator investigator_;
std::map<ReportingType, std::string> suffix_ = {
{ReportingType::PERIODIC, "_Periodic"},
@@ -164,9 +162,9 @@ AccountInfo ToAccountInfo(ListedAccount account) {
// NOTE: IdentityTestEnvironment uses a prefix for generating gaia IDs:
// "gaia_id_for_". For this reason, the tests prefix expected account IDs
// used so that there is a match.
-const std::string kGaiaId1 = identity::GetTestGaiaIdForEmail("1@mail.com");
-const std::string kGaiaId2 = identity::GetTestGaiaIdForEmail("2@mail.com");
-const std::string kGaiaId3 = identity::GetTestGaiaIdForEmail("3@mail.com");
+const std::string kGaiaId1 = signin::GetTestGaiaIdForEmail("1@mail.com");
+const std::string kGaiaId2 = signin::GetTestGaiaIdForEmail("2@mail.com");
+const std::string kGaiaId3 = signin::GetTestGaiaIdForEmail("3@mail.com");
const ListedAccount one(Account(kGaiaId1));
const ListedAccount two(Account(kGaiaId2));
@@ -263,7 +261,7 @@ TEST_F(AccountInvestigatorTest, SharedCookieJarReportWithAccount) {
TEST_F(AccountInvestigatorTest, OnGaiaAccountsInCookieUpdatedError) {
const HistogramTester histogram_tester;
- identity::AccountsInCookieJarInfo accounts_in_cookie_jar_info = {
+ signin::AccountsInCookieJarInfo accounts_in_cookie_jar_info = {
/*accounts_are_fresh=*/true, just_one, no_accounts};
GoogleServiceAuthError error(GoogleServiceAuthError::SERVICE_UNAVAILABLE);
investigator()->OnAccountsInCookieUpdated(accounts_in_cookie_jar_info, error);
@@ -273,7 +271,7 @@ TEST_F(AccountInvestigatorTest, OnGaiaAccountsInCookieUpdatedError) {
TEST_F(AccountInvestigatorTest, OnGaiaAccountsInCookieUpdatedOnChange) {
const HistogramTester histogram_tester;
- identity::AccountsInCookieJarInfo accounts_in_cookie_jar_info = {
+ signin::AccountsInCookieJarInfo accounts_in_cookie_jar_info = {
/*accounts_are_fresh=*/true, just_one, no_accounts};
investigator()->OnAccountsInCookieUpdated(
accounts_in_cookie_jar_info, GoogleServiceAuthError::AuthErrorNone());
@@ -284,14 +282,14 @@ TEST_F(AccountInvestigatorTest, OnGaiaAccountsInCookieUpdatedOnChange) {
TEST_F(AccountInvestigatorTest, OnGaiaAccountsInCookieUpdatedSigninOnly) {
// Initial update to simulate the update on first-time-run.
investigator()->OnAccountsInCookieUpdated(
- identity::AccountsInCookieJarInfo(),
+ signin::AccountsInCookieJarInfo(),
GoogleServiceAuthError::AuthErrorNone());
const HistogramTester histogram_tester;
identity_test_env()->SetPrimaryAccount("1@mail.com");
pref_service()->SetString(prefs::kGaiaCookieHash,
Hash(just_one, no_accounts));
- identity::AccountsInCookieJarInfo accounts_in_cookie_jar_info = {
+ signin::AccountsInCookieJarInfo accounts_in_cookie_jar_info = {
/*accounts_are_fresh=*/true, just_one, no_accounts};
investigator()->OnAccountsInCookieUpdated(
accounts_in_cookie_jar_info, GoogleServiceAuthError::AuthErrorNone());
@@ -305,7 +303,7 @@ TEST_F(AccountInvestigatorTest,
OnGaiaAccountsInCookieUpdatedSigninSignOutOfContent) {
const HistogramTester histogram_tester;
identity_test_env()->SetPrimaryAccount("1@mail.com");
- identity::AccountsInCookieJarInfo accounts_in_cookie_jar_info = {
+ signin::AccountsInCookieJarInfo accounts_in_cookie_jar_info = {
/*accounts_are_fresh=*/true, just_one, no_accounts};
investigator()->OnAccountsInCookieUpdated(
accounts_in_cookie_jar_info, GoogleServiceAuthError::AuthErrorNone());
@@ -355,7 +353,7 @@ TEST_F(AccountInvestigatorTest, TryPeriodicReportStale) {
std::string email("f@bar.com");
identity_test_env()->SetCookieAccounts(
- {{email, identity::GetTestGaiaIdForEmail(email)}});
+ {{email, signin::GetTestGaiaIdForEmail(email)}});
EXPECT_FALSE(*periodic_pending());
ExpectSharedReportHistograms(ReportingType::PERIODIC, histogram_tester,
diff --git a/chromium/components/signin/core/browser/account_reconcilor.cc b/chromium/components/signin/core/browser/account_reconcilor.cc
index a2f98a11ed4..f609c05f688 100644
--- a/chromium/components/signin/core/browser/account_reconcilor.cc
+++ b/chromium/components/signin/core/browser/account_reconcilor.cc
@@ -20,19 +20,18 @@
#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "components/signin/core/browser/account_consistency_method.h"
#include "components/signin/core/browser/account_reconcilor_delegate.h"
#include "components/signin/core/browser/consistency_cookie_manager_base.h"
-#include "components/signin/core/browser/set_accounts_in_cookie_result.h"
-#include "components/signin/core/browser/signin_buildflags.h"
-#include "components/signin/core/browser/signin_client.h"
-#include "components/signin/core/browser/signin_metrics.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/base/signin_client.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/identity_manager/accounts_cookie_mutator.h"
+#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
+#include "components/signin/public/identity_manager/accounts_mutator.h"
+#include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/google_service_auth_error.h"
-#include "services/identity/public/cpp/accounts_cookie_mutator.h"
-#include "services/identity/public/cpp/accounts_in_cookie_jar_info.h"
-#include "services/identity/public/cpp/accounts_mutator.h"
#if defined(OS_ANDROID)
#include "components/signin/core/browser/consistency_cookie_manager_android.h"
@@ -60,7 +59,7 @@ bool AccountEqualToFunc::operator()(const gaia::ListedAccount& other) const {
return account_.valid == other.valid && account_.id == other.id;
}
-gaia::ListedAccount AccountForId(const std::string& account_id) {
+gaia::ListedAccount AccountForId(const CoreAccountId& account_id) {
gaia::ListedAccount account;
account.id = account_id;
return account;
@@ -81,9 +80,9 @@ std::vector<gaia::ListedAccount> FilterUnverifiedAccounts(
// Revokes tokens for all accounts in chrome_accounts but the primary account.
// Returns true if tokens were revoked, and false if the function did nothing.
bool RevokeAllSecondaryTokens(
- identity::IdentityManager* identity_manager,
+ signin::IdentityManager* identity_manager,
signin::AccountReconcilorDelegate::RevokeTokenOption revoke_option,
- const std::string& primary_account,
+ const CoreAccountId& primary_account,
bool is_account_consistency_enforced,
signin_metrics::SourceForRefreshTokenOperation source) {
bool token_revoked = false;
@@ -92,7 +91,7 @@ bool RevokeAllSecondaryTokens(
return false;
for (const CoreAccountInfo& account_info :
identity_manager->GetAccountsWithRefreshTokens()) {
- std::string account(account_info.account_id);
+ CoreAccountId account = account_info.account_id;
if (account == primary_account)
continue;
bool should_revoke = false;
@@ -127,7 +126,7 @@ bool RevokeAllSecondaryTokens(
}
// Pick the account will become first after this reconcile is finished.
-std::string PickFirstGaiaAccount(
+CoreAccountId PickFirstGaiaAccount(
const signin::MultiloginParameters& parameters,
const std::vector<gaia::ListedAccount>& gaia_accounts) {
if (parameters.mode ==
@@ -135,18 +134,18 @@ std::string PickFirstGaiaAccount(
!gaia_accounts.empty()) {
return gaia_accounts[0].id;
}
- return parameters.accounts_to_send.empty() ? ""
+ return parameters.accounts_to_send.empty() ? CoreAccountId()
: parameters.accounts_to_send[0];
}
// Returns true if gaia_accounts contains an invalid account that is unknown to
// the identity manager.
bool HasUnknownInvalidAccountInCookie(
- identity::IdentityManager* identity_manager,
+ signin::IdentityManager* identity_manager,
const std::vector<gaia::ListedAccount>& gaia_accounts) {
for (const gaia::ListedAccount& account : gaia_accounts) {
if (!account.valid &&
- !identity_manager->HasAccountWithRefreshToken(account.gaia_id)) {
+ !identity_manager->HasAccountWithRefreshToken(account.id)) {
return true;
}
}
@@ -183,7 +182,7 @@ AccountReconcilor::ScopedSyncedDataDeletion::~ScopedSyncedDataDeletion() {
}
AccountReconcilor::AccountReconcilor(
- identity::IdentityManager* identity_manager,
+ signin::IdentityManager* identity_manager,
SigninClient* client,
std::unique_ptr<signin::AccountReconcilorDelegate> delegate)
: delegate_(std::move(delegate)),
@@ -200,8 +199,7 @@ AccountReconcilor::AccountReconcilor(
account_reconcilor_lock_count_(0),
reconcile_on_unblock_(false),
timer_(new base::OneShotTimer),
- state_(signin_metrics::ACCOUNT_RECONCILOR_OK),
- weak_factory_(this) {
+ state_(signin_metrics::ACCOUNT_RECONCILOR_OK) {
VLOG(1) << "AccountReconcilor::AccountReconcilor";
DCHECK(delegate_);
delegate_->set_reconcilor(this);
@@ -251,11 +249,8 @@ void AccountReconcilor::SetIsWKHTTPSystemCookieStoreEnabled(bool is_enabled) {
void AccountReconcilor::EnableReconcile() {
SetState(AccountReconcilorState::ACCOUNT_RECONCILOR_SCHEDULED);
RegisterWithAllDependencies();
-#if !defined(OS_IOS)
- // TODO(droger): Investigate why this breaks tests on iOS.
if (IsIdentityManagerReady())
StartReconcile();
-#endif // !defined(OS_IOS)
}
void AccountReconcilor::DisableReconcile(bool logout_all_accounts) {
@@ -379,7 +374,7 @@ void AccountReconcilor::OnErrorStateOfRefreshTokenUpdatedForAccount(
identity_manager_->GetAccountsCookieMutator()->TriggerCookieJarUpdate();
}
-void AccountReconcilor::PerformMergeAction(const std::string& account_id) {
+void AccountReconcilor::PerformMergeAction(const CoreAccountId& account_id) {
reconcile_is_noop_ = false;
if (!delegate_->IsAccountConsistencyEnforced()) {
MarkAccountAsAddedToCookie(account_id);
@@ -399,14 +394,20 @@ void AccountReconcilor::PerformSetCookiesAction(
OnSetAccountsInCookieCompleted(signin::SetAccountsInCookieResult::kSuccess);
return;
}
+
VLOG(1) << "AccountReconcilor::PerformSetCookiesAction: "
- << base::JoinString(parameters.accounts_to_send, " ");
+ << base::JoinString(ToStringList(parameters.accounts_to_send), " ");
// TODO (https://crbug.com/890321): pass mode to GaiaCookieManagerService.
//
// Using Unretained is safe here because the CookieManagerService outlives
// the AccountReconcilor.
+ // TODO(triploblastic): Remove this vector once account_reconcilor and
+ // related classes has been refactored to use CoreAccountId.
+ std::vector<CoreAccountId> accounts_to_send;
+ for (const auto& account : parameters.accounts_to_send)
+ accounts_to_send.push_back(CoreAccountId(account));
identity_manager_->GetAccountsCookieMutator()->SetAccountsInCookie(
- parameters.accounts_to_send, delegate_->GetGaiaApiSource(),
+ accounts_to_send, delegate_->GetGaiaApiSource(),
base::BindOnce(&AccountReconcilor::OnSetAccountsInCookieCompleted,
base::Unretained(this)));
}
@@ -461,7 +462,7 @@ void AccountReconcilor::StartReconcile() {
base::Unretained(this)));
}
- const std::string& account_id = identity_manager_->GetPrimaryAccountId();
+ const CoreAccountId& account_id = identity_manager_->GetPrimaryAccountId();
if (identity_manager_->HasAccountWithRefreshTokenInPersistentErrorState(
account_id) &&
delegate_->ShouldAbortReconcileIfPrimaryHasError()) {
@@ -475,7 +476,7 @@ void AccountReconcilor::StartReconcile() {
// Rely on the IdentityManager to manage calls to and responses from
// ListAccounts.
- identity::AccountsInCookieJarInfo accounts_in_cookie_jar =
+ signin::AccountsInCookieJarInfo accounts_in_cookie_jar =
identity_manager_->GetAccountsInCookieJar();
if (accounts_in_cookie_jar.accounts_are_fresh) {
OnAccountsInCookieUpdated(
@@ -485,8 +486,8 @@ void AccountReconcilor::StartReconcile() {
}
void AccountReconcilor::FinishReconcileWithMultiloginEndpoint(
- const std::string& primary_account,
- const std::vector<std::string>& chrome_accounts,
+ const CoreAccountId& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
std::vector<gaia::ListedAccount>&& gaia_accounts) {
DCHECK(IsMultiloginEndpointEnabled());
DCHECK(!set_accounts_in_progress_);
@@ -538,7 +539,7 @@ void AccountReconcilor::FinishReconcileWithMultiloginEndpoint(
// be already consistent.
DCHECK(!CookieNeedsUpdate(parameters_for_multilogin, gaia_accounts));
DCHECK_NE(AccountReconcilorState::ACCOUNT_RECONCILOR_RUNNING, state_);
- std::string first_gaia_account_after_reconcile =
+ CoreAccountId first_gaia_account_after_reconcile =
PickFirstGaiaAccount(parameters_for_multilogin, gaia_accounts);
delegate_->OnReconcileFinished(first_gaia_account_after_reconcile,
reconcile_is_noop_);
@@ -547,7 +548,7 @@ void AccountReconcilor::FinishReconcileWithMultiloginEndpoint(
}
void AccountReconcilor::OnAccountsInCookieUpdated(
- const identity::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+ const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
const GoogleServiceAuthError& error) {
const std::vector<gaia::ListedAccount>& accounts(
accounts_in_cookie_jar_info.signed_in_accounts);
@@ -590,7 +591,7 @@ void AccountReconcilor::OnAccountsInCookieUpdated(
<< "Ignore " << accounts.size() - verified_gaia_accounts.size()
<< " unverified account(s).";
- std::string primary_account = identity_manager_->GetPrimaryAccountId();
+ CoreAccountId primary_account = identity_manager_->GetPrimaryAccountId();
// Revoking tokens for secondary accounts causes the AccountTracker to
// completely remove them from Chrome.
// Revoking the token for the primary account is not supported (it should be
@@ -603,11 +604,11 @@ void AccountReconcilor::OnAccountsInCookieUpdated(
signin_metrics::SourceForRefreshTokenOperation::
kAccountReconcilor_GaiaCookiesUpdated);
- std::vector<std::string> chrome_accounts =
+ std::vector<CoreAccountId> chrome_accounts =
LoadValidAccountsFromTokenService();
if (delegate_->ShouldAbortReconcileIfPrimaryHasError() &&
- !base::ContainsValue(chrome_accounts, primary_account)) {
+ !base::Contains(chrome_accounts, primary_account)) {
VLOG(1) << "Primary account has error, abort.";
DCHECK(is_reconcile_started_);
AbortReconcile();
@@ -628,7 +629,8 @@ void AccountReconcilor::OnAccountsCookieDeletedByUserAction() {
if (!delegate_->ShouldRevokeTokensOnCookieDeleted())
return;
- const std::string& primary_account = identity_manager_->GetPrimaryAccountId();
+ const CoreAccountId& primary_account =
+ identity_manager_->GetPrimaryAccountId();
// Revoke secondary tokens.
RevokeAllSecondaryTokens(
identity_manager_, AccountReconcilorDelegate::RevokeTokenOption::kRevoke,
@@ -648,12 +650,12 @@ void AccountReconcilor::OnAccountsCookieDeletedByUserAction() {
}
}
-std::vector<std::string> AccountReconcilor::LoadValidAccountsFromTokenService()
- const {
+std::vector<CoreAccountId>
+AccountReconcilor::LoadValidAccountsFromTokenService() const {
auto chrome_accounts_with_refresh_tokens =
identity_manager_->GetAccountsWithRefreshTokens();
- std::vector<std::string> chrome_account_ids;
+ std::vector<CoreAccountId> chrome_account_ids;
// Remove any accounts that have an error. There is no point in trying to
// reconcile them, since it won't work anyway. If the list ends up being
@@ -684,14 +686,17 @@ void AccountReconcilor::OnReceivedManageAccountsResponse(
}
void AccountReconcilor::FinishReconcile(
- const std::string& primary_account,
- const std::vector<std::string>& chrome_accounts,
+ const CoreAccountId& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
std::vector<gaia::ListedAccount>&& gaia_accounts) {
VLOG(1) << "AccountReconcilor::FinishReconcile";
DCHECK(add_to_cookie_.empty());
DCHECK(delegate_->IsUnknownInvalidAccountInCookieAllowed())
<< "Only supported in UPDATE mode";
+ delegate_->MaybeLogInconsistencyReason(primary_account, chrome_accounts,
+ gaia_accounts, first_execution_);
+
size_t number_gaia_accounts = gaia_accounts.size();
// If there are any accounts in the gaia cookie but not in chrome, then
// those accounts need to be removed from the cookie. This means we need
@@ -699,12 +704,12 @@ void AccountReconcilor::FinishReconcile(
int removed_from_cookie = 0;
for (size_t i = 0; i < number_gaia_accounts; ++i) {
if (gaia_accounts[i].valid &&
- !base::ContainsValue(chrome_accounts, gaia_accounts[i].id)) {
+ !base::Contains(chrome_accounts, gaia_accounts[i].id)) {
++removed_from_cookie;
}
}
- std::string first_account = delegate_->GetFirstGaiaAccountForReconcile(
+ CoreAccountId first_account = delegate_->GetFirstGaiaAccountForReconcile(
chrome_accounts, gaia_accounts, primary_account, first_execution_,
removed_from_cookie > 0);
bool first_account_mismatch =
@@ -731,13 +736,13 @@ void AccountReconcilor::FinishReconcile(
kAccountReconcilor_Reconcile);
} else {
// Create a list of accounts that need to be added to the Gaia cookie.
- if (base::ContainsValue(chrome_accounts, first_account)) {
+ if (base::Contains(chrome_accounts, first_account)) {
add_to_cookie_.push_back(first_account);
} else {
// If the first account is not empty and not in chrome_accounts, it is
// impossible to rebuild it. It must be already the current default
// account, and no logout can happen.
- DCHECK_EQ(gaia_accounts[0].gaia_id, first_account);
+ DCHECK_EQ(gaia_accounts[0].id, first_account);
DCHECK(!rebuild_cookie);
}
for (size_t i = 0; i < chrome_accounts.size(); ++i) {
@@ -748,9 +753,9 @@ void AccountReconcilor::FinishReconcile(
// For each account known to chrome, PerformMergeAction() if the account is
// not already in the cookie jar or its state is invalid, or signal merge
- // completed otherwise. Make a copy of |add_to_cookie_| since calls to
- // OnAddAccountToCookieCompleted() will change the array.
- std::vector<std::string> add_to_cookie_copy = add_to_cookie_;
+ // completed otherwise. Make a copy of |add_to_cookie_| since calls
+ // to OnAddAccountToCookieCompleted() will change the array.
+ std::vector<CoreAccountId> add_to_cookie_copy = add_to_cookie_;
int added_to_cookie = 0;
for (size_t i = 0; i < add_to_cookie_copy.size(); ++i) {
if (gaia_accounts.end() !=
@@ -843,7 +848,7 @@ void AccountReconcilor::ScheduleStartReconcileIfChromeAccountsChanged() {
// Remove the account from the list that is being merged.
bool AccountReconcilor::MarkAccountAsAddedToCookie(
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
for (auto i = add_to_cookie_.begin(); i != add_to_cookie_.end(); ++i) {
if (account_id == *i) {
add_to_cookie_.erase(i);
@@ -854,16 +859,7 @@ bool AccountReconcilor::MarkAccountAsAddedToCookie(
}
bool AccountReconcilor::IsIdentityManagerReady() {
-#if defined(OS_CHROMEOS)
- // TODO(droger): ChromeOS should use the same logic as other platforms. See
- // https://crbug.com/749535
- // On ChromeOS, there are cases where the IdentityManager is never fully
- // initialized and AreAllCredentialsLoaded() always return false.
- return identity_manager_->AreRefreshTokensLoaded() ||
- (identity_manager_->GetAccountsWithRefreshTokens().size() > 0);
-#else
return identity_manager_->AreRefreshTokensLoaded();
-#endif
}
void AccountReconcilor::OnSetAccountsInCookieCompleted(
@@ -894,7 +890,7 @@ void AccountReconcilor::OnSetAccountsInCookieCompleted(
}
void AccountReconcilor::OnAddAccountToCookieCompleted(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const GoogleServiceAuthError& error) {
VLOG(1) << "AccountReconcilor::OnAddAccountToCookieCompleted: "
<< "Account added: " << account_id << ", "
@@ -1015,9 +1011,9 @@ bool AccountReconcilor::CookieNeedsUpdate(
}
// Maybe some accounts in cookies are not valid and need refreshing.
- std::set<std::string> accounts_to_send_set(
+ std::set<CoreAccountId> accounts_to_send_set(
parameters.accounts_to_send.begin(), parameters.accounts_to_send.end());
- std::set<std::string> existing_accounts_set;
+ std::set<CoreAccountId> existing_accounts_set;
for (const gaia::ListedAccount& account : existing_accounts) {
if (account.valid)
existing_accounts_set.insert(account.id);
diff --git a/chromium/components/signin/core/browser/account_reconcilor.h b/chromium/components/signin/core/browser/account_reconcilor.h
index 9801137824e..387cd6f6ed6 100644
--- a/chromium/components/signin/core/browser/account_reconcilor.h
+++ b/chromium/components/signin/core/browser/account_reconcilor.h
@@ -23,11 +23,11 @@
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/signin/core/browser/account_reconcilor_delegate.h"
-#include "components/signin/core/browser/signin_client.h"
#include "components/signin/core/browser/signin_header_helper.h"
-#include "components/signin/core/browser/signin_metrics.h"
+#include "components/signin/public/base/signin_client.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
#include "google_apis/gaia/google_service_auth_error.h"
-#include "services/identity/public/cpp/identity_manager.h"
// Enables usage of Gaia Auth Multilogin endpoint for identity consistency.
extern const base::Feature kUseMultiloginEndpoint;
@@ -42,7 +42,7 @@ class SigninClient;
class AccountReconcilor : public KeyedService,
public content_settings::Observer,
- public identity::IdentityManager::Observer {
+ public signin::IdentityManager::Observer {
public:
// When an instance of this class exists, the account reconcilor is suspended.
// It will automatically restart when all instances of Lock have been
@@ -94,7 +94,7 @@ class AccountReconcilor : public KeyedService,
};
AccountReconcilor(
- identity::IdentityManager* identity_manager,
+ signin::IdentityManager* identity_manager,
SigninClient* client,
std::unique_ptr<signin::AccountReconcilorDelegate> delegate);
~AccountReconcilor() override;
@@ -146,6 +146,8 @@ class AccountReconcilor : public KeyedService,
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorMirrorEndpointParamTest,
ProfileAlreadyConnected);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTestTable, TableRowTest);
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTestTable,
+ InconsistencyReasonLogging);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTestDiceMultilogin, TableRowTest);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTestMirrorMultilogin, TableRowTest);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTestMiceMultilogin, TableRowTest);
@@ -254,7 +256,7 @@ class AccountReconcilor : public KeyedService,
// All actions with side effects, only doing meaningful work if account
// consistency is enabled. Virtual so that they can be overridden in tests.
- virtual void PerformMergeAction(const std::string& account_id);
+ virtual void PerformMergeAction(const CoreAccountId& account_id);
virtual void PerformLogoutAllAccountsAction();
virtual void PerformSetCookiesAction(
const signin::MultiloginParameters& parameters);
@@ -262,18 +264,18 @@ class AccountReconcilor : public KeyedService,
// Used during periodic reconciliation.
void StartReconcile();
// |gaia_accounts| are the accounts in the Gaia cookie.
- void FinishReconcile(const std::string& primary_account,
- const std::vector<std::string>& chrome_accounts,
+ void FinishReconcile(const CoreAccountId& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
std::vector<gaia::ListedAccount>&& gaia_accounts);
void AbortReconcile();
void CalculateIfReconcileIsDone();
void ScheduleStartReconcileIfChromeAccountsChanged();
// Returns the list of valid accounts from the TokenService.
- std::vector<std::string> LoadValidAccountsFromTokenService() const;
+ std::vector<CoreAccountId> LoadValidAccountsFromTokenService() const;
// Note internally that this |account_id| is added to the cookie jar.
- bool MarkAccountAsAddedToCookie(const std::string& account_id);
+ bool MarkAccountAsAddedToCookie(const CoreAccountId& account_id);
// The reconcilor only starts when the token service is ready.
bool IsIdentityManagerReady();
@@ -284,24 +286,23 @@ class AccountReconcilor : public KeyedService,
ContentSettingsType content_type,
const std::string& resource_identifier) override;
-
- // Overridden from identity::IdentityManager::Observer.
+ // Overridden from signin::IdentityManager::Observer.
void OnEndBatchOfRefreshTokenStateChanges() override;
void OnRefreshTokensLoaded() override;
void OnErrorStateOfRefreshTokenUpdatedForAccount(
const CoreAccountInfo& account_info,
const GoogleServiceAuthError& error) override;
void OnAccountsInCookieUpdated(
- const identity::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+ const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
const GoogleServiceAuthError& error) override;
void OnAccountsCookieDeletedByUserAction() override;
void FinishReconcileWithMultiloginEndpoint(
- const std::string& primary_account,
- const std::vector<std::string>& chrome_accounts,
+ const CoreAccountId& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
std::vector<gaia::ListedAccount>&& gaia_accounts);
- void OnAddAccountToCookieCompleted(const std::string& account_id,
+ void OnAddAccountToCookieCompleted(const CoreAccountId& account_id,
const GoogleServiceAuthError& error);
void OnSetAccountsInCookieCompleted(signin::SetAccountsInCookieResult result);
@@ -330,7 +331,7 @@ class AccountReconcilor : public KeyedService,
std::unique_ptr<signin::AccountReconcilorDelegate> delegate_;
// The IdentityManager associated with this reconcilor.
- identity::IdentityManager* identity_manager_;
+ signin::IdentityManager* identity_manager_;
// The SigninClient associated with this reconcilor.
SigninClient* client_;
@@ -361,8 +362,8 @@ class AccountReconcilor : public KeyedService,
bool reconcile_is_noop_;
// Used during reconcile action.
- std::vector<std::string> add_to_cookie_; // Progress of AddAccount calls.
- bool set_accounts_in_progress_; // Progress of SetAccounts calls.
+ std::vector<CoreAccountId> add_to_cookie_; // Progress of AddAccount calls.
+ bool set_accounts_in_progress_; // Progress of SetAccounts calls.
bool chrome_accounts_changed_;
// Used for the Lock.
@@ -398,7 +399,7 @@ class AccountReconcilor : public KeyedService,
std::unique_ptr<signin::ConsistencyCookieManagerBase>
consistency_cookie_manager_;
- base::WeakPtrFactory<AccountReconcilor> weak_factory_;
+ base::WeakPtrFactory<AccountReconcilor> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(AccountReconcilor);
};
diff --git a/chromium/components/signin/core/browser/account_reconcilor_delegate.cc b/chromium/components/signin/core/browser/account_reconcilor_delegate.cc
index 1b5d13c290d..3cf1a3bbb7a 100644
--- a/chromium/components/signin/core/browser/account_reconcilor_delegate.cc
+++ b/chromium/components/signin/core/browser/account_reconcilor_delegate.cc
@@ -18,6 +18,12 @@ bool AccountReconcilorDelegate::IsAccountConsistencyEnforced() const {
return false;
}
+void AccountReconcilorDelegate::MaybeLogInconsistencyReason(
+ const CoreAccountId& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const std::vector<gaia::ListedAccount>& gaia_accounts,
+ bool first_execution) const {}
+
gaia::GaiaSource AccountReconcilorDelegate::GetGaiaApiSource() const {
NOTREACHED() << "Reconcile is not enabled, no Gaia API calls should be made.";
return gaia::GaiaSource::kChrome;
@@ -27,25 +33,25 @@ bool AccountReconcilorDelegate::ShouldAbortReconcileIfPrimaryHasError() const {
return false;
}
-std::string AccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
- const std::vector<std::string>& chrome_accounts,
+CoreAccountId AccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string& primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool will_logout) const {
- return std::string();
+ return CoreAccountId();
}
MultiloginParameters
AccountReconcilorDelegate::CalculateParametersForMultilogin(
- const std::vector<std::string>& chrome_accounts,
- const std::string& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const CoreAccountId& primary_account,
const std::vector<gaia::ListedAccount>& gaia_accounts,
bool first_execution,
bool primary_has_error) const {
const gaia::MultiloginMode mode = CalculateModeForReconcile(
gaia_accounts, primary_account, first_execution, primary_has_error);
- const std::vector<std::string> accounts_to_send =
+ const std::vector<CoreAccountId> accounts_to_send =
GetChromeAccountsForReconcile(chrome_accounts, primary_account,
gaia_accounts, mode);
return {mode, accounts_to_send};
@@ -53,38 +59,38 @@ AccountReconcilorDelegate::CalculateParametersForMultilogin(
gaia::MultiloginMode AccountReconcilorDelegate::CalculateModeForReconcile(
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool primary_has_error) const {
return gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER;
}
-std::vector<std::string>
+std::vector<CoreAccountId>
AccountReconcilorDelegate::ReorderChromeAccountsForReconcile(
- const std::vector<std::string>& chrome_accounts,
- const std::string& first_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const CoreAccountId& first_account,
const std::vector<gaia::ListedAccount>& gaia_accounts) const {
// Gaia only supports kMaxGaiaAccounts. Multilogin and MergeSession calls
// which go above this count will fail.
const int kMaxGaiaAccounts = 10;
DCHECK(!first_account.empty());
- DCHECK(base::ContainsValue(chrome_accounts, first_account));
+ DCHECK(base::Contains(chrome_accounts, first_account));
// Ordered list of accounts, this is the result of this function.
- std::vector<std::string> ordered_accounts;
+ std::vector<CoreAccountId> ordered_accounts;
ordered_accounts.reserve(gaia_accounts.size());
// Set of accounts that must be added to ordered_accounts.
- std::set<std::string> chrome_accounts_set(chrome_accounts.begin(),
- chrome_accounts.end());
+ std::set<CoreAccountId> chrome_accounts_set(chrome_accounts.begin(),
+ chrome_accounts.end());
// Start from the gaia accounts.
for (const gaia::ListedAccount& account : gaia_accounts)
ordered_accounts.push_back(account.id);
// Keep only accounts that are in chrome_accounts_set.
- for (std::string& account : ordered_accounts) {
+ for (CoreAccountId& account : ordered_accounts) {
if (chrome_accounts_set.find(account) == chrome_accounts_set.end())
- account = std::string();
+ account = CoreAccountId();
else
chrome_accounts_set.erase(account);
}
@@ -101,7 +107,7 @@ AccountReconcilorDelegate::ReorderChromeAccountsForReconcile(
// The first account was not already in the cookies, add it in the first
// empty spot, or at the end if there is no available spot.
first_account_it = std::find(ordered_accounts.begin(),
- ordered_accounts.end(), std::string());
+ ordered_accounts.end(), CoreAccountId());
if (first_account_it == ordered_accounts.end()) {
first_account_it =
ordered_accounts.insert(first_account_it, first_account);
@@ -115,7 +121,7 @@ AccountReconcilorDelegate::ReorderChromeAccountsForReconcile(
// Add the remaining chrome accounts.
// First in empty spots.
auto remaining_accounts_it = chrome_accounts_set.begin();
- for (std::string& account : ordered_accounts) {
+ for (CoreAccountId& account : ordered_accounts) {
if (remaining_accounts_it == chrome_accounts_set.end())
break;
if (account.empty()) {
@@ -138,7 +144,7 @@ AccountReconcilorDelegate::ReorderChromeAccountsForReconcile(
ordered_accounts.pop_back();
// Find next empty slot.
compacting_it =
- std::find(compacting_it, ordered_accounts.end(), std::string());
+ std::find(compacting_it, ordered_accounts.end(), CoreAccountId());
// Swap it with the last element.
if (compacting_it != ordered_accounts.end())
std::swap(*compacting_it, ordered_accounts.back());
@@ -155,13 +161,13 @@ AccountReconcilorDelegate::ReorderChromeAccountsForReconcile(
return ordered_accounts;
}
-std::vector<std::string>
+std::vector<CoreAccountId>
AccountReconcilorDelegate::GetChromeAccountsForReconcile(
- const std::vector<std::string>& chrome_accounts,
- const std::string& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const CoreAccountId& primary_account,
const std::vector<gaia::ListedAccount>& gaia_accounts,
const gaia::MultiloginMode mode) const {
- return std::vector<std::string>();
+ return std::vector<CoreAccountId>();
}
AccountReconcilorDelegate::RevokeTokenOption
diff --git a/chromium/components/signin/core/browser/account_reconcilor_delegate.h b/chromium/components/signin/core/browser/account_reconcilor_delegate.h
index e75cfe0cda1..ab7cf8a88e4 100644
--- a/chromium/components/signin/core/browser/account_reconcilor_delegate.h
+++ b/chromium/components/signin/core/browser/account_reconcilor_delegate.h
@@ -9,7 +9,7 @@
#include <vector>
#include "base/time/time.h"
-#include "components/signin/core/browser/gaia_cookie_manager_service.h"
+#include "components/signin/core/browser/multilogin_parameters.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/google_service_auth_error.h"
@@ -43,6 +43,13 @@ class AccountReconcilorDelegate {
// changes to the accounts are made. Defaults to false.
virtual bool IsAccountConsistencyEnforced() const;
+ // Computes inconsistency reason and uploads it to UMA.
+ virtual void MaybeLogInconsistencyReason(
+ const CoreAccountId& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const std::vector<gaia::ListedAccount>& gaia_accounts,
+ bool first_execution) const;
+
// Returns the value to set in the "source" parameter for Gaia API calls.
virtual gaia::GaiaSource GetGaiaApiSource() const;
@@ -57,17 +64,17 @@ class AccountReconcilorDelegate {
// |will_logout| is true if the reconcilor will perform a logout no matter
// what is returned by this function.
// Only used with MergeSession.
- virtual std::string GetFirstGaiaAccountForReconcile(
- const std::vector<std::string>& chrome_accounts,
+ virtual CoreAccountId GetFirstGaiaAccountForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string& primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool will_logout) const;
// Returns a pair of mode and accounts to send to Mutilogin endpoint.
MultiloginParameters CalculateParametersForMultilogin(
- const std::vector<std::string>& chrome_accounts,
- const std::string& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const CoreAccountId& primary_account,
const std::vector<gaia::ListedAccount>& gaia_accounts,
bool first_execution,
bool primary_has_error) const;
@@ -88,7 +95,7 @@ class AccountReconcilorDelegate {
// |OnReconcileFinished| is always called at the end of reconciliation, even
// when there is an error (except in cases where reconciliation times out
// before finishing, see |GetReconcileTimeout|).
- virtual void OnReconcileFinished(const std::string& first_account,
+ virtual void OnReconcileFinished(const CoreAccountId& first_account,
bool reconcile_is_noop) {}
// Returns the desired timeout for account reconciliation. If reconciliation
@@ -125,17 +132,17 @@ class AccountReconcilorDelegate {
// Aplhabetical order is used to break ties.
// Note: the input order of the accounts in |chrome_accounts| does not matter
// (different orders yield to the same result).
- std::vector<std::string> ReorderChromeAccountsForReconcile(
- const std::vector<std::string>& chrome_accounts,
- const std::string& first_account,
+ std::vector<CoreAccountId> ReorderChromeAccountsForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const CoreAccountId& first_account,
const std::vector<gaia::ListedAccount>& gaia_accounts) const;
private:
// Reorders chrome accounts in the order they should appear in cookies with
// respect to existing cookies.
- virtual std::vector<std::string> GetChromeAccountsForReconcile(
- const std::vector<std::string>& chrome_accounts,
- const std::string& primary_account,
+ virtual std::vector<CoreAccountId> GetChromeAccountsForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const CoreAccountId& primary_account,
const std::vector<gaia::ListedAccount>& gaia_accounts,
const gaia::MultiloginMode mode) const;
@@ -143,7 +150,7 @@ class AccountReconcilorDelegate {
// accounts (e.g. on mobile or on stratup). Default is UPDATE.
virtual gaia::MultiloginMode CalculateModeForReconcile(
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool primary_has_error) const;
diff --git a/chromium/components/signin/core/browser/account_reconcilor_delegate_unittest.cc b/chromium/components/signin/core/browser/account_reconcilor_delegate_unittest.cc
index c8bdedf51de..218386d9725 100644
--- a/chromium/components/signin/core/browser/account_reconcilor_delegate_unittest.cc
+++ b/chromium/components/signin/core/browser/account_reconcilor_delegate_unittest.cc
@@ -107,7 +107,7 @@ class AccountReconcilorDelegateTest
std::vector<gaia::ListedAccount> gaia_accounts;
for (const char& c : account_string) {
gaia::ListedAccount account;
- account.id = std::string(1, c);
+ account.id = CoreAccountId(std::string(1, c));
gaia_accounts.push_back(account);
}
return gaia_accounts;
@@ -116,24 +116,27 @@ class AccountReconcilorDelegateTest
TEST_P(AccountReconcilorDelegateTest, ReorderChromeAccountsForReconcile) {
// Decode test parameters.
- std::string first_account = std::string(1, GetParam().first_account);
- std::vector<std::string> chrome_accounts;
- for (int i = 0; GetParam().chrome_accounts[i] != '\0'; ++i)
- chrome_accounts.push_back(std::string(1, GetParam().chrome_accounts[i]));
- ASSERT_TRUE(base::ContainsValue(chrome_accounts, first_account))
+ CoreAccountId first_account =
+ CoreAccountId(std::string(1, GetParam().first_account));
+ std::vector<CoreAccountId> chrome_accounts;
+ for (int i = 0; GetParam().chrome_accounts[i] != '\0'; ++i) {
+ chrome_accounts.push_back(
+ CoreAccountId(std::string(1, GetParam().chrome_accounts[i])));
+ }
+ ASSERT_TRUE(base::Contains(chrome_accounts, first_account))
<< "Invalid test parameter.";
std::vector<gaia::ListedAccount> gaia_accounts =
GaiaAccountsFromString(GetParam().gaia_accounts);
// Reorder the accounts.
- std::vector<std::string> order = ReorderChromeAccountsForReconcile(
+ std::vector<CoreAccountId> order = ReorderChromeAccountsForReconcile(
chrome_accounts, first_account, gaia_accounts);
// Check results.
std::string order_as_string;
- for (const std::string& account : order) {
- ASSERT_EQ(1u, account.size());
- order_as_string += account;
+ for (const CoreAccountId& account : order) {
+ ASSERT_EQ(1u, account.id.size());
+ order_as_string += account.id;
}
EXPECT_EQ(GetParam().expected_order, order_as_string);
diff --git a/chromium/components/signin/core/browser/account_reconcilor_unittest.cc b/chromium/components/signin/core/browser/account_reconcilor_unittest.cc
index a1d22a5f74e..2269dd882ff 100644
--- a/chromium/components/signin/core/browser/account_reconcilor_unittest.cc
+++ b/chromium/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -19,27 +19,26 @@
#include "base/time/time.h"
#include "base/timer/mock_timer.h"
#include "build/build_config.h"
-#include "components/image_fetcher/core/fake_image_decoder.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/signin/core/browser/account_consistency_method.h"
+#include "components/prefs/pref_service.h"
#include "components/signin/core/browser/account_reconcilor.h"
-#include "components/signin/core/browser/list_accounts_test_utils.h"
#include "components/signin/core/browser/mice_account_reconcilor_delegate.h"
#include "components/signin/core/browser/mirror_account_reconcilor_delegate.h"
-#include "components/signin/core/browser/set_accounts_in_cookie_result.h"
-#include "components/signin/core/browser/signin_buildflags.h"
-#include "components/signin/core/browser/signin_metrics.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "components/signin/core/browser/test_signin_client.h"
-#include "components/sync_preferences/pref_service_syncable.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/base/list_accounts_test_utils.h"
+#include "components/signin/public/base/signin_buildflags.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/base/test_signin_client.h"
+#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "components/signin/public/identity_manager/identity_test_utils.h"
+#include "components/signin/public/identity_manager/primary_account_mutator.h"
+#include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "net/url_request/test_url_fetcher_factory.h"
-#include "services/identity/public/cpp/identity_test_environment.h"
-#include "services/identity/public/cpp/identity_test_utils.h"
-#include "services/identity/public/cpp/primary_account_mutator.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -67,16 +66,16 @@ class SpyReconcilorDelegate : public signin::AccountReconcilorDelegate {
bool ShouldAbortReconcileIfPrimaryHasError() const override { return true; }
- std::string GetFirstGaiaAccountForReconcile(
- const std::vector<std::string>& chrome_accounts,
+ CoreAccountId GetFirstGaiaAccountForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string& primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool will_logout) const override {
return primary_account;
}
- void OnReconcileFinished(const std::string& first_account,
+ void OnReconcileFinished(const CoreAccountId& first_account,
bool reconcile_is_noop) override {
++num_reconcile_finished_calls_;
}
@@ -98,7 +97,7 @@ class SpyReconcilorDelegate : public signin::AccountReconcilorDelegate {
class DummyAccountReconcilorWithDelegate : public AccountReconcilor {
public:
DummyAccountReconcilorWithDelegate(
- identity::IdentityManager* identity_manager,
+ signin::IdentityManager* identity_manager,
SigninClient* client,
signin::AccountConsistencyMethod account_consistency)
: AccountReconcilor(
@@ -116,7 +115,7 @@ class DummyAccountReconcilorWithDelegate : public AccountReconcilor {
// Takes ownership of |delegate|.
// gmock can't work with move only parameters.
DummyAccountReconcilorWithDelegate(
- identity::IdentityManager* identity_manager,
+ signin::IdentityManager* identity_manager,
SigninClient* client,
signin::AccountReconcilorDelegate* delegate)
: AccountReconcilor(
@@ -132,7 +131,7 @@ class DummyAccountReconcilorWithDelegate : public AccountReconcilor {
static std::unique_ptr<signin::AccountReconcilorDelegate>
CreateAccountReconcilorDelegate(
SigninClient* signin_client,
- identity::IdentityManager* identity_manager,
+ signin::IdentityManager* identity_manager,
signin::AccountConsistencyMethod account_consistency) {
switch (account_consistency) {
case signin::AccountConsistencyMethod::kMirror:
@@ -163,23 +162,23 @@ class MockAccountReconcilor
: public testing::StrictMock<DummyAccountReconcilorWithDelegate> {
public:
explicit MockAccountReconcilor(
- identity::IdentityManager* identity_manager,
+ signin::IdentityManager* identity_manager,
SigninClient* client,
signin::AccountConsistencyMethod account_consistency);
explicit MockAccountReconcilor(
- identity::IdentityManager* identity_manager,
+ signin::IdentityManager* identity_manager,
SigninClient* client,
std::unique_ptr<signin::AccountReconcilorDelegate> delegate);
- MOCK_METHOD1(PerformMergeAction, void(const std::string& account_id));
+ MOCK_METHOD1(PerformMergeAction, void(const CoreAccountId& account_id));
MOCK_METHOD0(PerformLogoutAllAccountsAction, void());
MOCK_METHOD1(PerformSetCookiesAction,
void(const signin::MultiloginParameters& parameters));
};
MockAccountReconcilor::MockAccountReconcilor(
- identity::IdentityManager* identity_manager,
+ signin::IdentityManager* identity_manager,
SigninClient* client,
signin::AccountConsistencyMethod account_consistency)
: testing::StrictMock<DummyAccountReconcilorWithDelegate>(
@@ -188,7 +187,7 @@ MockAccountReconcilor::MockAccountReconcilor(
account_consistency) {}
MockAccountReconcilor::MockAccountReconcilor(
- identity::IdentityManager* identity_manager,
+ signin::IdentityManager* identity_manager,
SigninClient* client,
std::unique_ptr<signin::AccountReconcilorDelegate> delegate)
: testing::StrictMock<DummyAccountReconcilorWithDelegate>(
@@ -208,7 +207,7 @@ struct Cookie {
// Converts CookieParams to ListedAccounts.
gaia::ListedAccount ListedAccountFromCookieParams(
const signin::CookieParams& params,
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
gaia::ListedAccount listed_account;
listed_account.id = account_id;
listed_account.email = params.email;
@@ -227,9 +226,14 @@ class AccountReconcilorTest : public ::testing::Test {
AccountReconcilorTest();
~AccountReconcilorTest() override;
- identity::IdentityTestEnvironment* identity_test_env() {
+ signin::IdentityTestEnvironment* identity_test_env() {
return &identity_test_env_;
}
+
+ base::test::ScopedTaskEnvironment* task_environment() {
+ return &task_environment_;
+ }
+
TestSigninClient* test_signin_client() { return &test_signin_client_; }
base::HistogramTester* histogram_tester() { return &histogram_tester_; }
@@ -239,11 +243,11 @@ class AccountReconcilorTest : public ::testing::Test {
AccountInfo ConnectProfileToAccount(const std::string& email);
- std::string PickAccountIdForAccount(const std::string& gaia_id,
- const std::string& username);
+ CoreAccountId PickAccountIdForAccount(const std::string& gaia_id,
+ const std::string& username);
void SimulateAddAccountToCookieCompleted(AccountReconcilor* reconcilor,
- const std::string& account_id,
+ const CoreAccountId& account_id,
const GoogleServiceAuthError& error);
void SimulateCookieContentSettingsChanged(
@@ -267,7 +271,7 @@ class AccountReconcilorTest : public ::testing::Test {
signin::AccountConsistencyMethod account_consistency_;
sync_preferences::TestingPrefServiceSyncable pref_service_;
TestSigninClient test_signin_client_;
- identity::IdentityTestEnvironment identity_test_env_;
+ signin::IdentityTestEnvironment identity_test_env_;
std::unique_ptr<MockAccountReconcilor> mock_reconcilor_;
base::HistogramTester histogram_tester_;
@@ -327,15 +331,14 @@ INSTANTIATE_TEST_SUITE_P(Dice_Mirror,
signin::AccountConsistencyMethod::kMirror));
AccountReconcilorTest::AccountReconcilorTest()
- : account_consistency_(signin::AccountConsistencyMethod::kDisabled),
+ : task_environment_(
+ base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
+ account_consistency_(signin::AccountConsistencyMethod::kDisabled),
test_signin_client_(&pref_service_, &test_url_loader_factory_),
identity_test_env_(/*test_url_loader_factory=*/nullptr,
&pref_service_,
account_consistency_,
&test_signin_client_) {
- pref_service_.registry()->RegisterBooleanPref(
- prefs::kTokenServiceDiceCompatible, false);
-
signin::SetListAccountsResponseHttpNotFound(&test_url_loader_factory_);
// The reconcilor should not be built before the test can set the account
@@ -375,7 +378,7 @@ AccountInfo AccountReconcilorTest::ConnectProfileToAccount(
return account_info;
}
-std::string AccountReconcilorTest::PickAccountIdForAccount(
+CoreAccountId AccountReconcilorTest::PickAccountIdForAccount(
const std::string& gaia_id,
const std::string& username) {
return identity_test_env()->identity_manager()->PickAccountIdForAccount(
@@ -384,7 +387,7 @@ std::string AccountReconcilorTest::PickAccountIdForAccount(
void AccountReconcilorTest::SimulateAddAccountToCookieCompleted(
AccountReconcilor* reconcilor,
- const std::string& account_id,
+ const CoreAccountId& account_id,
const GoogleServiceAuthError& error) {
reconcilor->OnAddAccountToCookieCompleted(account_id, error);
}
@@ -429,6 +432,8 @@ struct AccountReconcilorTestTableParam {
const char* gaia_api_calls_multilogin;
const char* tokens_after_reconcile_multilogin;
const char* cookies_after_reconcile_multilogin;
+ // Int represents AccountReconcilorDelegate::InconsistencyReason.
+ const int inconsistency_reason;
};
std::vector<AccountReconcilorTestTableParam> GenerateTestCasesFromParams(
@@ -476,11 +481,11 @@ class AccountReconcilorTestTable
AccountReconcilorTestTable() {
accounts_['A'] = {"a@gmail.com",
- identity::GetTestGaiaIdForEmail("a@gmail.com")};
+ signin::GetTestGaiaIdForEmail("a@gmail.com")};
accounts_['B'] = {"b@gmail.com",
- identity::GetTestGaiaIdForEmail("b@gmail.com")};
+ signin::GetTestGaiaIdForEmail("b@gmail.com")};
accounts_['C'] = {"c@gmail.com",
- identity::GetTestGaiaIdForEmail("c@gmail.com")};
+ signin::GetTestGaiaIdForEmail("c@gmail.com")};
}
// Build Tokens from string.
@@ -531,7 +536,7 @@ class AccountReconcilorTestTable
bool authenticated_account_found = false;
for (const Token& token : tokens) {
- std::string account_id =
+ CoreAccountId account_id =
PickAccountIdForAccount(token.gaia_id, token.email);
EXPECT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id));
EXPECT_EQ(
@@ -552,7 +557,7 @@ class AccountReconcilorTestTable
ParseTokenString(GetParam().tokens);
Token primary_account;
for (const Token& token : tokens_before_reconcile) {
- std::string account_id;
+ CoreAccountId account_id;
if (token.is_authenticated) {
account_id = ConnectProfileToAccount(token.email).account_id;
} else {
@@ -560,7 +565,7 @@ class AccountReconcilorTestTable
identity_test_env()->MakeAccountAvailable(token.email).account_id;
}
if (token.has_error) {
- identity::UpdatePersistentErrorOfRefreshTokenForAccount(
+ signin::UpdatePersistentErrorOfRefreshTokenForAccount(
identity_test_env()->identity_manager(), account_id,
GoogleServiceAuthError(
GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
@@ -686,12 +691,12 @@ std::vector<Cookie> FakeSetAccountsInCookie(
std::vector<Cookie> cookies_after_reconcile;
if (parameters.mode ==
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER) {
- for (const std::string& account : parameters.accounts_to_send) {
+ for (const CoreAccountId& account : parameters.accounts_to_send) {
cookies_after_reconcile.push_back({account, true});
}
} else {
- std::set<std::string> accounts_set;
- for (const std::string& account : parameters.accounts_to_send) {
+ std::set<CoreAccountId> accounts_set;
+ for (const CoreAccountId& account : parameters.accounts_to_send) {
accounts_set.insert(account);
}
cookies_after_reconcile = cookies_before_reconcile;
@@ -703,7 +708,7 @@ std::vector<Cookie> FakeSetAccountsInCookie(
param.is_valid = false;
}
}
- for (const std::string& account : accounts_set) {
+ for (const CoreAccountId& account : accounts_set) {
cookies_after_reconcile.push_back({account, true});
}
}
@@ -731,156 +736,165 @@ const std::vector<AccountReconcilorTestTableParam> kDiceParams = {
// x: The next cookie is marked "invalid".
// - First Run: true if this is the first reconcile (i.e. Chrome startup).
// -------------------------------------------------------------------------
- // Tokens|Cookies|First Run|Gaia calls|Tokens aft.|Cookies aft.|M.calls| M.Tokens aft.| M.Cookies aft.|
+ // Tokens|Cookies|First Run|Gaia calls|Tokens aft.|Cookies aft.|M.calls| M.Tokens aft.| M.Cookies aft.| AccountReconcilorDelegate::InconsistencyReason |
// -------------------------------------------------------------------------
// First reconcile (Chrome restart): Rebuild the Gaia cookie to match the
// tokens. Make the Sync account the default account in the Gaia cookie.
// Sync enabled.
- { "*AB", "AB", IsFirstReconcile::kBoth, "", "*AB", "AB", "", "*AB", "AB"},
+ { "", "A", IsFirstReconcile::kBoth, "X", "", "", "P", "", "xA", 3},
+ { "*AB", "AB", IsFirstReconcile::kBoth, "", "*AB", "AB", "", "*AB", "AB", 0},
+ { "*A", "A", IsFirstReconcile::kBoth, "", "*A", "A", "", "*A" , "A", 0},
+
+ { "*A", "", IsFirstReconcile::kFirst, "A", "*A", "A", "UA", "*A" , "A", 1},
+ { "*A", "", IsFirstReconcile::kNotFirst, "A", "*A", "A", "PA", "*A" , "A", 1},
- { "*AB", "BA", IsFirstReconcile::kFirst, "XAB", "*AB", "AB", "UAB", "*AB", "AB"},
- { "*AB", "BA", IsFirstReconcile::kNotFirst, "", "*AB", "BA", "", "*AB", "BA"},
+ { "*A", "B", IsFirstReconcile::kFirst, "XA", "*A", "A", "UA", "*A" , "A", 1},
+ { "*A", "B", IsFirstReconcile::kNotFirst, "XA", "*A", "A", "PA", "*A" , "xBA", 1},
- { "*AB", "A", IsFirstReconcile::kBoth, "B", "*AB", "AB", "PAB", "*AB", "AB"},
+ { "*A", "AB", IsFirstReconcile::kBoth, "XA", "*A", "A", "PA", "*A" , "AxB", 5},
- { "*AB", "B", IsFirstReconcile::kFirst, "XAB", "*AB", "AB", "UAB", "*AB", "AB"},
- { "*AB", "B", IsFirstReconcile::kNotFirst, "A", "*AB", "BA", "PAB", "*AB", "BA"},
+ { "*AB", "BA", IsFirstReconcile::kFirst, "XAB", "*AB", "AB", "UAB", "*AB", "AB", 7},
+ { "*AB", "BA", IsFirstReconcile::kNotFirst, "", "*AB", "BA", "", "*AB", "BA", 0},
- { "*AB", "", IsFirstReconcile::kFirst, "AB", "*AB", "AB", "UAB", "*AB", "AB"},
- { "*AB", "", IsFirstReconcile::kNotFirst, "AB", "*AB", "AB", "PAB", "*AB", "AB"},
+ { "*AB", "A", IsFirstReconcile::kBoth, "B", "*AB", "AB", "PAB", "*AB", "AB", 4},
+
+ { "*AB", "B", IsFirstReconcile::kFirst, "XAB", "*AB", "AB", "UAB", "*AB", "AB", 1},
+ { "*AB", "B", IsFirstReconcile::kNotFirst, "A", "*AB", "BA", "PAB", "*AB", "BA", 1},
+
+ { "*AB", "", IsFirstReconcile::kFirst, "AB", "*AB", "AB", "UAB", "*AB", "AB", 1},
+ { "*AB", "", IsFirstReconcile::kNotFirst, "AB", "*AB", "AB", "PAB", "*AB", "AB", 1},
// Sync enabled, token error on primary.
- { "*xAB", "AB", IsFirstReconcile::kBoth, "X", "*xA", "" , "PB", "*xAB", "xAB"},
- { "*xAB", "BA", IsFirstReconcile::kBoth, "XB", "*xAB", "B", "PB", "*xAB", "BxA"},
- { "*xAB", "A", IsFirstReconcile::kBoth, "X", "*xA", "" , "PB", "*xAB", "xAB"},
- { "*xAB", "B", IsFirstReconcile::kBoth, "", "*xAB", "B", "", "*xAB", "B" },
- { "*xAB", "", IsFirstReconcile::kBoth, "B", "*xAB", "B", "PB", "*xAB", "B" },
+ { "*xAB", "AB", IsFirstReconcile::kBoth, "X", "*xA", "" , "PB", "*xAB", "xAB", 2},
+ { "*xAB", "BA", IsFirstReconcile::kBoth, "XB", "*xAB", "B", "PB", "*xAB", "BxA", 2},
+ { "*xAB", "A", IsFirstReconcile::kBoth, "X", "*xA", "" , "PB", "*xAB", "xAB", 2},
+ { "*xAB", "B", IsFirstReconcile::kBoth, "", "*xAB", "B", "", "*xAB", "B" , 0},
+ { "*xAB", "", IsFirstReconcile::kBoth, "B", "*xAB", "B", "PB", "*xAB", "B" , 0},
// Sync enabled, token error on secondary.
- { "*AxB", "AB", IsFirstReconcile::kBoth, "XA", "*A", "A", "PA", "*A", "AxB"},
+ { "*AxB", "AB", IsFirstReconcile::kBoth, "XA", "*A", "A", "PA", "*A", "AxB", 5},
- { "*AxB", "BA", IsFirstReconcile::kFirst, "XA", "*A", "A", "UA", "*A", "A" },
- { "*AxB", "BA", IsFirstReconcile::kNotFirst, "XA", "*A", "A", "PA", "*A", "xBA"},
+ { "*AxB", "BA", IsFirstReconcile::kFirst, "XA", "*A", "A", "UA", "*A", "A" , 5},
+ { "*AxB", "BA", IsFirstReconcile::kNotFirst, "XA", "*A", "A", "PA", "*A", "xBA", 5},
- { "*AxB", "A", IsFirstReconcile::kBoth, "", "*A", "A", "", "*A", "A" },
+ { "*AxB", "A", IsFirstReconcile::kBoth, "", "*A", "A", "", "*A", "A" , 0 },
- { "*AxB", "B", IsFirstReconcile::kFirst, "XA", "*A", "A", "UA", "*A", "A" },
- { "*AxB", "B", IsFirstReconcile::kNotFirst, "XA", "*A", "A", "PA", "*A", "xBA"},
+ { "*AxB", "B", IsFirstReconcile::kFirst, "XA", "*A", "A", "UA", "*A", "A" , 1},
+ { "*AxB", "B", IsFirstReconcile::kNotFirst, "XA", "*A", "A", "PA", "*A", "xBA", 1 },
- { "*AxB", "", IsFirstReconcile::kFirst, "A", "*A", "A", "UA", "*A", "A" },
- { "*AxB", "", IsFirstReconcile::kNotFirst, "A", "*A", "A", "PA", "*A", "A"},
+ { "*AxB", "", IsFirstReconcile::kFirst, "A", "*A", "A", "UA", "*A", "A", 1},
+ { "*AxB", "", IsFirstReconcile::kNotFirst, "A", "*A", "A", "PA", "*A", "A", 1},
// Sync enabled, token error on both accounts.
- { "*xAxB", "AB", IsFirstReconcile::kBoth, "X", "*xA", "", "P", "*xA", "xAxB"},
- { "*xAxB", "BA", IsFirstReconcile::kBoth, "X", "*xA", "", "P", "*xA", "xBxA"},
- { "*xAxB", "A", IsFirstReconcile::kBoth, "X", "*xA", "", "P", "*xA", "xA" },
- { "*xAxB", "B", IsFirstReconcile::kBoth, "X", "*xA", "", "P", "*xA", "xB" },
- { "*xAxB", "", IsFirstReconcile::kBoth, "", "*xA", "", "", "*xA", "" },
+ { "*xAxB", "AB", IsFirstReconcile::kBoth, "X", "*xA", "", "P", "*xA", "xAxB", 2},
+ { "*xAxB", "BA", IsFirstReconcile::kBoth, "X", "*xA", "", "P", "*xA", "xBxA", 2},
+ { "*xAxB", "A", IsFirstReconcile::kBoth, "X", "*xA", "", "P", "*xA", "xA", 2},
+ { "*xAxB", "B", IsFirstReconcile::kBoth, "X", "*xA", "", "P", "*xA", "xB", 5},
+ { "*xAxB", "", IsFirstReconcile::kBoth, "", "*xA", "", "", "*xA", "", 0},
// Sync disabled.
- { "AB", "AB", IsFirstReconcile::kBoth, "", "AB", "AB", "", "AB", "AB"},
- { "AB", "BA", IsFirstReconcile::kBoth, "", "AB", "BA", "", "AB", "BA"},
- { "AB", "A", IsFirstReconcile::kBoth, "B", "AB", "AB", "PAB", "AB", "AB"},
- { "AB", "B", IsFirstReconcile::kBoth, "A", "AB", "BA", "PAB", "AB", "BA"},
- { "AB", "", IsFirstReconcile::kBoth, "AB", "AB", "AB", "PAB", "AB", "AB"},
+ { "AB", "AB", IsFirstReconcile::kBoth, "", "AB", "AB", "", "AB", "AB", 0},
+ { "AB", "BA", IsFirstReconcile::kBoth, "", "AB", "BA", "", "AB", "BA", 0},
+ { "AB", "A", IsFirstReconcile::kBoth, "B", "AB", "AB", "PAB", "AB", "AB", 4},
+ { "AB", "B", IsFirstReconcile::kBoth, "A", "AB", "BA", "PAB", "AB", "BA", 4},
+ { "AB", "", IsFirstReconcile::kBoth, "AB", "AB", "AB", "PAB", "AB", "AB", 0},
// Sync disabled, token error on first account.
- { "xAB", "AB", IsFirstReconcile::kFirst, "XB", "B", "B", "PB", "B", "xAB"},
- { "xAB", "AB", IsFirstReconcile::kNotFirst, "X", "", "" , "PB", "B", "xAB"},
+ { "xAB", "AB", IsFirstReconcile::kFirst, "XB", "B", "B", "PB", "B", "xAB", 3},
+ { "xAB", "AB", IsFirstReconcile::kNotFirst, "X", "", "" , "PB", "B", "xAB", 3},
- { "xAB", "BA", IsFirstReconcile::kBoth, "XB", "B", "B", "PB", "B", "BxA"},
+ { "xAB", "BA", IsFirstReconcile::kBoth, "XB", "B", "B", "PB", "B", "BxA", 5},
- { "xAB", "A", IsFirstReconcile::kFirst, "XB", "B", "B", "PB", "B", "xAB"},
- { "xAB", "A", IsFirstReconcile::kNotFirst, "X", "", "" , "PB", "B", "xAB"},
+ { "xAB", "A", IsFirstReconcile::kFirst, "XB", "B", "B", "PB", "B", "xAB", 3},
+ { "xAB", "A", IsFirstReconcile::kNotFirst, "X", "", "" , "PB", "B", "xAB", 3},
- { "xAB", "B", IsFirstReconcile::kBoth, "", "B", "B", "", "B", "B"},
+ { "xAB", "B", IsFirstReconcile::kBoth, "", "B", "B", "", "B", "B", 0},
- { "xAB", "", IsFirstReconcile::kBoth, "B", "B", "B", "PB", "B", "B"},
+ { "xAB", "", IsFirstReconcile::kBoth, "B", "B", "B", "PB", "B", "B", 0},
// Sync disabled, token error on second account .
- { "AxB", "AB", IsFirstReconcile::kBoth, "XA", "A", "A", "PA", "A", "AxB"},
+ { "AxB", "AB", IsFirstReconcile::kBoth, "XA", "A", "A", "PA", "A", "AxB", 5},
- { "AxB", "BA", IsFirstReconcile::kFirst, "XA", "A", "A", "PA", "A", "xBA"},
- { "AxB", "BA", IsFirstReconcile::kNotFirst, "X", "", "" , "PA", "A", "xBA"},
+ { "AxB", "BA", IsFirstReconcile::kFirst, "XA", "A", "A", "PA", "A", "xBA", 3},
+ { "AxB", "BA", IsFirstReconcile::kNotFirst, "X", "", "" , "PA", "A", "xBA", 3},
- { "AxB", "A", IsFirstReconcile::kBoth, "", "A", "A", "", "A", "A"},
+ { "AxB", "A", IsFirstReconcile::kBoth, "", "A", "A", "", "A", "A", 0},
- { "AxB", "B", IsFirstReconcile::kFirst, "XA", "A", "A", "PA", "A", "xBA"},
- { "AxB", "B", IsFirstReconcile::kNotFirst, "X", "", "" , "PA", "A", "xBA"},
+ { "AxB", "B", IsFirstReconcile::kFirst, "XA", "A", "A", "PA", "A", "xBA", 3},
+ { "AxB", "B", IsFirstReconcile::kNotFirst, "X", "", "" , "PA", "A", "xBA", 3},
- { "AxB", "", IsFirstReconcile::kBoth, "A", "A", "A", "PA", "A", "A"},
+ { "AxB", "", IsFirstReconcile::kBoth, "A", "A", "A", "PA", "A", "A", 0},
// Sync disabled, token error on both accounts.
- { "xAxB", "AB", IsFirstReconcile::kBoth, "X", "", "", "P", "", "xAxB"},
- { "xAxB", "BA", IsFirstReconcile::kBoth, "X", "", "", "P", "", "xBxA"},
- { "xAxB", "A", IsFirstReconcile::kBoth, "X", "", "", "P", "", "xA"},
- { "xAxB", "B", IsFirstReconcile::kBoth, "X", "", "", "P", "", "xB"},
- { "xAxB", "", IsFirstReconcile::kBoth, "", "", "", "", "", ""},
+ { "xAxB", "AB", IsFirstReconcile::kBoth, "X", "", "", "P", "", "xAxB", 3},
+ { "xAxB", "BA", IsFirstReconcile::kBoth, "X", "", "", "P", "", "xBxA", 3},
+ { "xAxB", "A", IsFirstReconcile::kBoth, "X", "", "", "P", "", "xA", 3},
+ { "xAxB", "B", IsFirstReconcile::kBoth, "X", "", "", "P", "", "xB", 3},
+ { "xAxB", "", IsFirstReconcile::kBoth, "", "", "", "", "", "", 0},
// Account marked as invalid in cookies.
// No difference between cookies and tokens, do not do do anything.
// Do not logout. Regression tests for http://crbug.com/854799
- { "", "xA", IsFirstReconcile::kBoth, "", "", "xA", "", "", "xA"},
- { "", "xAxB", IsFirstReconcile::kBoth, "", "", "xAxB", "", "", "xAxB"},
- { "xA", "xA", IsFirstReconcile::kBoth, "", "", "xA", "", "", "xA"},
- { "xAB", "xAB", IsFirstReconcile::kBoth, "", "B", "xAB", "", "B", "xAB"},
- { "AxB", "AxC", IsFirstReconcile::kBoth, "", "A", "AxC", "", "A", "AxC"},
- { "B", "xAB", IsFirstReconcile::kBoth, "", "B", "xAB", "", "B", "xAB"},
- { "*xA", "xA", IsFirstReconcile::kBoth, "", "*xA", "xA", "", "*xA", "xA"},
- { "*xA", "xB", IsFirstReconcile::kBoth, "", "*xA", "xB", "", "*xA", "xB"},
- { "*xAB", "xAB", IsFirstReconcile::kBoth, "", "*xAB", "xAB", "", "*xAB", "xAB"},
- { "*AxB", "xBA", IsFirstReconcile::kNotFirst, "", "*A", "xBA", "", "*A", "xBA"},
+ { "", "xA", IsFirstReconcile::kBoth, "", "", "xA", "", "", "xA", 0},
+ { "", "xAxB", IsFirstReconcile::kBoth, "", "", "xAxB", "", "", "xAxB", 0},
+ { "xA", "xA", IsFirstReconcile::kBoth, "", "", "xA", "", "", "xA", 0},
+ { "xAB", "xAB", IsFirstReconcile::kBoth, "", "B", "xAB", "", "B", "xAB", 0},
+ { "AxB", "AxC", IsFirstReconcile::kBoth, "", "A", "AxC", "", "A", "AxC", 0},
+ { "B", "xAB", IsFirstReconcile::kBoth, "", "B", "xAB", "", "B", "xAB", 0},
+ { "*xA", "xA", IsFirstReconcile::kBoth, "", "*xA", "xA", "", "*xA", "xA", 0},
+ { "*xA", "xB", IsFirstReconcile::kBoth, "", "*xA", "xB", "", "*xA", "xB", 0},
+ { "*xAB", "xAB", IsFirstReconcile::kBoth, "", "*xAB", "xAB", "", "*xAB", "xAB", 0},
+ { "*AxB", "xBA", IsFirstReconcile::kNotFirst, "", "*A", "xBA", "", "*A", "xBA", 0},
// Appending a new cookie after the invalid one.
- { "B", "xA", IsFirstReconcile::kBoth, "B", "B", "xAB", "PB", "B", "xAB"},
- { "xAB", "xA", IsFirstReconcile::kBoth, "B", "B", "xAB", "PB", "B", "xAB"},
+ { "B", "xA", IsFirstReconcile::kBoth, "B", "B", "xAB", "PB", "B", "xAB", 4},
+ { "xAB", "xA", IsFirstReconcile::kBoth, "B", "B", "xAB", "PB", "B", "xAB", 4},
// Refresh existing cookies.
- { "AB", "xAB", IsFirstReconcile::kBoth, "A", "AB", "AB", "PAB","AB", "AB"},
- { "*AB", "xBxA", IsFirstReconcile::kNotFirst, "BA", "*AB", "BA", "PAB","*AB", "BA"},
+ { "AB", "xAB", IsFirstReconcile::kBoth, "A", "AB", "AB", "PAB","AB", "AB", 4},
+ { "*AB", "xBxA", IsFirstReconcile::kNotFirst, "BA", "*AB", "BA", "PAB","*AB", "BA", 1},
// Appending and invalidating cookies at the same time.
// Difference should disappear after migrating to Multilogin.
- { "xAB", "xAC", IsFirstReconcile::kFirst, "XB", "B", "B", "PB", "B", "xAxCB"},
- { "xAB", "xAC", IsFirstReconcile::kNotFirst, "X", "", "", "PB", "B", "xAxCB"},
+ { "xAB", "xAC", IsFirstReconcile::kFirst, "XB", "B", "B", "PB", "B", "xAxCB", 6},
+ { "xAB", "xAC", IsFirstReconcile::kNotFirst, "X", "", "", "PB", "B", "xAxCB", 6},
- { "xAB", "AxC", IsFirstReconcile::kFirst, "XB", "B", "B", "PB", "B", "xAxCB"},
- { "xAB", "AxC", IsFirstReconcile::kNotFirst, "X", "", "", "PB", "B", "xAxCB"},
+ { "xAB", "AxC", IsFirstReconcile::kFirst, "XB", "B", "B", "PB", "B", "xAxCB", 3},
+ { "xAB", "AxC", IsFirstReconcile::kNotFirst, "X", "", "", "PB", "B", "xAxCB", 3},
- { "*xAB", "xABC", IsFirstReconcile::kFirst, "XB", "*xAB", "B", "PB", "*xAB", "xABxC"},
- { "*xAB", "xABC", IsFirstReconcile::kNotFirst, "X", "*xA", "", "PB", "*xAB", "xABxC"},
+ { "*xAB", "xABC", IsFirstReconcile::kFirst, "XB", "*xAB", "B", "PB", "*xAB", "xABxC", 5},
+ { "*xAB", "xABC", IsFirstReconcile::kNotFirst, "X", "*xA", "", "PB", "*xAB", "xABxC", 5},
- { "xAB", "xABC", IsFirstReconcile::kFirst, "XB", "B", "B", "PB", "B", "xABxC"},
- { "xAB", "xABC", IsFirstReconcile::kNotFirst, "X", "", "", "PB", "B", "xABxC"},
+ { "xAB", "xABC", IsFirstReconcile::kFirst, "XB", "B", "B", "PB", "B", "xABxC", 5},
+ { "xAB", "xABC", IsFirstReconcile::kNotFirst, "X", "", "", "PB", "B", "xABxC", 5},
// Miscellaneous cases.
// Check that unknown Gaia accounts are signed out.
- { "", "A", IsFirstReconcile::kBoth, "X", "", "", "P", "", "xA"},
- { "*A", "AB", IsFirstReconcile::kBoth, "XA", "*A", "A", "PA", "*A", "AxB"},
+ { "*A", "AB", IsFirstReconcile::kBoth, "XA", "*A", "A", "PA", "*A", "AxB", 5},
// Check that Gaia default account is kept in first position.
- { "AB", "BC", IsFirstReconcile::kBoth, "XBA","AB", "BA", "PAB","AB", "BxCA"},
+ { "AB", "BC", IsFirstReconcile::kBoth, "XBA","AB", "BA", "PAB","AB", "BxCA", 6},
// Check that Gaia cookie order is preserved for B.
- { "*ABC", "CB", IsFirstReconcile::kFirst, "XABC","*ABC", "ABC", "UABC","*ABC","ABC"},
+ { "*ABC", "CB", IsFirstReconcile::kFirst, "XABC","*ABC", "ABC", "UABC","*ABC","ABC", 1},
// Required for idempotency check.
- { "", "", IsFirstReconcile::kNotFirst, "", "", "", "", "", ""},
- { "", "xA", IsFirstReconcile::kNotFirst, "", "", "xA", "", "", "xA"},
- { "", "xB", IsFirstReconcile::kNotFirst, "", "", "xB", "", "", "xB"},
- { "", "xAxB", IsFirstReconcile::kNotFirst, "", "", "xAxB", "", "", "xAxB"},
- { "", "xBxA", IsFirstReconcile::kNotFirst, "", "", "xBxA", "", "", "xBxA"},
- { "*A", "A", IsFirstReconcile::kNotFirst, "", "*A", "A", "", "*A", "A"},
- { "*A", "xBA", IsFirstReconcile::kNotFirst, "", "*A", "xBA", "", "*A", "xBA"},
- { "*A", "AxB", IsFirstReconcile::kNotFirst, "", "*A", "AxB", "", "*A", "AxB"},
- { "A", "A", IsFirstReconcile::kNotFirst, "", "A", "A", "", "A", "A"},
- { "A", "xBA", IsFirstReconcile::kNotFirst, "", "A", "xBA", "", "A", "xBA"},
- { "A", "AxB", IsFirstReconcile::kNotFirst, "", "A", "AxB", "", "A", "AxB"},
- { "B", "B", IsFirstReconcile::kNotFirst, "", "B", "B", "", "B", "B"},
- { "B", "xAB", IsFirstReconcile::kNotFirst, "", "B", "xAB", "", "B", "xAB"},
- { "B", "BxA", IsFirstReconcile::kNotFirst, "", "B", "BxA", "", "B", "BxA"},
- { "*xA", "", IsFirstReconcile::kNotFirst, "", "*xA", "", "", "*xA", ""},
- { "*xA", "xAxB", IsFirstReconcile::kNotFirst, "", "*xA", "xAxB", "", "*xA", "xAxB"},
- { "*xA", "xBxA", IsFirstReconcile::kNotFirst, "", "*xA", "xBxA", "", "*xA", "xBxA"},
- { "*xA", "xA", IsFirstReconcile::kNotFirst, "", "*xA", "xA", "", "*xA", "xA"},
- { "*xA", "xB", IsFirstReconcile::kNotFirst, "", "*xA", "xB", "", "*xA", "xB"},
- { "*xAB", "B", IsFirstReconcile::kNotFirst, "", "*xAB", "B", "", "*xAB", "B"},
- { "*xAB", "BxA", IsFirstReconcile::kNotFirst, "", "*xAB", "BxA", "", "*xAB", "BxA"},
- { "*xAB", "xAB", IsFirstReconcile::kNotFirst, "", "*xAB", "xAB", "", "*xAB", "xAB"},
- { "*xAB", "xABxC",IsFirstReconcile::kNotFirst, "", "*xAB", "xABxC","", "*xAB", "xABxC"},
- { "A", "AxC", IsFirstReconcile::kNotFirst, "", "A", "AxC", "", "A", "AxC"},
- { "AB", "BxCA", IsFirstReconcile::kNotFirst, "", "AB", "BxCA", "", "AB", "BxCA"},
- { "B", "xABxC",IsFirstReconcile::kNotFirst, "", "B", "xABxC","", "B", "xABxC"},
- { "B", "xAxCB",IsFirstReconcile::kNotFirst, "", "B", "xAxCB","", "B", "xAxCB"},
- { "*ABC", "ACB", IsFirstReconcile::kNotFirst, "", "*ABC", "ACB", "", "*ABC", "ACB"},
- { "*ABC", "ABC", IsFirstReconcile::kNotFirst, "", "*ABC", "ABC", "", "*ABC", "ABC"}
+ { "", "", IsFirstReconcile::kNotFirst, "", "", "", "", "", "", 0},
+ { "", "xA", IsFirstReconcile::kNotFirst, "", "", "xA", "", "", "xA", 0},
+ { "", "xB", IsFirstReconcile::kNotFirst, "", "", "xB", "", "", "xB", 0},
+ { "", "xAxB", IsFirstReconcile::kNotFirst, "", "", "xAxB", "", "", "xAxB", 0},
+ { "", "xBxA", IsFirstReconcile::kNotFirst, "", "", "xBxA", "", "", "xBxA", 0},
+ { "*A", "A", IsFirstReconcile::kNotFirst, "", "*A", "A", "", "*A", "A", 0},
+ { "*A", "xBA", IsFirstReconcile::kNotFirst, "", "*A", "xBA", "", "*A", "xBA", 0},
+ { "*A", "AxB", IsFirstReconcile::kNotFirst, "", "*A", "AxB", "", "*A", "AxB", 0},
+ { "A", "A", IsFirstReconcile::kNotFirst, "", "A", "A", "", "A", "A", 0},
+ { "A", "xBA", IsFirstReconcile::kNotFirst, "", "A", "xBA", "", "A", "xBA", 0},
+ { "A", "AxB", IsFirstReconcile::kNotFirst, "", "A", "AxB", "", "A", "AxB", 0},
+ { "B", "B", IsFirstReconcile::kNotFirst, "", "B", "B", "", "B", "B", 0},
+ { "B", "xAB", IsFirstReconcile::kNotFirst, "", "B", "xAB", "", "B", "xAB", 0},
+ { "B", "BxA", IsFirstReconcile::kNotFirst, "", "B", "BxA", "", "B", "BxA", 0},
+ { "*xA", "", IsFirstReconcile::kNotFirst, "", "*xA", "", "", "*xA", "", 0},
+ { "*xA", "xAxB", IsFirstReconcile::kNotFirst, "", "*xA", "xAxB", "", "*xA", "xAxB", 0},
+ { "*xA", "xBxA", IsFirstReconcile::kNotFirst, "", "*xA", "xBxA", "", "*xA", "xBxA", 0},
+ { "*xA", "xA", IsFirstReconcile::kNotFirst, "", "*xA", "xA", "", "*xA", "xA", 0},
+ { "*xA", "xB", IsFirstReconcile::kNotFirst, "", "*xA", "xB", "", "*xA", "xB", 0},
+ { "*xAB", "B", IsFirstReconcile::kNotFirst, "", "*xAB", "B", "", "*xAB", "B", 0},
+ { "*xAB", "BxA", IsFirstReconcile::kNotFirst, "", "*xAB", "BxA", "", "*xAB", "BxA", 0},
+ { "*xAB", "xAB", IsFirstReconcile::kNotFirst, "", "*xAB", "xAB", "", "*xAB", "xAB", 0},
+ { "*xAB", "xABxC",IsFirstReconcile::kNotFirst, "", "*xAB", "xABxC","", "*xAB", "xABxC", 0},
+ { "A", "AxC", IsFirstReconcile::kNotFirst, "", "A", "AxC", "", "A", "AxC", 0},
+ { "AB", "BxCA", IsFirstReconcile::kNotFirst, "", "AB", "BxCA", "", "AB", "BxCA", 0},
+ { "B", "xABxC",IsFirstReconcile::kNotFirst, "", "B", "xABxC","", "B", "xABxC", 0},
+ { "B", "xAxCB",IsFirstReconcile::kNotFirst, "", "B", "xAxCB","", "B", "xAxCB", 0},
+ { "*ABC", "ACB", IsFirstReconcile::kNotFirst, "", "*ABC", "ACB", "", "*ABC", "ACB", 0},
+ { "*ABC", "ABC", IsFirstReconcile::kNotFirst, "", "*ABC", "ABC", "", "*ABC", "ABC", 0}
};
// clang-format on
@@ -893,13 +907,14 @@ TEST_P(AccountReconcilorTestTable, TableRowTest) {
// nothing on the second call.
CheckReconcileIdempotent(kDiceParams, GetParam(), /*multilogin=*/false);
- // Setup tokens.
- SetupTokens();
-
// Setup cookies.
std::vector<Cookie> cookies = ParseCookieString(GetParam().cookies);
ConfigureCookieManagerService(cookies);
+ // Setup tokens. This triggers listing cookies so we need to setup cookies
+ // before that.
+ SetupTokens();
+
// Call list accounts now so that the next call completes synchronously.
identity_test_env()->identity_manager()->GetAccountsInCookieJar();
base::RunLoop().RunUntilIdle();
@@ -916,7 +931,8 @@ TEST_P(AccountReconcilorTestTable, TableRowTest) {
continue;
}
std::string cookie(1, GetParam().gaia_api_calls[i]);
- std::string account_id_for_cookie = GaiaIdForAccountKey(cookie[0]);
+ CoreAccountId account_id_for_cookie = PickAccountIdForAccount(
+ accounts_[cookie[0]].gaia_id, accounts_[cookie[0]].email);
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id_for_cookie))
.Times(1);
// MergeSession fixes an existing cookie or appends it at the end.
@@ -941,12 +957,12 @@ TEST_P(AccountReconcilorTestTable, TableRowTest) {
AccountReconcilor* reconcilor = GetMockReconcilor();
ASSERT_TRUE(reconcilor->first_execution_);
reconcilor->first_execution_ =
- GetParam().is_first_reconcile == IsFirstReconcile::kFirst ? true : false;
+ GetParam().is_first_reconcile == IsFirstReconcile::kFirst;
reconcilor->StartReconcile();
for (int i = 0; GetParam().gaia_api_calls[i] != '\0'; ++i) {
if (GetParam().gaia_api_calls[i] == 'X')
continue;
- std::string account_id =
+ CoreAccountId account_id =
PickAccountIdForAccount(accounts_[GetParam().gaia_api_calls[i]].gaia_id,
accounts_[GetParam().gaia_api_calls[i]].email);
SimulateAddAccountToCookieCompleted(
@@ -977,6 +993,44 @@ TEST_P(AccountReconcilorTestTable, TableRowTest) {
base::RunLoop().RunUntilIdle();
}
+// Checks one row of the kDiceParams table above.
+TEST_P(AccountReconcilorTestTable, InconsistencyReasonLogging) {
+ // Enable Dice Migration.
+ SetAccountConsistency(signin::AccountConsistencyMethod::kDiceMigration);
+ // Setup cookies.
+ std::vector<Cookie> cookies = ParseCookieString(GetParam().cookies);
+ ConfigureCookieManagerService(cookies);
+ // Setup tokens. This triggers listing cookies so we need to setup cookies
+ // before that.
+ SetupTokens();
+ // Call list accounts now so that the next call completes synchronously.
+ identity_test_env()->identity_manager()->GetAccountsInCookieJar();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(testing::_))
+ .WillRepeatedly(testing::Return());
+ EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
+ .WillRepeatedly(testing::Return());
+ // Reconcile.
+ AccountReconcilor* reconcilor = GetMockReconcilor();
+ bool first_execution =
+ GetParam().is_first_reconcile == IsFirstReconcile::kFirst;
+ reconcilor->first_execution_ = first_execution;
+ reconcilor->StartReconcile();
+ reconcilor->add_to_cookie_.clear();
+ reconcilor->CalculateIfReconcileIsDone();
+ ASSERT_FALSE(reconcilor->is_reconcile_started_);
+ std::string histogram_name_suffix =
+ first_execution ? "FirstExecution" : "NotFirstExecution";
+
+ histogram_tester()->ExpectUniqueSample(
+ "Signin.DiceMigrationNotReady.Reason." + histogram_name_suffix,
+ GetParam().inconsistency_reason, 1);
+
+ ConfigureCookieManagerService({});
+ base::RunLoop().RunUntilIdle();
+}
+
INSTANTIATE_TEST_SUITE_P(
DiceTable,
AccountReconcilorTestTable,
@@ -1003,14 +1057,15 @@ TEST_P(AccountReconcilorTestDiceMultilogin, TableRowTest) {
CheckReconcileIdempotent(kDiceParams, GetParam(), /*multilogin=*/true);
- // Setup tokens.
- SetupTokens();
-
// Setup cookies.
std::vector<Cookie> cookies = ParseCookieString(GetParam().cookies);
ConfigureCookieManagerService(cookies);
std::vector<Cookie> cookies_after_reconcile = cookies;
+ // Setup tokens. This triggers listing cookies so we need to setup cookies
+ // before that.
+ SetupTokens();
+
// Call list accounts now so that the next call completes synchronously.
identity_test_env()->identity_manager()->GetAccountsInCookieJar();
base::RunLoop().RunUntilIdle();
@@ -1024,7 +1079,7 @@ TEST_P(AccountReconcilorTestDiceMultilogin, TableRowTest) {
: gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER;
// Generate expected array of accounts in cookies and set fake gaia
// response.
- std::vector<std::string> accounts_to_send;
+ std::vector<CoreAccountId> accounts_to_send;
for (int i = 1; GetParam().gaia_api_calls_multilogin[i] != '\0'; ++i) {
accounts_to_send.push_back(
accounts_[GetParam().gaia_api_calls_multilogin[i]].gaia_id);
@@ -1114,15 +1169,17 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceTokenServiceRegistration) {
// Tests that reconcile starts even when Sync is not enabled.
TEST_P(AccountReconcilorDiceEndpointParamTest, DiceReconcileWithoutSignin) {
- // Add a token in Chrome but do not sign in.
- const std::string account_id =
- identity_test_env()->MakeAccountAvailable("user@gmail.com").account_id;
+ // Add a token in Chrome but do not sign in. Making account available (setting
+ // a refresh token) triggers listing cookies so we need to setup cookies
+ // before that.
signin::SetListAccountsResponseNoAccounts(&test_url_loader_factory_);
+ const CoreAccountId account_id =
+ identity_test_env()->MakeAccountAvailable("user@gmail.com").account_id;
if (!IsMultiloginEnabled()) {
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
} else {
- std::vector<std::string> accounts_to_send = {account_id};
+ std::vector<CoreAccountId> accounts_to_send = {account_id};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -1166,13 +1223,18 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceReconcileNoop) {
// Tests that the first Gaia account is re-used when possible.
TEST_P(AccountReconcilorDiceEndpointParamTest,
DiceReconcileReuseGaiaFirstAccount) {
- // Add accounts 1 and 2 to the token service.
+ // Add account "other" to the Gaia cookie.
+ signin::SetListAccountsResponseTwoAccounts(
+ "other@gmail.com", signin::GetTestGaiaIdForEmail("other@gmail.com"),
+ "foo@gmail.com", "9999", &test_url_loader_factory_);
+
+ // Add accounts "user" and "other" to the token service.
const AccountInfo account_info_1 =
identity_test_env()->MakeAccountAvailable("user@gmail.com");
- const std::string account_id_1 = account_info_1.account_id;
+ const CoreAccountId account_id_1 = account_info_1.account_id;
const AccountInfo account_info_2 =
identity_test_env()->MakeAccountAvailable("other@gmail.com");
- const std::string account_id_2 = account_info_2.account_id;
+ const CoreAccountId account_id_2 = account_info_2.account_id;
auto* identity_manager = identity_test_env()->identity_manager();
std::vector<CoreAccountInfo> accounts =
@@ -1181,11 +1243,6 @@ TEST_P(AccountReconcilorDiceEndpointParamTest,
ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_1));
ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_2));
- // Add account 2 to the Gaia cookie.
- signin::SetListAccountsResponseTwoAccounts(
- account_info_2.email, account_info_2.gaia, "foo@gmail.com", "9999",
- &test_url_loader_factory_);
-
if (!IsMultiloginEnabled()) {
testing::InSequence mock_sequence;
EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
@@ -1193,7 +1250,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest,
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id_2));
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id_1));
} else {
- std::vector<std::string> accounts_to_send = {account_id_2, account_id_1};
+ std::vector<CoreAccountId> accounts_to_send = {account_id_2, account_id_1};
// Send accounts to Gaia in any order, it will determine the order itself in
// PRESERVE order.
const signin::MultiloginParameters params(
@@ -1223,20 +1280,25 @@ TEST_P(AccountReconcilorDiceEndpointParamTest,
// lost.
TEST_P(AccountReconcilorDiceEndpointParamTest, DiceLastKnownFirstAccount) {
// Add accounts to the token service and the Gaia cookie in a different order.
+ // Making account available (setting a refresh token) triggers listing cookies
+ // so we need to setup cookies before that.
+ signin::SetListAccountsResponseTwoAccounts(
+ "other@gmail.com", signin::GetTestGaiaIdForEmail("other@gmail.com"),
+ "user@gmail.com", signin::GetTestGaiaIdForEmail("user@gmail.com"),
+ &test_url_loader_factory_);
+
AccountInfo account_info_1 =
identity_test_env()->MakeAccountAvailable("user@gmail.com");
- const std::string account_id_1 = account_info_1.account_id;
+ const CoreAccountId account_id_1 = account_info_1.account_id;
AccountInfo account_info_2 =
identity_test_env()->MakeAccountAvailable("other@gmail.com");
- const std::string account_id_2 = account_info_2.account_id;
- signin::SetListAccountsResponseTwoAccounts(
- account_info_2.email, account_info_2.gaia, account_info_1.email,
- account_info_1.gaia, &test_url_loader_factory_);
+ const CoreAccountId account_id_2 = account_info_2.account_id;
auto* identity_manager = identity_test_env()->identity_manager();
std::vector<CoreAccountInfo> accounts =
identity_manager->GetAccountsWithRefreshTokens();
ASSERT_EQ(2u, accounts.size());
+
ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_1));
ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_2));
@@ -1274,7 +1336,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceLastKnownFirstAccount) {
} else {
// Since Gaia can't know about cached account, make sure that we reorder
// chrome accounts accordingly even in PRESERVE mode.
- std::vector<std::string> accounts_to_send = {account_id_2, account_id_1};
+ std::vector<CoreAccountId> accounts_to_send = {account_id_2, account_id_1};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -1330,7 +1392,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, UnverifiedAccountMerge) {
&test_url_loader_factory_);
// Add a token to Chrome.
- const std::string chrome_account_id =
+ const CoreAccountId chrome_account_id =
identity_test_env()->MakeAccountAvailable("other@gmail.com").account_id;
if (!IsMultiloginEnabled()) {
@@ -1343,7 +1405,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, UnverifiedAccountMerge) {
} else {
// In PRESERVE mode it is up to Gaia to not delete existing accounts in
// cookies and not sign out unveridied accounts.
- std::vector<std::string> accounts_to_send = {chrome_account_id};
+ std::vector<CoreAccountId> accounts_to_send = {chrome_account_id};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -1371,11 +1433,14 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceMigrationAfterNoop) {
SetAccountConsistency(signin::AccountConsistencyMethod::kDiceMigration);
pref_service()->SetBoolean(prefs::kTokenServiceDiceCompatible, true);
- // Chrome account is consistent with the cookie.
+ // Chrome account is consistent with the cookie. Making account available
+ // (setting a refresh token) triggers listing cookies so we need to setup
+ // cookies before that.
+ signin::SetListAccountsResponseOneAccount(
+ "user@gmail.com", signin::GetTestGaiaIdForEmail("user@gmail.com"),
+ &test_url_loader_factory_);
AccountInfo account_info =
identity_test_env()->MakeAccountAvailable("user@gmail.com");
- signin::SetListAccountsResponseOneAccount(
- account_info.email, account_info.gaia, &test_url_loader_factory_);
AccountReconcilor* reconcilor = GetMockReconcilor();
// Dice is not enabled by default.
EXPECT_FALSE(reconcilor->delegate_->IsAccountConsistencyEnforced());
@@ -1401,11 +1466,14 @@ TEST_P(AccountReconcilorDiceEndpointParamTest,
// Enable Dice migration.
SetAccountConsistency(signin::AccountConsistencyMethod::kDiceMigration);
- // Chrome account is consistent with the cookie.
+ // Chrome account is consistent with the cookie. Making account available
+ // (setting a refresh token) triggers listing cookies so we need to setup
+ // cookies before that.
+ signin::SetListAccountsResponseOneAccount(
+ "user@gmail.com", signin::GetTestGaiaIdForEmail("user@gmail.com"),
+ &test_url_loader_factory_);
AccountInfo account_info =
identity_test_env()->MakeAccountAvailable("user@gmail.com");
- signin::SetListAccountsResponseOneAccount(
- account_info.email, account_info.gaia, &test_url_loader_factory_);
AccountReconcilor* reconcilor = GetMockReconcilor();
// Dice is not enabled by default.
EXPECT_FALSE(reconcilor->delegate_->IsAccountConsistencyEnforced());
@@ -1432,7 +1500,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceNoMigrationAfterReconcile) {
pref_service()->SetBoolean(prefs::kTokenServiceDiceCompatible, true);
// Add a token in Chrome.
- const std::string account_id =
+ const CoreAccountId account_id =
ConnectProfileToAccount("user@gmail.com").account_id;
signin::SetListAccountsResponseNoAccounts(&test_url_loader_factory_);
AccountReconcilor* reconcilor = GetMockReconcilor();
@@ -1472,9 +1540,9 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, MigrationClearSecondaryTokens) {
pref_service()->SetBoolean(prefs::kTokenServiceDiceCompatible, true);
// Add a tokens in Chrome, signin to Sync, but no Gaia cookies.
- const std::string account_id_1 =
+ const CoreAccountId account_id_1 =
ConnectProfileToAccount("user@gmail.com").account_id;
- const std::string account_id_2 =
+ const CoreAccountId account_id_2 =
identity_test_env()->MakeAccountAvailable("other@gmail.com").account_id;
signin::SetListAccountsResponseNoAccounts(&test_url_loader_factory_);
@@ -1487,7 +1555,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, MigrationClearSecondaryTokens) {
if (!IsMultiloginEnabled()) {
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id_1));
} else {
- std::vector<std::string> accounts_to_send = {account_id_1};
+ std::vector<CoreAccountId> accounts_to_send = {account_id_1};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -1522,12 +1590,14 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, MigrationClearAllTokens) {
SetAccountConsistency(signin::AccountConsistencyMethod::kDiceMigration);
pref_service()->SetBoolean(prefs::kTokenServiceDiceCompatible, true);
- // Add a tokens in Chrome but no Gaia cookies.
- const std::string account_id_1 =
+ // Add a tokens in Chrome but no Gaia cookies. Making account available
+ // (setting a refresh token) triggers listing cookies so we need to setup
+ // cookies before that.
+ signin::SetListAccountsResponseNoAccounts(&test_url_loader_factory_);
+ const CoreAccountId account_id_1 =
identity_test_env()->MakeAccountAvailable("user@gmail.com").account_id;
- const std::string account_id_2 =
+ const CoreAccountId account_id_2 =
identity_test_env()->MakeAccountAvailable("other@gmail.com").account_id;
- signin::SetListAccountsResponseNoAccounts(&test_url_loader_factory_);
auto* identity_manager = identity_test_env()->identity_manager();
ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_1));
@@ -1556,11 +1626,11 @@ INSTANTIATE_TEST_SUITE_P(TestDiceEndpoint,
TEST_F(AccountReconcilorTest, DiceDeleteCookie) {
SetAccountConsistency(signin::AccountConsistencyMethod::kDice);
- const std::string primary_account_id =
+ const CoreAccountId primary_account_id =
identity_test_env()
->MakePrimaryAccountAvailable("user@gmail.com")
.account_id;
- const std::string secondary_account_id =
+ const CoreAccountId secondary_account_id =
identity_test_env()->MakeAccountAvailable("other@gmail.com").account_id;
auto* identity_manager = identity_test_env()->identity_manager();
@@ -1611,7 +1681,7 @@ TEST_F(AccountReconcilorTest, DiceDeleteCookie) {
EXPECT_FALSE(
identity_manager->HasAccountWithRefreshTokenInPersistentErrorState(
primary_account_id));
- identity::UpdatePersistentErrorOfRefreshTokenForAccount(
+ signin::UpdatePersistentErrorOfRefreshTokenForAccount(
identity_test_env()->identity_manager(), primary_account_id,
GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
GoogleServiceAuthError::InvalidGaiaCredentialsReason::
@@ -1707,7 +1777,7 @@ TEST_P(AccountReconcilorTestMirrorMultilogin, TableRowTest) {
continue;
}
if (GetParam().gaia_api_calls[i] == 'U') {
- std::vector<std::string> accounts_to_send;
+ std::vector<CoreAccountId> accounts_to_send;
for (int i = 0; GetParam().cookies_after_reconcile[i] != '\0'; ++i) {
char cookie = GetParam().cookies_after_reconcile[i];
std::string account_to_send = GaiaIdForAccountKey(cookie);
@@ -1801,13 +1871,14 @@ TEST_P(AccountReconcilorTestMiceMultilogin, TableRowTest) {
scoped_feature_list_.InitWithFeatures(
{kUseMultiloginEndpoint, signin::kMiceFeature}, {});
- // Setup tokens.
- SetupTokens();
-
// Setup cookies.
std::vector<Cookie> cookies = ParseCookieString(GetParam().cookies);
ConfigureCookieManagerService(cookies);
+ // Setup tokens. This triggers listing cookies so we need to setup cookies
+ // before that.
+ SetupTokens();
+
// Call list accounts now so that the next call completes synchronously.
identity_test_env()->identity_manager()->GetAccountsInCookieJar();
base::RunLoop().RunUntilIdle();
@@ -1824,7 +1895,7 @@ TEST_P(AccountReconcilorTestMiceMultilogin, TableRowTest) {
continue;
}
if (GetParam().gaia_api_calls[i] == 'U') {
- std::vector<std::string> accounts_to_send;
+ std::vector<CoreAccountId> accounts_to_send;
for (int i = 0; GetParam().cookies_after_reconcile[i] != '\0'; ++i) {
char cookie = GetParam().cookies_after_reconcile[i];
std::string account_to_send = GaiaIdForAccountKey(cookie);
@@ -1949,7 +2020,7 @@ TEST_F(AccountReconcilorMiceTest, AccountReconcilorStateScheduled) {
// Tests that reconcile cannot start before the tokens are loaded, and is
// automatically started when tokens are loaded.
TEST_P(AccountReconcilorMirrorEndpointParamTest, TokensNotLoaded) {
- const std::string account_id =
+ const CoreAccountId account_id =
ConnectProfileToAccount("user@gmail.com").account_id;
signin::SetListAccountsResponseNoAccounts(&test_url_loader_factory_);
identity_test_env()->ResetToAccountsNotYetLoadedFromDiskState();
@@ -1957,18 +2028,15 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, TokensNotLoaded) {
AccountReconcilor* reconcilor = GetMockReconcilor();
reconcilor->StartReconcile();
-#if !defined(OS_CHROMEOS)
- // No reconcile when tokens are not loaded, except on ChromeOS where reconcile
- // can start as long as the token service is not empty.
+ // No reconcile when tokens are not loaded.
ASSERT_FALSE(reconcilor->is_reconcile_started_);
// When tokens are loaded, reconcile starts automatically.
identity_test_env()->ReloadAccountsFromDisk();
-#endif
if (!IsMultiloginEnabled()) {
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
} else {
- std::vector<std::string> accounts_to_send = {account_id};
+ std::vector<CoreAccountId> accounts_to_send = {account_id};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -1989,7 +2057,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, TokensNotLoaded) {
TEST_P(AccountReconcilorMirrorEndpointParamTest, GetAccountsFromCookieSuccess) {
AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
- const std::string account_id = account_info.account_id;
+ const CoreAccountId account_id = account_info.account_id;
signin::SetListAccountsResponseOneAccountWithParams(
{account_info.email, account_info.gaia, false /* valid */,
false /* signed_out */, true /* verified */},
@@ -1998,7 +2066,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, GetAccountsFromCookieSuccess) {
if (!IsMultiloginEnabled()) {
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
} else {
- std::vector<std::string> accounts_to_send = {account_id};
+ std::vector<CoreAccountId> accounts_to_send = {account_id};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -2015,7 +2083,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, GetAccountsFromCookieSuccess) {
base::RunLoop().RunUntilIdle();
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_RUNNING, reconcilor->GetState());
- identity::AccountsInCookieJarInfo accounts_in_cookie_jar_info =
+ signin::AccountsInCookieJarInfo accounts_in_cookie_jar_info =
identity_test_env()->identity_manager()->GetAccountsInCookieJar();
ASSERT_TRUE(accounts_in_cookie_jar_info.accounts_are_fresh);
ASSERT_EQ(1u, accounts_in_cookie_jar_info.signed_in_accounts.size());
@@ -2025,7 +2093,8 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, GetAccountsFromCookieSuccess) {
TEST_P(AccountReconcilorMirrorEndpointParamTest, GetAccountsFromCookieFailure) {
ConnectProfileToAccount("user@gmail.com");
- signin::SetListAccountsResponseWebLoginRequired(&test_url_loader_factory_);
+ signin::SetListAccountsResponseWithUnexpectedServiceResponse(
+ &test_url_loader_factory_);
AccountReconcilor* reconcilor = GetMockReconcilor();
ASSERT_TRUE(reconcilor);
@@ -2036,11 +2105,14 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, GetAccountsFromCookieFailure) {
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_RUNNING, reconcilor->GetState());
base::RunLoop().RunUntilIdle();
- identity::AccountsInCookieJarInfo accounts_in_cookie_jar_info =
+ signin::AccountsInCookieJarInfo accounts_in_cookie_jar_info =
identity_test_env()->identity_manager()->GetAccountsInCookieJar();
ASSERT_FALSE(accounts_in_cookie_jar_info.accounts_are_fresh);
ASSERT_EQ(0u, accounts_in_cookie_jar_info.signed_in_accounts.size());
ASSERT_EQ(0u, accounts_in_cookie_jar_info.signed_out_accounts.size());
+ // List accounts retries once on |UNEXPECTED_SERVICE_RESPONSE| errors with
+ // backoff protection.
+ task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(2));
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_ERROR, reconcilor->GetState());
}
@@ -2048,7 +2120,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, GetAccountsFromCookieFailure) {
TEST_P(AccountReconcilorMirrorEndpointParamTest,
ExtraCookieChangeNotification) {
AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
- const std::string account_id = account_info.account_id;
+ const CoreAccountId account_id = account_info.account_id;
signin::CookieParams cookie_params = {
account_info.email, account_info.gaia, false /* valid */,
false /* signed_out */, true /* verified */};
@@ -2059,7 +2131,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
if (!IsMultiloginEnabled()) {
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
} else {
- std::vector<std::string> accounts_to_send = {account_id};
+ std::vector<CoreAccountId> accounts_to_send = {account_id};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -2077,7 +2149,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
// Add extra cookie change notification. Reconcilor should ignore it.
gaia::ListedAccount listed_account =
ListedAccountFromCookieParams(cookie_params, account_id);
- identity::AccountsInCookieJarInfo accounts_in_cookie_jar_info = {
+ signin::AccountsInCookieJarInfo accounts_in_cookie_jar_info = {
/*accounts_are_fresh=*/true, {listed_account}, {}};
reconcilor->OnAccountsInCookieUpdated(
accounts_in_cookie_jar_info, GoogleServiceAuthError::AuthErrorNone());
@@ -2121,7 +2193,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileNoop) {
TEST_P(AccountReconcilorMirrorEndpointParamTest,
StartReconcileCookiesDisabled) {
- const std::string account_id =
+ const CoreAccountId account_id =
ConnectProfileToAccount("user@gmail.com").account_id;
identity_test_env()->SetRefreshTokenForAccount(account_id);
test_signin_client()->set_are_signin_cookies_allowed(false);
@@ -2135,7 +2207,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
base::RunLoop().RunUntilIdle();
std::vector<gaia::ListedAccount> accounts;
// This will be the first call to ListAccounts.
- identity::AccountsInCookieJarInfo accounts_in_cookie_jar_info =
+ signin::AccountsInCookieJarInfo accounts_in_cookie_jar_info =
identity_test_env()->identity_manager()->GetAccountsInCookieJar();
ASSERT_FALSE(accounts_in_cookie_jar_info.accounts_are_fresh);
ASSERT_FALSE(reconcilor->is_reconcile_started_);
@@ -2143,7 +2215,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
TEST_P(AccountReconcilorMirrorEndpointParamTest,
StartReconcileContentSettings) {
- const std::string account_id =
+ const CoreAccountId account_id =
ConnectProfileToAccount("user@gmail.com").account_id;
identity_test_env()->SetRefreshTokenForAccount(account_id);
@@ -2163,7 +2235,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
TEST_P(AccountReconcilorMirrorEndpointParamTest,
StartReconcileContentSettingsGaiaUrl) {
- const std::string account_id =
+ const CoreAccountId account_id =
ConnectProfileToAccount("user@gmail.com").account_id;
identity_test_env()->SetRefreshTokenForAccount(account_id);
@@ -2178,7 +2250,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
TEST_P(AccountReconcilorMirrorEndpointParamTest,
StartReconcileContentSettingsNonGaiaUrl) {
- const std::string account_id =
+ const CoreAccountId account_id =
ConnectProfileToAccount("user@gmail.com").account_id;
identity_test_env()->SetRefreshTokenForAccount(account_id);
@@ -2193,7 +2265,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
TEST_P(AccountReconcilorMirrorEndpointParamTest,
StartReconcileContentSettingsInvalidPattern) {
- const std::string account_id =
+ const CoreAccountId account_id =
ConnectProfileToAccount("user@gmail.com").account_id;
identity_test_env()->SetRefreshTokenForAccount(account_id);
@@ -2209,17 +2281,16 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
}
// This test is needed until chrome changes to use gaia obfuscated id.
-// The signin manager and token service use the gaia "email" property, which
-// preserves dots in usernames and preserves case. gaia::ParseListAccountsData()
-// however uses gaia "displayEmail" which does not preserve case, and then
-// passes the string through gaia::CanonicalizeEmail() which removes dots. This
-// tests makes sure that an email like "Dot.S@hmail.com", as seen by the
-// token service, will be considered the same as "dots@gmail.com" as returned
-// by gaia::ParseListAccountsData().
+// The primary account manager and token service use the gaia "email" property,
+// which preserves dots in usernames and preserves case.
+// gaia::ParseListAccountsData() however uses gaia "displayEmail" which does not
+// preserve case, and then passes the string through gaia::CanonicalizeEmail()
+// which removes dots. This tests makes sure that an email like
+// "Dot.S@hmail.com", as seen by the token service, will be considered the same
+// as "dots@gmail.com" as returned by gaia::ParseListAccountsData().
TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileNoopWithDots) {
if (identity_test_env()->identity_manager()->GetAccountIdMigrationState() !=
- identity::IdentityManager::AccountIdMigrationState::
- MIGRATION_NOT_STARTED) {
+ signin::IdentityManager::AccountIdMigrationState::MIGRATION_NOT_STARTED) {
return;
}
@@ -2266,18 +2337,18 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileNoopMultiple) {
TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileAddToCookie) {
AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
- const std::string account_id = account_info.account_id;
+ const CoreAccountId account_id = account_info.account_id;
identity_test_env()->SetRefreshTokenForAccount(account_id);
signin::SetListAccountsResponseOneAccount(
account_info.email, account_info.gaia, &test_url_loader_factory_);
- const std::string account_id2 =
+ const CoreAccountId account_id2 =
identity_test_env()->MakeAccountAvailable("other@gmail.com").account_id;
if (!IsMultiloginEnabled()) {
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2));
} else {
- std::vector<std::string> accounts_to_send = {account_id, account_id2};
+ std::vector<CoreAccountId> accounts_to_send = {account_id, account_id2};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -2316,10 +2387,10 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileAddToCookie) {
}
TEST_F(AccountReconcilorTest, AuthErrorTriggersListAccount) {
- class TestGaiaCookieObserver : public identity::IdentityManager::Observer {
+ class TestGaiaCookieObserver : public signin::IdentityManager::Observer {
public:
void OnAccountsInCookieUpdated(
- const identity::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+ const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
const GoogleServiceAuthError& error) override {
cookies_updated_ = true;
}
@@ -2339,7 +2410,7 @@ TEST_F(AccountReconcilorTest, AuthErrorTriggersListAccount) {
// Add one account to Chrome and instantiate the reconcilor.
AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
- const std::string account_id = account_info.account_id;
+ const CoreAccountId account_id = account_info.account_id;
identity_test_env()->SetRefreshTokenForAccount(account_id);
TestGaiaCookieObserver observer;
identity_test_env()->identity_manager()->AddObserver(&observer);
@@ -2355,7 +2426,7 @@ TEST_F(AccountReconcilorTest, AuthErrorTriggersListAccount) {
// Set an authentication error.
ASSERT_FALSE(observer.cookies_updated_);
- identity::UpdatePersistentErrorOfRefreshTokenForAccount(
+ signin::UpdatePersistentErrorOfRefreshTokenForAccount(
identity_test_env()->identity_manager(), account_id,
GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
GoogleServiceAuthError::InvalidGaiaCredentialsReason::
@@ -2376,18 +2447,18 @@ TEST_F(AccountReconcilorTest, AuthErrorTriggersListAccount) {
TEST_P(AccountReconcilorMirrorEndpointParamTest,
SignoutAfterErrorDoesNotRecordUma) {
AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
- const std::string account_id = account_info.account_id;
+ const CoreAccountId account_id = account_info.account_id;
identity_test_env()->SetRefreshTokenForAccount(account_id);
signin::SetListAccountsResponseOneAccount(
account_info.email, account_info.gaia, &test_url_loader_factory_);
- const std::string account_id2 =
+ const CoreAccountId account_id2 =
identity_test_env()->MakeAccountAvailable("other@gmail.com").account_id;
if (!IsMultiloginEnabled()) {
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2));
} else {
- std::vector<std::string> accounts_to_send = {account_id, account_id2};
+ std::vector<CoreAccountId> accounts_to_send = {account_id, account_id2};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -2427,7 +2498,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
TEST_P(AccountReconcilorMirrorEndpointParamTest,
StartReconcileRemoveFromCookie) {
AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
- const std::string account_id = account_info.account_id;
+ const CoreAccountId account_id = account_info.account_id;
identity_test_env()->SetRefreshTokenForAccount(account_id);
signin::SetListAccountsResponseTwoAccounts(
account_info.email, account_info.gaia, "other@gmail.com", "12345",
@@ -2437,7 +2508,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
} else {
- std::vector<std::string> accounts_to_send = {account_id};
+ std::vector<CoreAccountId> accounts_to_send = {account_id};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -2473,7 +2544,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
// Check that reconcile is aborted if there is token error on primary account.
TEST_P(AccountReconcilorMirrorEndpointParamTest, TokenErrorOnPrimary) {
AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
- identity::UpdatePersistentErrorOfRefreshTokenForAccount(
+ signin::UpdatePersistentErrorOfRefreshTokenForAccount(
identity_test_env()->identity_manager(), account_info.account_id,
GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
@@ -2491,14 +2562,14 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, TokenErrorOnPrimary) {
TEST_P(AccountReconcilorMirrorEndpointParamTest,
StartReconcileAddToCookieTwice) {
AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
- const std::string account_id = account_info.account_id;
+ const CoreAccountId account_id = account_info.account_id;
AccountInfo account_info2 =
identity_test_env()->MakeAccountAvailable("other@gmail.com");
- const std::string account_id2 = account_info2.account_id;
+ const CoreAccountId account_id2 = account_info2.account_id;
const std::string email3 = "third@gmail.com";
- const std::string gaia_id3 = identity::GetTestGaiaIdForEmail(email3);
- const std::string account_id3 = PickAccountIdForAccount(gaia_id3, email3);
+ const std::string gaia_id3 = signin::GetTestGaiaIdForEmail(email3);
+ const CoreAccountId account_id3 = PickAccountIdForAccount(gaia_id3, email3);
signin::SetListAccountsResponseOneAccount(
account_info.email, account_info.gaia, &test_url_loader_factory_);
@@ -2507,7 +2578,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2));
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id3));
} else {
- std::vector<std::string> accounts_to_send = {account_id, account_id2};
+ std::vector<CoreAccountId> accounts_to_send = {account_id, account_id2};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -2547,8 +2618,8 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
// This will cause the reconcilor to fire.
identity_test_env()->MakeAccountAvailable(email3);
if (IsMultiloginEnabled()) {
- std::vector<std::string> accounts_to_send = {account_id, account_id2,
- account_id3};
+ std::vector<CoreAccountId> accounts_to_send = {account_id, account_id2,
+ account_id3};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -2586,11 +2657,11 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileBadPrimary) {
AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
- const std::string account_id = account_info.account_id;
+ const CoreAccountId account_id = account_info.account_id;
AccountInfo account_info2 =
identity_test_env()->MakeAccountAvailable("other@gmail.com");
- const std::string account_id2 = account_info2.account_id;
+ const CoreAccountId account_id2 = account_info2.account_id;
signin::SetListAccountsResponseTwoAccounts(
account_info2.email, account_info2.gaia, account_info.email,
account_info.gaia, &test_url_loader_factory_);
@@ -2600,7 +2671,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileBadPrimary) {
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2));
} else {
- std::vector<std::string> accounts_to_send = {account_id, account_id2};
+ std::vector<CoreAccountId> accounts_to_send = {account_id, account_id2};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -2731,10 +2802,10 @@ TEST_P(AccountReconcilorMethodParamTest,
StartReconcileWithSessionInfoExpiredDefault) {
SetAccountConsistency(GetParam());
AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
- const std::string account_id = account_info.account_id;
+ const CoreAccountId account_id = account_info.account_id;
AccountInfo account_info2 =
identity_test_env()->MakeAccountAvailable("other@gmail.com");
- const std::string account_id2 = account_info2.account_id;
+ const CoreAccountId account_id2 = account_info2.account_id;
signin::SetListAccountsResponseWithParams(
{{account_info.email, account_info.gaia, false /* valid */,
false /* signed_out */, true /* verified */},
@@ -2774,7 +2845,7 @@ TEST_P(AccountReconcilorMethodParamTest, AccountReconcilorStateScheduled) {
AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
AccountInfo account_info2 =
identity_test_env()->MakeAccountAvailable("other@gmail.com");
- const std::string account_id2 = account_info2.account_id;
+ const CoreAccountId account_id2 = account_info2.account_id;
signin::SetListAccountsResponseOneAccount(
account_info.email, account_info.gaia, &test_url_loader_factory_);
@@ -2837,7 +2908,7 @@ TEST_P(AccountReconcilorMethodParamTest, AccountReconcilorStateScheduled) {
TEST_P(AccountReconcilorMirrorEndpointParamTest,
AddAccountToCookieCompletedWithBogusAccount) {
AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
- const std::string account_id = account_info.account_id;
+ const CoreAccountId account_id = account_info.account_id;
signin::SetListAccountsResponseOneAccountWithParams(
{account_info.email, account_info.gaia, false /* valid */,
false /* signed_out */, true /* verified */},
@@ -2846,7 +2917,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
if (!IsMultiloginEnabled()) {
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
} else {
- std::vector<std::string> accounts_to_send = {account_id};
+ std::vector<CoreAccountId> accounts_to_send = {account_id};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -2877,17 +2948,17 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
TEST_P(AccountReconcilorMirrorEndpointParamTest, NoLoopWithBadPrimary) {
// Connect profile to a primary account and then add a secondary account.
AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
- const std::string account_id1 = account_info.account_id;
+ const CoreAccountId account_id1 = account_info.account_id;
AccountInfo account_info2 =
identity_test_env()->MakeAccountAvailable("other@gmail.com");
- const std::string account_id2 = account_info2.account_id;
+ const CoreAccountId account_id2 = account_info2.account_id;
if (!IsMultiloginEnabled()) {
EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id1));
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2));
} else {
- std::vector<std::string> accounts_to_send = {account_id1, account_id2};
+ std::vector<CoreAccountId> accounts_to_send = {account_id1, account_id2};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -2926,7 +2997,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, NoLoopWithBadPrimary) {
// Now that we've tried once, the token service knows that the primary
// account has an auth error.
- identity::UpdatePersistentErrorOfRefreshTokenForAccount(
+ signin::UpdatePersistentErrorOfRefreshTokenForAccount(
identity_test_env()->identity_manager(), account_id1, error);
// A second attempt to reconcile should be a noop.
@@ -2938,13 +3009,13 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, NoLoopWithBadPrimary) {
TEST_P(AccountReconcilorMirrorEndpointParamTest, WontMergeAccountsWithError) {
// Connect profile to a primary account and then add a secondary account.
- const std::string account_id1 =
+ const CoreAccountId account_id1 =
ConnectProfileToAccount("user@gmail.com").account_id;
- const std::string account_id2 =
+ const CoreAccountId account_id2 =
identity_test_env()->MakeAccountAvailable("other@gmail.com").account_id;
// Mark the secondary account in auth error state.
- identity::UpdatePersistentErrorOfRefreshTokenForAccount(
+ signin::UpdatePersistentErrorOfRefreshTokenForAccount(
identity_test_env()->identity_manager(), account_id2,
GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
@@ -2957,7 +3028,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, WontMergeAccountsWithError) {
if (!IsMultiloginEnabled()) {
EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id1));
} else {
- std::vector<std::string> accounts_to_send = {account_id1};
+ std::vector<CoreAccountId> accounts_to_send = {account_id1};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
@@ -3073,16 +3144,16 @@ TEST_F(AccountReconcilorTest, MultiloginLogout) {
class MultiloginLogoutDelegate : public signin::AccountReconcilorDelegate {
bool IsReconcileEnabled() const override { return true; }
bool IsAccountConsistencyEnforced() const override { return true; }
- std::vector<std::string> GetChromeAccountsForReconcile(
- const std::vector<std::string>& chrome_accounts,
- const std::string& primary_account,
+ std::vector<CoreAccountId> GetChromeAccountsForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const CoreAccountId& primary_account,
const std::vector<gaia::ListedAccount>& gaia_accounts,
const gaia::MultiloginMode mode) const override {
return {};
}
gaia::MultiloginMode CalculateModeForReconcile(
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool primary_has_error) const override {
return gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER;
diff --git a/chromium/components/signin/core/browser/android/BUILD.gn b/chromium/components/signin/core/browser/android/BUILD.gn
index 52d54b20fdb..faf53256b5f 100644
--- a/chromium/components/signin/core/browser/android/BUILD.gn
+++ b/chromium/components/signin/core/browser/android/BUILD.gn
@@ -11,7 +11,6 @@ generate_jni("jni_headers") {
"java/src/org/chromium/components/signin/ConsistencyCookieManager.java",
"java/src/org/chromium/components/signin/OAuth2TokenService.java",
]
- jni_package = "components/signin"
}
android_library("java") {
diff --git a/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountIdProvider.java b/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountIdProvider.java
index 192ea3184e8..a56464df0ff 100644
--- a/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountIdProvider.java
+++ b/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountIdProvider.java
@@ -55,7 +55,7 @@ public class AccountIdProvider {
*/
public boolean canBeUsed() {
// TODO(http://crbug.com/577190): Remove StrictMode override.
- try (StrictModeContext unused = StrictModeContext.allowDiskWrites()) {
+ try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {
int resultCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(
ContextUtils.getApplicationContext());
return resultCode == ConnectionResult.SUCCESS;
diff --git a/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java b/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java
index c05c650293f..375737023a8 100644
--- a/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java
+++ b/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java
@@ -11,7 +11,6 @@ import android.text.TextUtils;
import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
-import org.chromium.base.ObserverList;
import org.chromium.base.StrictModeContext;
import org.chromium.base.ThreadUtils;
import org.chromium.base.VisibleForTesting;
@@ -60,21 +59,10 @@ public final class OAuth2TokenService
void onGetTokenFailure(boolean isTransientError);
}
- /**
- * Classes that want to listen for refresh token availability should
- * implement this interface and register with {@link #addObserver}.
- */
- public interface OAuth2TokenServiceObserver {
- void onRefreshTokenAvailable(Account account);
- void onRefreshTokenRevoked(Account account);
- void onRefreshTokensLoaded();
- }
-
private static final String OAUTH2_SCOPE_PREFIX = "oauth2:";
private final long mNativeOAuth2TokenServiceDelegate;
private final AccountTrackerService mAccountTrackerService;
- private final ObserverList<OAuth2TokenServiceObserver> mObservers = new ObserverList<>();
private boolean mPendingUpdate;
@@ -93,18 +81,6 @@ public final class OAuth2TokenService
return new OAuth2TokenService(nativeOAuth2TokenServiceDelegate, accountTrackerService);
}
- @VisibleForTesting
- public void addObserver(OAuth2TokenServiceObserver observer) {
- ThreadUtils.assertOnUiThread();
- mObservers.addObserver(observer);
- }
-
- @VisibleForTesting
- public void removeObserver(OAuth2TokenServiceObserver observer) {
- ThreadUtils.assertOnUiThread();
- mObservers.removeObserver(observer);
- }
-
private static Account getAccountOrNullFromUsername(String username) {
if (username == null) {
Log.e(TAG, "Username is null");
@@ -128,7 +104,7 @@ public final class OAuth2TokenService
public static String[] getSystemAccountNames() {
// TODO(https://crbug.com/768366): Remove this after adding cache to account manager facade.
// This function is called by native code on UI thread.
- try (StrictModeContext unused = StrictModeContext.allowDiskReads()) {
+ try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
List<String> accountNames = AccountManagerFacade.get().tryGetGoogleAccountNames();
return accountNames.toArray(new String[accountNames.size()]);
}
@@ -265,7 +241,7 @@ public final class OAuth2TokenService
// Temporarily allowing disk read while fixing. TODO: http://crbug.com/618096.
// This function is called in RefreshTokenIsAvailable of OAuth2TokenService which is
// expected to be called in the UI thread synchronously.
- try (StrictModeContext unused = StrictModeContext.allowDiskReads()) {
+ try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
return AccountManagerFacade.get().hasAccountForName(accountName);
}
}
@@ -316,31 +292,6 @@ public final class OAuth2TokenService
return true;
}
- @CalledByNative
- private void notifyRefreshTokenAvailable(String accountName) {
- assert accountName != null;
- Account account = AccountManagerFacade.createAccountFromName(accountName);
- for (OAuth2TokenServiceObserver observer : mObservers) {
- observer.onRefreshTokenAvailable(account);
- }
- }
-
- @CalledByNative
- public void notifyRefreshTokenRevoked(String accountName) {
- assert accountName != null;
- Account account = AccountManagerFacade.createAccountFromName(accountName);
- for (OAuth2TokenServiceObserver observer : mObservers) {
- observer.onRefreshTokenRevoked(account);
- }
- }
-
- @CalledByNative
- public void notifyRefreshTokensLoaded() {
- for (OAuth2TokenServiceObserver observer : mObservers) {
- observer.onRefreshTokensLoaded();
- }
- }
-
private static String[] getStoredAccounts() {
Set<String> accounts =
ContextUtils.getAppSharedPreferences().getStringSet(STORED_ACCOUNTS_KEY, null);
diff --git a/chromium/components/signin/core/browser/chrome_connected_header_helper.cc b/chromium/components/signin/core/browser/chrome_connected_header_helper.cc
index 142c31bef94..6909815553f 100644
--- a/chromium/components/signin/core/browser/chrome_connected_header_helper.cc
+++ b/chromium/components/signin/core/browser/chrome_connected_header_helper.cc
@@ -53,7 +53,7 @@ GAIAServiceType GetGAIAServiceTypeFromHeader(const std::string& header_value) {
ChromeConnectedHeaderHelper::ChromeConnectedHeaderHelper(
AccountConsistencyMethod account_consistency)
- : SigninHeaderHelper("Mirror"), account_consistency_(account_consistency) {}
+ : account_consistency_(account_consistency) {}
// static
std::string ChromeConnectedHeaderHelper::BuildRequestCookieIfPossible(
diff --git a/chromium/components/signin/core/browser/chrome_connected_header_helper.h b/chromium/components/signin/core/browser/chrome_connected_header_helper.h
index 606056243b2..81831b2b392 100644
--- a/chromium/components/signin/core/browser/chrome_connected_header_helper.h
+++ b/chromium/components/signin/core/browser/chrome_connected_header_helper.h
@@ -7,8 +7,8 @@
#include <string>
-#include "components/signin/core/browser/account_consistency_method.h"
#include "components/signin/core/browser/signin_header_helper.h"
+#include "components/signin/public/base/account_consistency_method.h"
class GURL;
diff --git a/chromium/components/signin/core/browser/consistency_cookie_manager_android.cc b/chromium/components/signin/core/browser/consistency_cookie_manager_android.cc
index 97f4ae6f5f6..5b044244d8f 100644
--- a/chromium/components/signin/core/browser/consistency_cookie_manager_android.cc
+++ b/chromium/components/signin/core/browser/consistency_cookie_manager_android.cc
@@ -4,13 +4,13 @@
#include "components/signin/core/browser/consistency_cookie_manager_android.h"
-#include "jni/ConsistencyCookieManager_jni.h"
-#include "services/identity/public/cpp/identity_manager.h"
+#include "components/signin/core/browser/android/jni_headers/ConsistencyCookieManager_jni.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
namespace signin {
ConsistencyCookieManagerAndroid::ConsistencyCookieManagerAndroid(
- identity::IdentityManager* identity_manager,
+ IdentityManager* identity_manager,
SigninClient* signin_client,
AccountReconcilor* reconcilor)
: ConsistencyCookieManagerBase(signin_client, reconcilor) {
diff --git a/chromium/components/signin/core/browser/consistency_cookie_manager_android.h b/chromium/components/signin/core/browser/consistency_cookie_manager_android.h
index ab2b7af1d6b..093b8898262 100644
--- a/chromium/components/signin/core/browser/consistency_cookie_manager_android.h
+++ b/chromium/components/signin/core/browser/consistency_cookie_manager_android.h
@@ -9,19 +9,17 @@
#include "base/macros.h"
#include "components/signin/core/browser/consistency_cookie_manager_base.h"
-namespace identity {
-class IdentityManager;
-}
-
class SigninClient;
namespace signin {
+class IdentityManager;
+
// ConsistencyCookieManagerAndroid subclasses ConsistencyCookieManagerBase to
// watch whether there are pending updates to the account list on the Java side.
class ConsistencyCookieManagerAndroid : public ConsistencyCookieManagerBase {
public:
- ConsistencyCookieManagerAndroid(identity::IdentityManager* identity_manager,
+ ConsistencyCookieManagerAndroid(IdentityManager* identity_manager,
SigninClient* signin_client,
AccountReconcilor* reconcilor);
diff --git a/chromium/components/signin/core/browser/consistency_cookie_manager_base.cc b/chromium/components/signin/core/browser/consistency_cookie_manager_base.cc
index c428f6e06c0..92dee2a07bc 100644
--- a/chromium/components/signin/core/browser/consistency_cookie_manager_base.cc
+++ b/chromium/components/signin/core/browser/consistency_cookie_manager_base.cc
@@ -6,7 +6,7 @@
#include "base/logging.h"
#include "base/time/time.h"
-#include "components/signin/core/browser/signin_client.h"
+#include "components/signin/public/base/signin_client.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_options.h"
@@ -70,9 +70,13 @@ void ConsistencyCookieManagerBase::UpdateCookie() {
kCookieName, cookie_value, GaiaUrls::GetInstance()->gaia_url().host(),
/*path=*/"/", /*creation=*/now, /*expiration=*/expiry,
/*last_access=*/now, /*secure=*/true, /*httponly=*/false,
- net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_DEFAULT);
+ net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_DEFAULT);
+ net::CookieOptions cookie_options;
+ // Permit to set SameSite cookies.
+ cookie_options.set_same_site_cookie_context(
+ net::CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
cookie_manager->SetCanonicalCookie(
- cookie, "https", net::CookieOptions(),
+ cookie, "https", cookie_options,
network::mojom::CookieManager::SetCanonicalCookieCallback());
}
diff --git a/chromium/components/signin/core/browser/consistency_cookie_manager_base.h b/chromium/components/signin/core/browser/consistency_cookie_manager_base.h
index 634086956e9..7c1d551c4c0 100644
--- a/chromium/components/signin/core/browser/consistency_cookie_manager_base.h
+++ b/chromium/components/signin/core/browser/consistency_cookie_manager_base.h
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "base/scoped_observer.h"
#include "components/signin/core/browser/account_reconcilor.h"
-#include "components/signin/core/browser/signin_metrics.h"
+#include "components/signin/public/base/signin_metrics.h"
class SigninClient;
diff --git a/chromium/components/signin/core/browser/consistency_cookie_manager_unittest.cc b/chromium/components/signin/core/browser/consistency_cookie_manager_unittest.cc
index 168581b1bac..5023f2c213f 100644
--- a/chromium/components/signin/core/browser/consistency_cookie_manager_unittest.cc
+++ b/chromium/components/signin/core/browser/consistency_cookie_manager_unittest.cc
@@ -9,13 +9,13 @@
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
-#include "components/signin/core/browser/account_consistency_method.h"
#include "components/signin/core/browser/account_reconcilor.h"
#include "components/signin/core/browser/account_reconcilor_delegate.h"
-#include "components/signin/core/browser/test_signin_client.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/base/test_signin_client.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "google_apis/gaia/gaia_urls.h"
-#include "services/identity/public/cpp/identity_test_environment.h"
#include "services/network/test/test_cookie_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -25,12 +25,22 @@ namespace {
// GMock matcher that checks that the consistency cookie has the expected value.
MATCHER_P(CookieHasValueMatcher, value, "") {
+ net::CookieOptions cookie_options;
+ cookie_options.set_same_site_cookie_context(
+ net::CookieOptions::SameSiteCookieContext::SAME_SITE_LAX);
return arg.Name() == "CHROME_ID_CONSISTENCY_STATE" && arg.Value() == value &&
arg.IncludeForRequestURL(GaiaUrls::GetInstance()->gaia_url(),
- net::CookieOptions()) ==
+ cookie_options) ==
net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
}
+MATCHER(SetPermittedInContext, "") {
+ const net::CanonicalCookie& cookie = testing::get<0>(arg);
+ const net::CookieOptions& cookie_options = testing::get<1>(arg);
+ return cookie.IsSetPermittedInContext(cookie_options) ==
+ net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
+}
+
class MockCookieManager
: public testing::StrictMock<network::TestCookieManager> {
public:
@@ -38,7 +48,8 @@ class MockCookieManager
// specified value.
void ExpectSetCookieCall(const std::string& value) {
EXPECT_CALL(*this, SetCanonicalCookie(CookieHasValueMatcher(value), "https",
- testing::_, testing::_));
+ testing::_, testing::_))
+ .With(testing::Args<0, 2>(SetPermittedInContext()));
}
MOCK_METHOD4(
@@ -49,8 +60,7 @@ class MockCookieManager
network::mojom::CookieManager::SetCanonicalCookieCallback callback));
};
-class FakeConsistencyCookieManager
- : public signin::ConsistencyCookieManagerBase {
+class FakeConsistencyCookieManager : public ConsistencyCookieManagerBase {
public:
FakeConsistencyCookieManager(SigninClient* signin_client,
AccountReconcilor* reconcilor)
@@ -97,7 +107,7 @@ class ConsistencyCookieManagerTest : public ::testing::Test {
MockCookieManager* mock_cookie_manager_ = nullptr;
TestSigninClient signin_client_;
- identity::IdentityTestEnvironment identity_test_env_;
+ IdentityTestEnvironment identity_test_env_;
std::unique_ptr<AccountReconcilor> reconcilor_;
};
diff --git a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc
index ddb4f9e3da4..bc560b63767 100644
--- a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc
+++ b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc
@@ -10,8 +10,8 @@
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/signin_client.h"
-#include "components/signin/core/browser/signin_pref_names.h"
+#include "components/signin/public/base/signin_client.h"
+#include "components/signin/public/base/signin_pref_names.h"
namespace signin {
@@ -32,6 +32,85 @@ bool DiceAccountReconcilorDelegate::IsAccountConsistencyEnforced() const {
return account_consistency_ == AccountConsistencyMethod::kDice;
}
+DiceAccountReconcilorDelegate::InconsistencyReason
+DiceAccountReconcilorDelegate::GetInconsistencyReason(
+ const CoreAccountId& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const std::vector<gaia::ListedAccount>& gaia_accounts,
+ bool first_execution) const {
+ std::vector<CoreAccountId> valid_gaia_accounts_ids;
+ for (const gaia::ListedAccount& gaia_account : gaia_accounts) {
+ if (gaia_account.valid)
+ valid_gaia_accounts_ids.push_back(gaia_account.id);
+ }
+
+ bool primary_account_has_token = false;
+ if (!primary_account.empty()) {
+ primary_account_has_token =
+ base::Contains(chrome_accounts, primary_account);
+ bool primary_account_has_cookie =
+ base::Contains(valid_gaia_accounts_ids, primary_account);
+ if (primary_account_has_token && !primary_account_has_cookie)
+ return InconsistencyReason::kMissingSyncCookie;
+
+ if (!primary_account_has_token && primary_account_has_cookie)
+ return InconsistencyReason::kSyncAccountAuthError;
+ }
+
+ bool missing_first_web_account_token =
+ primary_account.empty() && !gaia_accounts.empty() &&
+ gaia_accounts[0].valid &&
+ !base::Contains(chrome_accounts, gaia_accounts[0].id);
+
+ if (missing_first_web_account_token)
+ return InconsistencyReason::kMissingFirstWebAccountToken;
+
+ std::sort(valid_gaia_accounts_ids.begin(), valid_gaia_accounts_ids.end());
+ std::vector<CoreAccountId> sorted_chrome_accounts(chrome_accounts);
+ std::sort(sorted_chrome_accounts.begin(), sorted_chrome_accounts.end());
+ bool missing_token =
+ !base::STLIncludes(sorted_chrome_accounts, valid_gaia_accounts_ids);
+ bool missing_cookie =
+ !base::STLIncludes(valid_gaia_accounts_ids, sorted_chrome_accounts);
+
+ if (missing_token && missing_cookie)
+ return InconsistencyReason::kCookieTokenMismatch;
+
+ if (missing_token)
+ return InconsistencyReason::kMissingSecondaryToken;
+
+ if (missing_cookie)
+ return InconsistencyReason::kMissingSecondaryCookie;
+
+ if (first_execution && primary_account_has_token &&
+ gaia_accounts[0].id != primary_account && gaia_accounts[0].valid)
+ return InconsistencyReason::kSyncCookieNotFirst;
+
+ return InconsistencyReason::kNone;
+}
+
+void DiceAccountReconcilorDelegate::MaybeLogInconsistencyReason(
+ const CoreAccountId& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const std::vector<gaia::ListedAccount>& gaia_accounts,
+ bool first_execution) const {
+ if (account_consistency_ != AccountConsistencyMethod::kDiceMigration)
+ return;
+
+ InconsistencyReason inconsistency_reason = GetInconsistencyReason(
+ primary_account, chrome_accounts, gaia_accounts, first_execution);
+
+ if (first_execution) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Signin.DiceMigrationNotReady.Reason.FirstExecution",
+ inconsistency_reason);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Signin.DiceMigrationNotReady.Reason.NotFirstExecution",
+ inconsistency_reason);
+ }
+}
+
gaia::GaiaSource DiceAccountReconcilorDelegate::GetGaiaApiSource() const {
return gaia::GaiaSource::kAccountReconcilorDice;
}
@@ -46,15 +125,15 @@ gaia::GaiaSource DiceAccountReconcilorDelegate::GetGaiaApiSource() const {
// 2. The primary account
// 3. The last known first Gaia account
// 4. The first account in the token service
-std::string DiceAccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
- const std::vector<std::string>& chrome_accounts,
+CoreAccountId DiceAccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string& primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool will_logout) const {
bool primary_account_has_token =
!primary_account.empty() &&
- base::ContainsValue(chrome_accounts, primary_account);
+ base::Contains(chrome_accounts, primary_account);
if (gaia_accounts.empty()) {
if (primary_account_has_token)
@@ -62,22 +141,22 @@ std::string DiceAccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
// Try the last known account. This happens when the cookies are cleared
// while Sync is disabled.
- if (base::ContainsValue(chrome_accounts, last_known_first_account_))
+ if (base::Contains(chrome_accounts, last_known_first_account_))
return last_known_first_account_;
// As a last resort, use the first Chrome account.
- return chrome_accounts.empty() ? std::string() : chrome_accounts[0];
+ return chrome_accounts.empty() ? CoreAccountId() : chrome_accounts[0];
}
- const std::string& first_gaia_account = gaia_accounts[0].id;
+ const CoreAccountId& first_gaia_account = gaia_accounts[0].id;
bool first_gaia_account_has_token =
- base::ContainsValue(chrome_accounts, first_gaia_account);
+ base::Contains(chrome_accounts, first_gaia_account);
if (!first_gaia_account_has_token &&
(primary_account == first_gaia_account) && gaia_accounts[0].valid) {
// The primary account is also the first Gaia account, and has no token.
// Logout everything.
- return std::string();
+ return CoreAccountId();
}
// If the primary Chrome account and the default Gaia account are both in
@@ -96,7 +175,7 @@ std::string DiceAccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
if (first_gaia_account_has_token)
return first_gaia_account;
// As a last resort, use the first Chrome account.
- return chrome_accounts.empty() ? std::string() : chrome_accounts[0];
+ return chrome_accounts.empty() ? CoreAccountId() : chrome_accounts[0];
}
// While Chrome is running, try the first Gaia account, and then the
@@ -108,12 +187,12 @@ std::string DiceAccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
// Changing the first Gaia account while Chrome is running would be
// confusing for the user. Logout everything.
- return std::string();
+ return CoreAccountId();
}
gaia::MultiloginMode DiceAccountReconcilorDelegate::CalculateModeForReconcile(
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool primary_has_error) const {
const bool sync_enabled = !primary_account.empty();
@@ -125,10 +204,10 @@ gaia::MultiloginMode DiceAccountReconcilorDelegate::CalculateModeForReconcile(
: gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER;
}
-std::vector<std::string>
+std::vector<CoreAccountId>
DiceAccountReconcilorDelegate::GetChromeAccountsForReconcile(
- const std::vector<std::string>& chrome_accounts,
- const std::string& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const CoreAccountId& primary_account,
const std::vector<gaia::ListedAccount>& gaia_accounts,
const gaia::MultiloginMode mode) const {
if (mode == gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER) {
@@ -136,7 +215,7 @@ DiceAccountReconcilorDelegate::GetChromeAccountsForReconcile(
gaia_accounts);
}
if (gaia_accounts.empty() &&
- base::ContainsValue(chrome_accounts, last_known_first_account_)) {
+ base::Contains(chrome_accounts, last_known_first_account_)) {
// In PRESERVE mode in case accounts in cookies are accidentally lost we
// should put cached first account first since Gaia has no information about
// it.
@@ -166,7 +245,7 @@ bool DiceAccountReconcilorDelegate::ShouldRevokeTokensOnCookieDeleted() {
}
void DiceAccountReconcilorDelegate::OnReconcileFinished(
- const std::string& first_account,
+ const CoreAccountId& first_account,
bool reconcile_is_noop) {
last_known_first_account_ = first_account;
diff --git a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h
index a2dbf416e3c..d62c0375164 100644
--- a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h
+++ b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h
@@ -8,8 +8,8 @@
#include <string>
#include "base/macros.h"
-#include "components/signin/core/browser/account_consistency_method.h"
#include "components/signin/core/browser/account_reconcilor_delegate.h"
+#include "components/signin/public/base/account_consistency_method.h"
class SigninClient;
@@ -25,29 +25,58 @@ class DiceAccountReconcilorDelegate : public AccountReconcilorDelegate {
// AccountReconcilorDelegate:
bool IsReconcileEnabled() const override;
bool IsAccountConsistencyEnforced() const override;
+ void MaybeLogInconsistencyReason(
+ const CoreAccountId& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const std::vector<gaia::ListedAccount>& gaia_accounts,
+ bool first_execution) const override;
gaia::GaiaSource GetGaiaApiSource() const override;
- std::string GetFirstGaiaAccountForReconcile(
- const std::vector<std::string>& chrome_accounts,
+ CoreAccountId GetFirstGaiaAccountForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string& primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool will_logout) const override;
RevokeTokenOption ShouldRevokeSecondaryTokensBeforeReconcile(
const std::vector<gaia::ListedAccount>& gaia_accounts) override;
- void OnReconcileFinished(const std::string& first_account,
+ void OnReconcileFinished(const CoreAccountId& first_account,
bool reconcile_is_noop) override;
bool ShouldRevokeTokensOnCookieDeleted() override;
private:
- std::vector<std::string> GetChromeAccountsForReconcile(
- const std::vector<std::string>& chrome_accounts,
- const std::string& primary_account,
+ // Possible inconsistency reasons between tokens and gaia cookies.
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+ enum class InconsistencyReason {
+ // Consistent
+ kNone = 0,
+ // Inconsistent
+ kMissingSyncCookie = 1,
+ kSyncAccountAuthError = 2,
+ kMissingFirstWebAccountToken = 3,
+ kMissingSecondaryCookie = 4,
+ kMissingSecondaryToken = 5,
+ kCookieTokenMismatch = 6,
+ kSyncCookieNotFirst = 7,
+ kMaxValue = kSyncCookieNotFirst
+ };
+
+ // Computes inconsistency reason between tokens and gaia cookies.
+ InconsistencyReason GetInconsistencyReason(
+ const CoreAccountId& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const std::vector<gaia::ListedAccount>& gaia_accounts,
+ bool first_execution) const;
+
+ std::vector<CoreAccountId> GetChromeAccountsForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const CoreAccountId& primary_account,
const std::vector<gaia::ListedAccount>& gaia_accounts,
const gaia::MultiloginMode mode) const override;
gaia::MultiloginMode CalculateModeForReconcile(
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool primary_has_error) const override;
@@ -55,7 +84,7 @@ class DiceAccountReconcilorDelegate : public AccountReconcilorDelegate {
AccountConsistencyMethod account_consistency_;
// Last known "first account". Used when cookies are lost as a best guess.
- std::string last_known_first_account_;
+ CoreAccountId last_known_first_account_;
DISALLOW_COPY_AND_ASSIGN(DiceAccountReconcilorDelegate);
};
diff --git a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
index 4c467559d79..5e3134224b7 100644
--- a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
+++ b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
@@ -7,9 +7,9 @@
#include <vector>
#include "components/prefs/pref_registry_simple.h"
-#include "components/signin/core/browser/account_consistency_method.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "components/signin/core/browser/test_signin_client.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/base/test_signin_client.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -36,23 +36,21 @@ TEST(DiceAccountReconcilorDelegateTest, RevokeTokens) {
// Dice is enabled, revoke only tokens in error state.
DiceAccountReconcilorDelegate delegate(&client,
AccountConsistencyMethod::kDice);
- EXPECT_EQ(
- signin::AccountReconcilorDelegate::RevokeTokenOption::kRevokeIfInError,
- delegate.ShouldRevokeSecondaryTokensBeforeReconcile(
- std::vector<gaia::ListedAccount>()));
+ EXPECT_EQ(AccountReconcilorDelegate::RevokeTokenOption::kRevokeIfInError,
+ delegate.ShouldRevokeSecondaryTokensBeforeReconcile(
+ std::vector<gaia::ListedAccount>()));
}
{
DiceAccountReconcilorDelegate delegate(
&client, AccountConsistencyMethod::kDiceMigration);
// Gaia accounts are not empty, don't revoke.
gaia::ListedAccount gaia_account;
- gaia_account.id = "other";
- EXPECT_EQ(
- signin::AccountReconcilorDelegate::RevokeTokenOption::kDoNotRevoke,
- delegate.ShouldRevokeSecondaryTokensBeforeReconcile(
- std::vector<gaia::ListedAccount>{gaia_account}));
+ gaia_account.id = CoreAccountId("other");
+ EXPECT_EQ(AccountReconcilorDelegate::RevokeTokenOption::kDoNotRevoke,
+ delegate.ShouldRevokeSecondaryTokensBeforeReconcile(
+ std::vector<gaia::ListedAccount>{gaia_account}));
// Revoke.
- EXPECT_EQ(signin::AccountReconcilorDelegate::RevokeTokenOption::kRevoke,
+ EXPECT_EQ(AccountReconcilorDelegate::RevokeTokenOption::kRevoke,
delegate.ShouldRevokeSecondaryTokensBeforeReconcile(
std::vector<gaia::ListedAccount>()));
}
@@ -71,7 +69,8 @@ TEST(DiceAccountReconcilorDelegateTest, OnReconcileFinished) {
EXPECT_CALL(client, SetReadyForDiceMigration(false)).Times(1);
DiceAccountReconcilorDelegate delegate(
&client, AccountConsistencyMethod::kDiceMigration);
- delegate.OnReconcileFinished("account", true /* is_reconcile_noop */);
+ delegate.OnReconcileFinished(CoreAccountId("account"),
+ true /* is_reconcile_noop */);
}
pref_service.SetBoolean(prefs::kTokenServiceDiceCompatible, true);
@@ -83,7 +82,8 @@ TEST(DiceAccountReconcilorDelegateTest, OnReconcileFinished) {
EXPECT_CALL(client, SetReadyForDiceMigration(false)).Times(1);
DiceAccountReconcilorDelegate delegate(
&client, AccountConsistencyMethod::kDiceMigration);
- delegate.OnReconcileFinished("account", false /* is_reconcile_noop */);
+ delegate.OnReconcileFinished(CoreAccountId("account"),
+ false /* is_reconcile_noop */);
}
{
@@ -92,7 +92,8 @@ TEST(DiceAccountReconcilorDelegateTest, OnReconcileFinished) {
EXPECT_CALL(client, SetReadyForDiceMigration(true)).Times(1);
DiceAccountReconcilorDelegate delegate(
&client, AccountConsistencyMethod::kDiceMigration);
- delegate.OnReconcileFinished("account", true /* is_reconcile_noop */);
+ delegate.OnReconcileFinished(CoreAccountId("account"),
+ true /* is_reconcile_noop */);
}
}
diff --git a/chromium/components/signin/core/browser/dice_header_helper.cc b/chromium/components/signin/core/browser/dice_header_helper.cc
index eac6a7c18b4..0c9880ed4c7 100644
--- a/chromium/components/signin/core/browser/dice_header_helper.cc
+++ b/chromium/components/signin/core/browser/dice_header_helper.cc
@@ -50,7 +50,7 @@ DiceAction GetDiceActionFromHeader(const std::string& value) {
} // namespace
DiceHeaderHelper::DiceHeaderHelper(AccountConsistencyMethod account_consistency)
- : SigninHeaderHelper("Dice"), account_consistency_(account_consistency) {}
+ : account_consistency_(account_consistency) {}
// static
DiceResponseParams DiceHeaderHelper::BuildDiceSigninResponseParams(
diff --git a/chromium/components/signin/core/browser/dice_header_helper.h b/chromium/components/signin/core/browser/dice_header_helper.h
index cd725f274e1..d4711431582 100644
--- a/chromium/components/signin/core/browser/dice_header_helper.h
+++ b/chromium/components/signin/core/browser/dice_header_helper.h
@@ -8,8 +8,8 @@
#include <string>
#include "base/macros.h"
-#include "components/signin/core/browser/account_consistency_method.h"
#include "components/signin/core/browser/signin_header_helper.h"
+#include "components/signin/public/base/account_consistency_method.h"
class GURL;
diff --git a/chromium/components/signin/core/browser/fake_profile_oauth2_token_service.cc b/chromium/components/signin/core/browser/fake_profile_oauth2_token_service.cc
deleted file mode 100644
index 4d2899e7550..00000000000
--- a/chromium/components/signin/core/browser/fake_profile_oauth2_token_service.cc
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "google_apis/gaia/fake_oauth2_token_service_delegate.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-
-FakeProfileOAuth2TokenService::PendingRequest::PendingRequest() {}
-
-FakeProfileOAuth2TokenService::PendingRequest::PendingRequest(
- const PendingRequest& other) = default;
-
-FakeProfileOAuth2TokenService::PendingRequest::~PendingRequest() {}
-
-FakeProfileOAuth2TokenService::FakeProfileOAuth2TokenService(
- PrefService* user_prefs)
- : FakeProfileOAuth2TokenService(
- user_prefs,
- std::make_unique<FakeOAuth2TokenServiceDelegate>()) {}
-
-FakeProfileOAuth2TokenService::FakeProfileOAuth2TokenService(
- PrefService* user_prefs,
- std::unique_ptr<OAuth2TokenServiceDelegate> delegate)
- : ProfileOAuth2TokenService(user_prefs, std::move(delegate)),
- auto_post_fetch_response_on_message_loop_(false),
- weak_ptr_factory_(this) {}
-
-FakeProfileOAuth2TokenService::~FakeProfileOAuth2TokenService() {}
-
-void FakeProfileOAuth2TokenService::IssueAllTokensForAccount(
- const std::string& account_id,
- const std::string& access_token,
- const base::Time& expiration) {
- DCHECK(!auto_post_fetch_response_on_message_loop_);
- CompleteRequests(account_id, true, ScopeSet(),
- GoogleServiceAuthError::AuthErrorNone(),
- OAuth2AccessTokenConsumer::TokenResponse(
- access_token, expiration, std::string() /* id_token */));
-}
-
-void FakeProfileOAuth2TokenService::IssueAllTokensForAccount(
- const std::string& account_id,
- const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
- DCHECK(!auto_post_fetch_response_on_message_loop_);
- CompleteRequests(account_id, true, ScopeSet(),
- GoogleServiceAuthError::AuthErrorNone(), token_response);
-}
-
-void FakeProfileOAuth2TokenService::IssueErrorForAllPendingRequestsForAccount(
- const std::string& account_id,
- const GoogleServiceAuthError& error) {
- DCHECK(!auto_post_fetch_response_on_message_loop_);
- CompleteRequests(account_id, true, ScopeSet(), error,
- OAuth2AccessTokenConsumer::TokenResponse());
-}
-
-void FakeProfileOAuth2TokenService::IssueTokenForScope(
- const ScopeSet& scope,
- const std::string& access_token,
- const base::Time& expiration) {
- DCHECK(!auto_post_fetch_response_on_message_loop_);
- CompleteRequests("", false, scope, GoogleServiceAuthError::AuthErrorNone(),
- OAuth2AccessTokenConsumer::TokenResponse(
- access_token, expiration, std::string() /* id_token */));
-}
-
-void FakeProfileOAuth2TokenService::IssueTokenForScope(
- const ScopeSet& scope,
- const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
- DCHECK(!auto_post_fetch_response_on_message_loop_);
- CompleteRequests("", false, scope, GoogleServiceAuthError::AuthErrorNone(),
- token_response);
-}
-
-void FakeProfileOAuth2TokenService::IssueErrorForScope(
- const ScopeSet& scope,
- const GoogleServiceAuthError& error) {
- DCHECK(!auto_post_fetch_response_on_message_loop_);
- CompleteRequests("", false, scope, error,
- OAuth2AccessTokenConsumer::TokenResponse());
-}
-
-void FakeProfileOAuth2TokenService::IssueErrorForAllPendingRequests(
- const GoogleServiceAuthError& error) {
- DCHECK(!auto_post_fetch_response_on_message_loop_);
- CompleteRequests("", true, ScopeSet(), error,
- OAuth2AccessTokenConsumer::TokenResponse());
-}
-
-void FakeProfileOAuth2TokenService::IssueTokenForAllPendingRequests(
- const std::string& access_token,
- const base::Time& expiration) {
- DCHECK(!auto_post_fetch_response_on_message_loop_);
- CompleteRequests("", true, ScopeSet(),
- GoogleServiceAuthError::AuthErrorNone(),
- OAuth2AccessTokenConsumer::TokenResponse(
- access_token, expiration, std::string() /* id_token */));
-}
-
-void FakeProfileOAuth2TokenService::IssueTokenForAllPendingRequests(
- const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
- DCHECK(!auto_post_fetch_response_on_message_loop_);
- CompleteRequests("", true, ScopeSet(),
- GoogleServiceAuthError::AuthErrorNone(), token_response);
-}
-
-void FakeProfileOAuth2TokenService::CompleteRequests(
- const std::string& account_id,
- bool all_scopes,
- const ScopeSet& scope,
- const GoogleServiceAuthError& error,
- const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
- std::vector<FakeProfileOAuth2TokenService::PendingRequest> requests =
- GetPendingRequests();
-
- // Walk the requests and notify the callbacks.
- for (auto it = requests.begin(); it != requests.end(); ++it) {
- DCHECK(it->request);
-
- bool scope_matches = all_scopes || it->scopes == scope;
- bool account_matches = account_id.empty() || account_id == it->account_id;
- if (account_matches && scope_matches) {
- for (auto& diagnostic_observer : GetDiagnicsObservers()) {
- diagnostic_observer.OnFetchAccessTokenComplete(
- account_id, it->request->GetConsumerId(), scope, error,
- base::Time());
- }
-
- it->request->InformConsumer(
- error, OAuth2AccessTokenConsumer::TokenResponse(
- token_response.access_token,
- token_response.expiration_time, token_response.id_token));
- }
- }
-}
-
-std::vector<FakeProfileOAuth2TokenService::PendingRequest>
-FakeProfileOAuth2TokenService::GetPendingRequests() {
- std::vector<PendingRequest> valid_requests;
- for (auto it = pending_requests_.begin(); it != pending_requests_.end();
- ++it) {
- if (it->request)
- valid_requests.push_back(*it);
- }
- return valid_requests;
-}
-
-void FakeProfileOAuth2TokenService::CancelAllRequests() {
- CompleteRequests(
- "", true, ScopeSet(),
- GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
- OAuth2AccessTokenConsumer::TokenResponse());
-}
-
-void FakeProfileOAuth2TokenService::CancelRequestsForAccount(
- const std::string& account_id) {
- CompleteRequests(
- account_id, true, ScopeSet(),
- GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
- OAuth2AccessTokenConsumer::TokenResponse());
-}
-
-void FakeProfileOAuth2TokenService::FetchOAuth2Token(
- RequestImpl* request,
- const std::string& account_id,
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- const std::string& client_id,
- const std::string& client_secret,
- const ScopeSet& scopes) {
- PendingRequest pending_request;
- pending_request.account_id = account_id;
- pending_request.client_id = client_id;
- pending_request.client_secret = client_secret;
- pending_request.url_loader_factory = url_loader_factory;
- pending_request.scopes = scopes;
- pending_request.request = request->AsWeakPtr();
- pending_requests_.push_back(pending_request);
-
- if (auto_post_fetch_response_on_message_loop_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(&FakeProfileOAuth2TokenService::CompleteRequests,
- weak_ptr_factory_.GetWeakPtr(), account_id,
- /*all_scoped=*/true, scopes,
- GoogleServiceAuthError::AuthErrorNone(),
- OAuth2AccessTokenConsumer::TokenResponse(
- "access_token", base::Time::Max(), std::string())));
- }
-}
-
-void FakeProfileOAuth2TokenService::InvalidateAccessTokenImpl(
- const std::string& account_id,
- const std::string& client_id,
- const ScopeSet& scopes,
- const std::string& access_token) {
- // Do nothing, as we don't have a cache from which to remove the token.
-}
diff --git a/chromium/components/signin/core/browser/identity_manager_wrapper.cc b/chromium/components/signin/core/browser/identity_manager_wrapper.cc
deleted file mode 100644
index 2025ebcd649..00000000000
--- a/chromium/components/signin/core/browser/identity_manager_wrapper.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/core/browser/identity_manager_wrapper.h"
-
-#include "components/keyed_service/core/keyed_service.h"
-#include "services/identity/public/cpp/accounts_cookie_mutator.h"
-#include "services/identity/public/cpp/accounts_mutator.h"
-#include "services/identity/public/cpp/diagnostics_provider.h"
-#include "services/identity/public/cpp/primary_account_mutator.h"
-
-IdentityManagerWrapper::IdentityManagerWrapper(
- std::unique_ptr<AccountTrackerService> account_tracker_service,
- std::unique_ptr<ProfileOAuth2TokenService> token_service,
- std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service,
- std::unique_ptr<SigninManagerBase> signin_manager,
- std::unique_ptr<AccountFetcherService> account_fetcher_service,
- std::unique_ptr<identity::PrimaryAccountMutator> primary_account_mutator,
- std::unique_ptr<identity::AccountsMutator> accounts_mutator,
- std::unique_ptr<identity::AccountsCookieMutator> accounts_cookie_mutator,
- std::unique_ptr<identity::DiagnosticsProvider> diagnostics_provider)
- : identity::IdentityManager(std::move(account_tracker_service),
- std::move(token_service),
- std::move(gaia_cookie_manager_service),
- std::move(signin_manager),
- std::move(account_fetcher_service),
- std::move(primary_account_mutator),
- std::move(accounts_mutator),
- std::move(accounts_cookie_mutator),
- std::move(diagnostics_provider)) {}
diff --git a/chromium/components/signin/core/browser/identity_manager_wrapper.h b/chromium/components/signin/core/browser/identity_manager_wrapper.h
deleted file mode 100644
index b1c03249a61..00000000000
--- a/chromium/components/signin/core/browser/identity_manager_wrapper.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_IDENTITY_MANAGER_WRAPPER_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_IDENTITY_MANAGER_WRAPPER_H_
-
-#include "components/keyed_service/core/keyed_service.h"
-#include "services/identity/public/cpp/identity_manager.h"
-
-class ProfileOAuth2TokenService;
-class SigninManagerBase;
-class GaiaCookieManagerService;
-class AccountFetcherService;
-class SigninManagerBase;
-class AccountsMutator;
-
-namespace identity {
-class PrimaryAccountMutator;
-class AccountsCookieMutator;
-class DiagnosticsProvider;
-} // namespace identity
-
-// Subclass that wraps IdentityManager in a KeyedService.
-// TODO(https://crbug.com/952788): This class can be deleted if
-// IdentityManager is updated to inherit from KeyedService directly.
-class IdentityManagerWrapper : public KeyedService,
- public identity::IdentityManager {
- public:
- IdentityManagerWrapper(
- std::unique_ptr<AccountTrackerService> account_tracker_service,
- std::unique_ptr<ProfileOAuth2TokenService> token_service,
- std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service,
- std::unique_ptr<SigninManagerBase> signin_manager,
- std::unique_ptr<AccountFetcherService> account_fetcher_service,
- std::unique_ptr<identity::PrimaryAccountMutator> primary_account_mutator,
- std::unique_ptr<identity::AccountsMutator> accounts_mutator,
- std::unique_ptr<identity::AccountsCookieMutator> accounts_cookie_mutator,
- std::unique_ptr<identity::DiagnosticsProvider> diagnostics_provider);
-};
-
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_IDENTITY_MANAGER_WRAPPER_H_
diff --git a/chromium/components/signin/core/browser/identity_utils.h b/chromium/components/signin/core/browser/identity_utils.h
deleted file mode 100644
index 241066b6c22..00000000000
--- a/chromium/components/signin/core/browser/identity_utils.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Functions that are shared between the Identity Service implementation and its
-// consumers. Currently in //components/signin because they are used by classes
-// in this component, which cannot depend on //services/identity to avoid a
-// dependency cycle. When these classes have no direct consumers and are moved
-// to //services/identity, these functions should correspondingly be moved to
-// //services/identity/public/cpp.
-
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_IDENTITY_UTILS_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_IDENTITY_UTILS_H_
-
-#include "base/strings/string_piece.h"
-
-class PrefService;
-
-namespace identity {
-
-// Returns true if the username is allowed based on the pattern string.
-//
-// NOTE: Can be moved to //services/identity/public/cpp once SigninManager is
-// moved to //services/identity.
-bool IsUsernameAllowedByPattern(base::StringPiece username,
- base::StringPiece pattern);
-
-// Returns true if the username is either allowed based on a pattern registered
-// as |pattern_pref_name| with the preferences service referenced by |prefs|,
-// or if such pattern can't be retrieved from |prefs|. This is a legacy
-// method intended to be used to migrate from SigninManager::IsAllowedUsername()
-// only while SigninManager::Initialize() can still accept a null PrefService*,
-// and can be removed once that's no longer the case (see crbug.com/908121).
-bool LegacyIsUsernameAllowedByPatternFromPrefs(
- PrefService* prefs,
- const std::string& username,
- const std::string& pattern_pref_name);
-} // namespace identity
-
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_IDENTITY_UTILS_H_
diff --git a/chromium/components/signin/core/browser/identity_utils_unittest.cc b/chromium/components/signin/core/browser/identity_utils_unittest.cc
deleted file mode 100644
index bdb7f76bc84..00000000000
--- a/chromium/components/signin/core/browser/identity_utils_unittest.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/core/browser/identity_utils.h"
-
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-#include "components/prefs/testing_pref_service.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-const char kUsername[] = "test@test.com";
-
-const char kValidWildcardPattern[] = ".*@test.com";
-const char kInvalidWildcardPattern[] = "*@test.com";
-
-const char kMatchingPattern1[] = "test@test.com";
-const char kMatchingPattern2[] = ".*@test.com";
-const char kMatchingPattern3[] = "test@.*.com";
-const char kMatchingPattern4[] = ".*@.*.com";
-const char kMatchingPattern5[] = ".*@.*";
-const char kMatchingPattern6[] = ".*";
-
-const char kNonMatchingPattern[] = ".*foo.*";
-const char kNonMatchingUsernamePattern[] = "foo@test.com";
-const char kNonMatchingDomainPattern[] = "test@foo.com";
-
-const char kRegisteredPattern[] = "test.registered.username_pattern";
-} // namespace
-
-class IdentityUtilsTest : public testing::Test {
- public:
- IdentityUtilsTest() {
- prefs_.registry()->RegisterStringPref(kRegisteredPattern, std::string());
- }
-
- TestingPrefServiceSimple* prefs() { return &prefs_; }
-
- private:
- TestingPrefServiceSimple prefs_;
-};
-
-TEST_F(IdentityUtilsTest, IsUsernameAllowedByPattern_EmptyPatterns) {
- EXPECT_TRUE(identity::IsUsernameAllowedByPattern(kUsername, ""));
- EXPECT_FALSE(identity::IsUsernameAllowedByPattern(kUsername, " "));
-}
-
-TEST_F(IdentityUtilsTest, IsUsernameAllowedByPattern_InvalidWildcardPatterns) {
- // identity::IsUsernameAllowedByPattern should recognize invalid wildcard
- // patterns like "*@foo.com" and insert a "." before them automatically.
- EXPECT_TRUE(
- identity::IsUsernameAllowedByPattern(kUsername, kValidWildcardPattern));
- EXPECT_TRUE(
- identity::IsUsernameAllowedByPattern(kUsername, kInvalidWildcardPattern));
-}
-
-TEST_F(IdentityUtilsTest, IsUsernameAllowedByPattern_MatchingWildcardPatterns) {
- EXPECT_TRUE(
- identity::IsUsernameAllowedByPattern(kUsername, kMatchingPattern1));
- EXPECT_TRUE(
- identity::IsUsernameAllowedByPattern(kUsername, kMatchingPattern2));
- EXPECT_TRUE(
- identity::IsUsernameAllowedByPattern(kUsername, kMatchingPattern3));
- EXPECT_TRUE(
- identity::IsUsernameAllowedByPattern(kUsername, kMatchingPattern4));
- EXPECT_TRUE(
- identity::IsUsernameAllowedByPattern(kUsername, kMatchingPattern5));
- EXPECT_TRUE(
- identity::IsUsernameAllowedByPattern(kUsername, kMatchingPattern6));
-
- EXPECT_FALSE(
- identity::IsUsernameAllowedByPattern(kUsername, kNonMatchingPattern));
- EXPECT_FALSE(identity::IsUsernameAllowedByPattern(
- kUsername, kNonMatchingUsernamePattern));
- EXPECT_FALSE(identity::IsUsernameAllowedByPattern(kUsername,
- kNonMatchingDomainPattern));
-}
-
-TEST_F(IdentityUtilsTest, LegacyIsUsernameAllowedByPatternFromPrefs) {
- // Passing a null local state should return 'allowed'.
- EXPECT_TRUE(identity::LegacyIsUsernameAllowedByPatternFromPrefs(
- nullptr, kUsername, kRegisteredPattern));
-
- // Now set different values for the named pattern and check against them.
- prefs()->SetString(kRegisteredPattern, kMatchingPattern1);
- EXPECT_TRUE(identity::LegacyIsUsernameAllowedByPatternFromPrefs(
- prefs(), kUsername, kRegisteredPattern));
-
- prefs()->SetString(kRegisteredPattern, kNonMatchingUsernamePattern);
- EXPECT_FALSE(identity::LegacyIsUsernameAllowedByPatternFromPrefs(
- prefs(), kUsername, kRegisteredPattern));
-
- prefs()->SetString(kRegisteredPattern, kMatchingPattern2);
- EXPECT_TRUE(identity::LegacyIsUsernameAllowedByPatternFromPrefs(
- prefs(), kUsername, kRegisteredPattern));
-
- prefs()->SetString(kRegisteredPattern, kNonMatchingDomainPattern);
- EXPECT_FALSE(identity::LegacyIsUsernameAllowedByPatternFromPrefs(
- prefs(), kUsername, kRegisteredPattern));
-}
diff --git a/chromium/components/signin/core/browser/mice_account_reconcilor_delegate.cc b/chromium/components/signin/core/browser/mice_account_reconcilor_delegate.cc
index 86bcfa4143a..8b8c9369672 100644
--- a/chromium/components/signin/core/browser/mice_account_reconcilor_delegate.cc
+++ b/chromium/components/signin/core/browser/mice_account_reconcilor_delegate.cc
@@ -5,7 +5,6 @@
#include "components/signin/core/browser/mice_account_reconcilor_delegate.h"
#include "base/logging.h"
-#include "components/signin/core/browser/account_reconcilor.h"
namespace signin {
@@ -25,22 +24,22 @@ gaia::GaiaSource MiceAccountReconcilorDelegate::GetGaiaApiSource() const {
return gaia::GaiaSource::kAccountReconcilorMirror;
}
-std::string MiceAccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
- const std::vector<std::string>& chrome_accounts,
+CoreAccountId MiceAccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string& primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool will_logout) const {
// This flow is deprecated and will be removed when multilogin is fully
// launched.
NOTREACHED() << "Mice requires multilogin";
- return std::string();
+ return CoreAccountId();
}
-std::vector<std::string>
+std::vector<CoreAccountId>
MiceAccountReconcilorDelegate::GetChromeAccountsForReconcile(
- const std::vector<std::string>& chrome_accounts,
- const std::string& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const CoreAccountId& primary_account,
const std::vector<gaia::ListedAccount>& gaia_accounts,
const gaia::MultiloginMode mode) const {
if (chrome_accounts.empty())
@@ -51,10 +50,9 @@ MiceAccountReconcilorDelegate::GetChromeAccountsForReconcile(
// - first account on the device.
// Warning: As a result, the reconciliation may change the default Gaia
// account. It should be ensured that this is not surprising for the user.
- std::string new_first_account =
- base::ContainsValue(chrome_accounts, primary_account)
- ? primary_account
- : chrome_accounts[0];
+ CoreAccountId new_first_account =
+ base::Contains(chrome_accounts, primary_account) ? primary_account
+ : chrome_accounts[0];
// Minimize account shuffling and ensure that the number of accounts does not
// exceed the limit.
@@ -64,7 +62,7 @@ MiceAccountReconcilorDelegate::GetChromeAccountsForReconcile(
gaia::MultiloginMode MiceAccountReconcilorDelegate::CalculateModeForReconcile(
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool primary_has_error) const {
return gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER;
diff --git a/chromium/components/signin/core/browser/mice_account_reconcilor_delegate.h b/chromium/components/signin/core/browser/mice_account_reconcilor_delegate.h
index b5d080b0129..28a71d00bc1 100644
--- a/chromium/components/signin/core/browser/mice_account_reconcilor_delegate.h
+++ b/chromium/components/signin/core/browser/mice_account_reconcilor_delegate.h
@@ -24,20 +24,20 @@ class MiceAccountReconcilorDelegate : public AccountReconcilorDelegate {
bool IsReconcileEnabled() const override;
bool IsAccountConsistencyEnforced() const override;
gaia::GaiaSource GetGaiaApiSource() const override;
- std::string GetFirstGaiaAccountForReconcile(
- const std::vector<std::string>& chrome_accounts,
+ CoreAccountId GetFirstGaiaAccountForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string& primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool will_logout) const override;
- std::vector<std::string> GetChromeAccountsForReconcile(
- const std::vector<std::string>& chrome_accounts,
- const std::string& primary_account,
+ std::vector<CoreAccountId> GetChromeAccountsForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const CoreAccountId& primary_account,
const std::vector<gaia::ListedAccount>& gaia_accounts,
const gaia::MultiloginMode mode) const override;
gaia::MultiloginMode CalculateModeForReconcile(
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool primary_has_error) const override;
bool IsUnknownInvalidAccountInCookieAllowed() const override;
diff --git a/chromium/components/signin/core/browser/mice_account_reconcilor_delegate_unittest.cc b/chromium/components/signin/core/browser/mice_account_reconcilor_delegate_unittest.cc
index 001637f6376..b3947eaab72 100644
--- a/chromium/components/signin/core/browser/mice_account_reconcilor_delegate_unittest.cc
+++ b/chromium/components/signin/core/browser/mice_account_reconcilor_delegate_unittest.cc
@@ -17,11 +17,20 @@ namespace {
gaia::ListedAccount BuildTestListedAccount(const std::string account_id,
bool valid) {
gaia::ListedAccount account;
- account.id = account_id;
+ account.id = CoreAccountId(account_id);
account.valid = valid;
return account;
}
+// Returns vector of account_id created from value
+std::vector<CoreAccountId> ToAccountIdList(
+ const std::vector<std::string>& account_ids_value) {
+ std::vector<CoreAccountId> account_ids;
+ for (const auto& account_id_value : account_ids_value)
+ account_ids.push_back(CoreAccountId(account_id_value));
+ return account_ids;
+}
+
} // namespace
TEST(MiceAccountReconcilorDelegate, CalculateParametersForMultilogin) {
@@ -65,11 +74,13 @@ TEST(MiceAccountReconcilorDelegate, CalculateParametersForMultilogin) {
for (const auto& test : cases) {
MultiloginParameters multilogin_parameters =
mice_delegate.CalculateParametersForMultilogin(
- test.chrome_accounts, test.primary_account, test.gaia_accounts,
- false, false);
+ ToAccountIdList(test.chrome_accounts),
+ CoreAccountId(test.primary_account), test.gaia_accounts, false,
+ false);
EXPECT_EQ(gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
multilogin_parameters.mode);
- EXPECT_EQ(test.expected_accounts, multilogin_parameters.accounts_to_send);
+ EXPECT_EQ(ToAccountIdList(test.expected_accounts),
+ multilogin_parameters.accounts_to_send);
}
}
diff --git a/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.cc b/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.cc
index dec959175c4..db56be5a380 100644
--- a/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.cc
+++ b/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.cc
@@ -10,7 +10,7 @@
namespace signin {
MirrorAccountReconcilorDelegate::MirrorAccountReconcilorDelegate(
- identity::IdentityManager* identity_manager)
+ IdentityManager* identity_manager)
: identity_manager_(identity_manager) {
DCHECK(identity_manager_);
identity_manager_->AddObserver(this);
@@ -37,22 +37,22 @@ bool MirrorAccountReconcilorDelegate::ShouldAbortReconcileIfPrimaryHasError()
return true;
}
-std::string MirrorAccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
- const std::vector<std::string>& chrome_accounts,
+CoreAccountId MirrorAccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string& primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool will_logout) const {
// Mirror only uses the primary account, and it is never empty.
DCHECK(!primary_account.empty());
- DCHECK(base::ContainsValue(chrome_accounts, primary_account));
+ DCHECK(base::Contains(chrome_accounts, primary_account));
return primary_account;
}
-std::vector<std::string>
+std::vector<CoreAccountId>
MirrorAccountReconcilorDelegate::GetChromeAccountsForReconcile(
- const std::vector<std::string>& chrome_accounts,
- const std::string& primary_account,
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const CoreAccountId& primary_account,
const std::vector<gaia::ListedAccount>& gaia_accounts,
const gaia::MultiloginMode mode) const {
DCHECK_EQ(mode,
diff --git a/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.h b/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.h
index a13904754a1..bc465861119 100644
--- a/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.h
+++ b/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.h
@@ -10,17 +10,15 @@
#include "base/macros.h"
#include "components/signin/core/browser/account_reconcilor_delegate.h"
-#include "services/identity/public/cpp/identity_manager.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
namespace signin {
// AccountReconcilorDelegate specialized for Mirror.
-class MirrorAccountReconcilorDelegate
- : public AccountReconcilorDelegate,
- public identity::IdentityManager::Observer {
+class MirrorAccountReconcilorDelegate : public AccountReconcilorDelegate,
+ public IdentityManager::Observer {
public:
- explicit MirrorAccountReconcilorDelegate(
- identity::IdentityManager* identity_manager);
+ explicit MirrorAccountReconcilorDelegate(IdentityManager* identity_manager);
~MirrorAccountReconcilorDelegate() override;
protected:
@@ -34,15 +32,15 @@ class MirrorAccountReconcilorDelegate
bool IsAccountConsistencyEnforced() const override;
gaia::GaiaSource GetGaiaApiSource() const override;
bool ShouldAbortReconcileIfPrimaryHasError() const override;
- std::string GetFirstGaiaAccountForReconcile(
- const std::vector<std::string>& chrome_accounts,
+ CoreAccountId GetFirstGaiaAccountForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
const std::vector<gaia::ListedAccount>& gaia_accounts,
- const std::string& primary_account,
+ const CoreAccountId& primary_account,
bool first_execution,
bool will_logout) const override;
- std::vector<std::string> GetChromeAccountsForReconcile(
- const std::vector<std::string>& chrome_accounts,
- const std::string& primary_account,
+ std::vector<CoreAccountId> GetChromeAccountsForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const CoreAccountId& primary_account,
const std::vector<gaia::ListedAccount>& gaia_accounts,
const gaia::MultiloginMode mode) const override;
@@ -52,7 +50,7 @@ class MirrorAccountReconcilorDelegate
void OnPrimaryAccountCleared(
const CoreAccountInfo& previous_primary_account_info) override;
- identity::IdentityManager* identity_manager_;
+ IdentityManager* identity_manager_;
DISALLOW_COPY_AND_ASSIGN(MirrorAccountReconcilorDelegate);
};
diff --git a/chromium/components/signin/core/browser/multilogin_parameters.cc b/chromium/components/signin/core/browser/multilogin_parameters.cc
new file mode 100644
index 00000000000..6afad08509a
--- /dev/null
+++ b/chromium/components/signin/core/browser/multilogin_parameters.cc
@@ -0,0 +1,28 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/multilogin_parameters.h"
+
+namespace signin {
+
+MultiloginParameters::MultiloginParameters(
+ const gaia::MultiloginMode mode,
+ const std::vector<CoreAccountId>& accounts_to_send)
+ : mode(mode), accounts_to_send(accounts_to_send) {}
+
+MultiloginParameters::~MultiloginParameters() {}
+
+MultiloginParameters::MultiloginParameters(const MultiloginParameters& other) {
+ mode = other.mode;
+ accounts_to_send = other.accounts_to_send;
+}
+
+MultiloginParameters& MultiloginParameters::operator=(
+ const MultiloginParameters& other) {
+ mode = other.mode;
+ accounts_to_send = other.accounts_to_send;
+ return *this;
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/core/browser/multilogin_parameters.h b/chromium/components/signin/core/browser/multilogin_parameters.h
new file mode 100644
index 00000000000..9dae3b26b49
--- /dev/null
+++ b/chromium/components/signin/core/browser/multilogin_parameters.h
@@ -0,0 +1,33 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_MULTILOGIN_PARAMETERS_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_MULTILOGIN_PARAMETERS_H_
+
+#include <string>
+#include <vector>
+
+#include "google_apis/gaia/core_account_id.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
+
+namespace signin {
+
+struct MultiloginParameters {
+ MultiloginParameters(gaia::MultiloginMode mode,
+ const std::vector<CoreAccountId>& accounts_to_send);
+ MultiloginParameters(const MultiloginParameters& other);
+ MultiloginParameters& operator=(const MultiloginParameters& other);
+ ~MultiloginParameters();
+
+ // Needed for testing.
+ bool operator==(const MultiloginParameters& other) const {
+ return mode == other.mode && accounts_to_send == other.accounts_to_send;
+ }
+
+ gaia::MultiloginMode mode;
+ std::vector<CoreAccountId> accounts_to_send;
+};
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_CORE_BROWSER_MULTILOGIN_PARAMETERS_H_
diff --git a/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher.h b/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher.h
deleted file mode 100644
index 168ba881513..00000000000
--- a/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH_MULTILOGIN_TOKEN_FETCHER_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH_MULTILOGIN_TOKEN_FETCHER_H_
-
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/bind_helpers.h"
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "google_apis/gaia/gaia_auth_fetcher.h"
-#include "google_apis/gaia/google_service_auth_error.h"
-#include "google_apis/gaia/oauth2_token_service.h"
-
-class SigninClient;
-
-namespace signin {
-
-// Fetches multilogin access tokens in parallel for multiple accounts.
-// It is safe to delete this object from within the callbacks.
-class OAuthMultiloginTokenFetcher : public OAuth2TokenService::Consumer {
- public:
- using SuccessCallback = base::OnceCallback<void(
- const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>&)>;
- using FailureCallback =
- base::OnceCallback<void(const GoogleServiceAuthError&)>;
-
- OAuthMultiloginTokenFetcher(SigninClient* signin_client,
- OAuth2TokenService* token_service,
- const std::vector<std::string>& account_ids,
- SuccessCallback success_callback,
- FailureCallback failure_callback);
-
- ~OAuthMultiloginTokenFetcher() override;
-
- private:
- void StartFetchingToken(const std::string& account_id);
-
- // Overridden from OAuth2TokenService::Consumer.
- void OnGetTokenSuccess(
- const OAuth2TokenService::Request* request,
- const OAuth2AccessTokenConsumer::TokenResponse& token_response) override;
- void OnGetTokenFailure(const OAuth2TokenService::Request* request,
- const GoogleServiceAuthError& error) override;
-
- // Helper function to remove a request from token_requests_.
- void EraseRequest(const OAuth2TokenService::Request* request);
-
- SigninClient* signin_client_;
- OAuth2TokenService* token_service_;
- const std::vector<std::string> account_ids_;
-
- SuccessCallback success_callback_;
- FailureCallback failure_callback_;
-
- std::vector<std::unique_ptr<OAuth2TokenService::Request>> token_requests_;
- std::map<std::string, std::string> access_tokens_;
- std::set<std::string> retried_requests_; // Requests are retried once.
-
- base::WeakPtrFactory<OAuthMultiloginTokenFetcher> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(OAuthMultiloginTokenFetcher);
-};
-
-} // namespace signin
-
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH_MULTILOGIN_TOKEN_FETCHER_H_
diff --git a/chromium/components/signin/core/browser/profile_oauth2_token_service.cc b/chromium/components/signin/core/browser/profile_oauth2_token_service.cc
deleted file mode 100644
index 50fb83dd5ce..00000000000
--- a/chromium/components/signin/core/browser/profile_oauth2_token_service.cc
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
-
-#include "base/auto_reset.h"
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/signin/core/browser/device_id_helper.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-
-using signin_metrics::SourceForRefreshTokenOperation;
-
-namespace {
-std::string SourceToString(SourceForRefreshTokenOperation source) {
- switch (source) {
- case SourceForRefreshTokenOperation::kUnknown:
- return "Unknown";
- case SourceForRefreshTokenOperation::kTokenService_LoadCredentials:
- return "TokenService::LoadCredentials";
- case SourceForRefreshTokenOperation::kSupervisedUser_InitSync:
- return "SupervisedUser::InitSync";
- case SourceForRefreshTokenOperation::kInlineLoginHandler_Signin:
- return "InlineLoginHandler::Signin";
- case SourceForRefreshTokenOperation::kSigninManager_ClearPrimaryAccount:
- return "SigninManager::ClearPrimaryAccount";
- case SourceForRefreshTokenOperation::kSigninManager_LegacyPreDiceSigninFlow:
- return "SigninManager::LegacyPreDiceSigninFlow";
- case SourceForRefreshTokenOperation::kUserMenu_RemoveAccount:
- return "UserMenu::RemoveAccount";
- case SourceForRefreshTokenOperation::kUserMenu_SignOutAllAccounts:
- return "UserMenu::SignOutAllAccounts";
- case SourceForRefreshTokenOperation::kSettings_Signout:
- return "Settings::Signout";
- case SourceForRefreshTokenOperation::kSettings_PauseSync:
- return "Settings::PauseSync";
- case SourceForRefreshTokenOperation::
- kAccountReconcilor_GaiaCookiesDeletedByUser:
- return "AccountReconcilor::GaiaCookiesDeletedByUser";
- case SourceForRefreshTokenOperation::kAccountReconcilor_GaiaCookiesUpdated:
- return "AccountReconcilor::GaiaCookiesUpdated";
- case SourceForRefreshTokenOperation::kAccountReconcilor_Reconcile:
- return "AccountReconcilor::Reconcile";
- case SourceForRefreshTokenOperation::kDiceResponseHandler_Signin:
- return "DiceResponseHandler::Signin";
- case SourceForRefreshTokenOperation::kDiceResponseHandler_Signout:
- return "DiceResponseHandler::Signout";
- case SourceForRefreshTokenOperation::kDiceTurnOnSyncHelper_Abort:
- return "DiceTurnOnSyncHelper::Abort";
- case SourceForRefreshTokenOperation::kMachineLogon_CredentialProvider:
- return "MachineLogon::CredentialProvider";
- case SourceForRefreshTokenOperation::kTokenService_ExtractCredentials:
- return "TokenService::ExtractCredentials";
- }
-}
-} // namespace
-
-ProfileOAuth2TokenService::ProfileOAuth2TokenService(
- PrefService* user_prefs,
- std::unique_ptr<OAuth2TokenServiceDelegate> delegate)
- : OAuth2TokenService(std::move(delegate)),
- user_prefs_(user_prefs),
- all_credentials_loaded_(false) {
- DCHECK(user_prefs_);
- AddObserver(this);
-}
-
-ProfileOAuth2TokenService::~ProfileOAuth2TokenService() {
- RemoveObserver(this);
-}
-
-// static
-void ProfileOAuth2TokenService::RegisterProfilePrefs(
- PrefRegistrySimple* registry) {
-#if defined(OS_IOS)
- registry->RegisterBooleanPref(prefs::kTokenServiceExcludeAllSecondaryAccounts,
- false);
- registry->RegisterListPref(prefs::kTokenServiceExcludedSecondaryAccounts);
-#endif
- registry->RegisterStringPref(prefs::kGoogleServicesSigninScopedDeviceId,
- std::string());
-}
-
-void ProfileOAuth2TokenService::Shutdown() {
- CancelAllRequests();
- GetDelegate()->Shutdown();
-}
-
-void ProfileOAuth2TokenService::LoadCredentials(
- const std::string& primary_account_id) {
- DCHECK_EQ(SourceForRefreshTokenOperation::kUnknown,
- update_refresh_token_source_);
- update_refresh_token_source_ =
- SourceForRefreshTokenOperation::kTokenService_LoadCredentials;
- GetDelegate()->LoadCredentials(primary_account_id);
-}
-
-bool ProfileOAuth2TokenService::AreAllCredentialsLoaded() {
- return all_credentials_loaded_;
-}
-
-void ProfileOAuth2TokenService::UpdateCredentials(
- const std::string& account_id,
- const std::string& refresh_token,
- SourceForRefreshTokenOperation source) {
- base::AutoReset<SourceForRefreshTokenOperation> auto_reset(
- &update_refresh_token_source_, source);
- GetDelegate()->UpdateCredentials(account_id, refresh_token);
-}
-
-void ProfileOAuth2TokenService::RevokeCredentials(
- const std::string& account_id,
- SourceForRefreshTokenOperation source) {
- base::AutoReset<SourceForRefreshTokenOperation> auto_reset(
- &update_refresh_token_source_, source);
- GetDelegate()->RevokeCredentials(account_id);
-}
-
-void ProfileOAuth2TokenService::RevokeAllCredentials(
- SourceForRefreshTokenOperation source) {
- base::AutoReset<SourceForRefreshTokenOperation> auto_reset(
- &update_refresh_token_source_, source);
- CancelAllRequests();
- ClearCache();
- GetDelegate()->RevokeAllCredentials();
-}
-
-const net::BackoffEntry* ProfileOAuth2TokenService::GetDelegateBackoffEntry() {
- return GetDelegate()->BackoffEntry();
-}
-
-#if BUILDFLAG(ENABLE_DICE_SUPPORT)
-void ProfileOAuth2TokenService::ExtractCredentials(
- ProfileOAuth2TokenService* to_service,
- const std::string& account_id) {
- base::AutoReset<SourceForRefreshTokenOperation> auto_reset(
- &update_refresh_token_source_,
- SourceForRefreshTokenOperation::kTokenService_ExtractCredentials);
- GetDelegate()->ExtractCredentials(to_service, account_id);
-}
-#endif
-
-void ProfileOAuth2TokenService::OnRefreshTokenAvailable(
- const std::string& account_id) {
- // Check if the newly-updated token is valid (invalid tokens are inserted when
- // the user signs out on the web with DICE enabled).
- bool is_valid = true;
- GoogleServiceAuthError token_error = GetAuthError(account_id);
- if (token_error == GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
- GoogleServiceAuthError::InvalidGaiaCredentialsReason::
- CREDENTIALS_REJECTED_BY_CLIENT)) {
- is_valid = false;
- }
-
- CancelRequestsForAccount(account_id);
- ClearCacheForAccount(account_id);
-
- signin_metrics::RecordRefreshTokenUpdatedFromSource(
- is_valid, update_refresh_token_source_);
-
- std::string source_string = SourceToString(update_refresh_token_source_);
- for (auto& diagnostic_observer : GetDiagnicsObservers()) {
- diagnostic_observer.OnRefreshTokenAvailableFromSource(account_id, is_valid,
- source_string);
- }
-}
-
-void ProfileOAuth2TokenService::OnRefreshTokenRevoked(
- const std::string& account_id) {
- // If this was the last token, recreate the device ID.
- RecreateDeviceIdIfNeeded();
-
- CancelRequestsForAccount(account_id);
- ClearCacheForAccount(account_id);
-
- signin_metrics::RecordRefreshTokenRevokedFromSource(
- update_refresh_token_source_);
- std::string source_string = SourceToString(update_refresh_token_source_);
- for (auto& diagnostic_observer : GetDiagnicsObservers()) {
- diagnostic_observer.OnRefreshTokenRevokedFromSource(account_id,
- source_string);
- }
-}
-
-void ProfileOAuth2TokenService::OnRefreshTokensLoaded() {
- DCHECK_NE(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_NOT_STARTED,
- GetDelegate()->load_credentials_state());
- DCHECK_NE(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_IN_PROGRESS,
- GetDelegate()->load_credentials_state());
-
- all_credentials_loaded_ = true;
-
- // Reset the state for update refresh token operations to Unknown as this
- // was the original state before LoadCredentials was called.
- update_refresh_token_source_ = SourceForRefreshTokenOperation::kUnknown;
-
- // Ensure the device ID is not empty, and recreate it if all tokens were
- // cleared during the loading process.
- RecreateDeviceIdIfNeeded();
-}
-
-bool ProfileOAuth2TokenService::HasLoadCredentialsFinishedWithNoErrors() {
- switch (GetDelegate()->load_credentials_state()) {
- case OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_NOT_STARTED:
- case OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_IN_PROGRESS:
- // LoadCredentials has not finished.
- return false;
- case OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_FINISHED_WITH_DB_ERRORS:
- case OAuth2TokenServiceDelegate::
- LOAD_CREDENTIALS_FINISHED_WITH_DECRYPT_ERRORS:
- case OAuth2TokenServiceDelegate::
- LOAD_CREDENTIALS_FINISHED_WITH_UNKNOWN_ERRORS:
- // LoadCredentials finished, but with errors
- return false;
- case OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS:
- case OAuth2TokenServiceDelegate::
- LOAD_CREDENTIALS_FINISHED_WITH_NO_TOKEN_FOR_PRIMARY_ACCOUNT:
- // Load credentials finished with success.
- return true;
- }
-}
-
-void ProfileOAuth2TokenService::RecreateDeviceIdIfNeeded() {
-// On ChromeOS the device ID is not managed by the token service.
-#if !defined(OS_CHROMEOS)
- if (AreAllCredentialsLoaded() && HasLoadCredentialsFinishedWithNoErrors() &&
- GetAccounts().empty()) {
- signin::RecreateSigninScopedDeviceId(user_prefs_);
- }
-#endif
-}
diff --git a/chromium/components/signin/core/browser/profile_oauth2_token_service.h b/chromium/components/signin/core/browser/profile_oauth2_token_service.h
deleted file mode 100644
index c985a241111..00000000000
--- a/chromium/components/signin/core/browser/profile_oauth2_token_service.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "build/buildflag.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "components/signin/core/browser/signin_buildflags.h"
-#include "components/signin/core/browser/signin_metrics.h"
-#include "google_apis/gaia/oauth2_token_service.h"
-#include "google_apis/gaia/oauth2_token_service_delegate.h"
-#include "net/base/backoff_entry.h"
-
-#include <memory>
-
-namespace identity {
-class IdentityManager;
-}
-
-class PrefService;
-class PrefRegistrySimple;
-
-// ProfileOAuth2TokenService is a KeyedService that retrieves
-// OAuth2 access tokens for a given set of scopes using the OAuth2 login
-// refresh tokens.
-//
-// See |OAuth2TokenService| for usage details.
-//
-// Note: after StartRequest returns, in-flight requests will continue
-// even if the TokenService refresh token that was used to initiate
-// the request changes or is cleared. When the request completes,
-// Consumer::OnGetTokenSuccess will be invoked, but the access token
-// won't be cached.
-//
-// Note: requests should be started from the UI thread. To start a
-// request from other thread, please use OAuth2TokenServiceRequest.
-class ProfileOAuth2TokenService : public OAuth2TokenService,
- public OAuth2TokenService::Observer {
- public:
- ProfileOAuth2TokenService(
- PrefService* user_prefs,
- std::unique_ptr<OAuth2TokenServiceDelegate> delegate);
- ~ProfileOAuth2TokenService() override;
-
- // Registers per-profile prefs.
- static void RegisterProfilePrefs(PrefRegistrySimple* registry);
-
- void Shutdown();
-
- // Loads credentials from a backing persistent store to make them available
- // after service is used between profile restarts.
- //
- // The primary account is specified with the |primary_account_id| argument.
- // For a regular profile, the primary account id comes from SigninManager.
- // For a supervised user, the id comes from SupervisedUserService.
- void LoadCredentials(const std::string& primary_account_id);
-
- // Returns true iff all credentials have been loaded from disk.
- bool AreAllCredentialsLoaded();
-
- // Returns true if LoadCredentials finished with no errors.
- bool HasLoadCredentialsFinishedWithNoErrors();
-
- // Updates a |refresh_token| for an |account_id|. Credentials are persisted,
- // and available through |LoadCredentials| after service is restarted.
- void UpdateCredentials(
- const std::string& account_id,
- const std::string& refresh_token,
- signin_metrics::SourceForRefreshTokenOperation source =
- signin_metrics::SourceForRefreshTokenOperation::kUnknown);
-
- void RevokeCredentials(
- const std::string& account_id,
- signin_metrics::SourceForRefreshTokenOperation source =
- signin_metrics::SourceForRefreshTokenOperation::kUnknown);
-
- // Revokes all credentials.
- void RevokeAllCredentials(
- signin_metrics::SourceForRefreshTokenOperation source =
- signin_metrics::SourceForRefreshTokenOperation::kUnknown);
-
- // Returns a pointer to its instance of net::BackoffEntry or nullptr if there
- // is no such instance.
- const net::BackoffEntry* GetDelegateBackoffEntry();
-
-#if BUILDFLAG(ENABLE_DICE_SUPPORT)
- // Removes the credentials associated to account_id from the internal storage,
- // and moves them to |to_service|. The credentials are not revoked on the
- // server, but the OnRefreshTokenRevoked() notification is sent to the
- // observers.
- void ExtractCredentials(ProfileOAuth2TokenService* to_service,
- const std::string& account_id);
-#endif
-
- void set_all_credentials_loaded_for_testing(bool loaded) {
- all_credentials_loaded_ = loaded;
- }
-
- // Exposes the ability to update auth errors to tests.
- void UpdateAuthErrorForTesting(const std::string& account_id,
- const GoogleServiceAuthError& error) {
- UpdateAuthError(account_id, error);
- }
-
- private:
- friend class identity::IdentityManager;
-
- // OAuth2TokenService::Observer implementation.
- void OnRefreshTokenAvailable(const std::string& account_id) override;
- void OnRefreshTokenRevoked(const std::string& account_id) override;
- void OnRefreshTokensLoaded() override;
-
- // Creates a new device ID if there are no accounts, or if the current device
- // ID is empty.
- void RecreateDeviceIdIfNeeded();
-
- PrefService* user_prefs_;
-
- // Whether all credentials have been loaded.
- bool all_credentials_loaded_;
-
- signin_metrics::SourceForRefreshTokenOperation update_refresh_token_source_ =
- signin_metrics::SourceForRefreshTokenOperation::kUnknown;
-
- DISALLOW_COPY_AND_ASSIGN(ProfileOAuth2TokenService);
-};
-
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_H_
diff --git a/chromium/components/signin/core/browser/resources/OWNERS b/chromium/components/signin/core/browser/resources/OWNERS
new file mode 100644
index 00000000000..c05db2e16e1
--- /dev/null
+++ b/chromium/components/signin/core/browser/resources/OWNERS
@@ -0,0 +1,2 @@
+# For trivial or mechanical horizontal JS/CSS/HTML changes.
+file://ui/webui/PLATFORM_OWNERS
diff --git a/chromium/components/signin/core/browser/resources/signin_index.html b/chromium/components/signin/core/browser/resources/signin_index.html
index 64d66020dcb..b54d72bbf19 100644
--- a/chromium/components/signin/core/browser/resources/signin_index.html
+++ b/chromium/components/signin/core/browser/resources/signin_index.html
@@ -1,15 +1,15 @@
<!doctype html>
-<html dir="$i18n{textdirection}" lang="$i18n{language}">
+<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/util.js"></script>
<script src="chrome://resources/js/load_time_data.js"></script>
<script src="strings.js"></script>
- <if expr="is_ios">
- <!-- TODO(crbug.com/487000): Remove this once injected by the web layer. -->
- <script src="chrome://resources/js/ios/web_ui.js"></script>
- </if>
+<if expr="is_ios">
+ <!-- TODO(crbug.com/487000): Remove this once injected by the web layer. -->
+ <script src="chrome://resources/js/ios/web_ui.js"></script>
+</if>
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
<link rel="stylesheet" type="text/css" href="signin_index.css">
</head>
diff --git a/chromium/components/signin/core/browser/signin_error_controller.cc b/chromium/components/signin/core/browser/signin_error_controller.cc
index e3e4668f03e..bbfd519f5a0 100644
--- a/chromium/components/signin/core/browser/signin_error_controller.cc
+++ b/chromium/components/signin/core/browser/signin_error_controller.cc
@@ -4,11 +4,11 @@
#include "components/signin/core/browser/signin_error_controller.h"
-#include "components/signin/core/browser/signin_metrics.h"
+#include "components/signin/public/base/signin_metrics.h"
SigninErrorController::SigninErrorController(
AccountMode mode,
- identity::IdentityManager* identity_manager)
+ signin::IdentityManager* identity_manager)
: account_mode_(mode),
identity_manager_(identity_manager),
scoped_identity_manager_observer_(this),
diff --git a/chromium/components/signin/core/browser/signin_error_controller.h b/chromium/components/signin/core/browser/signin_error_controller.h
index 311111985fe..b1f64862ecc 100644
--- a/chromium/components/signin/core/browser/signin_error_controller.h
+++ b/chromium/components/signin/core/browser/signin_error_controller.h
@@ -13,15 +13,15 @@
#include "base/observer_list.h"
#include "base/scoped_observer.h"
#include "components/keyed_service/core/keyed_service.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
#include "google_apis/gaia/google_service_auth_error.h"
-#include "services/identity/public/cpp/identity_manager.h"
// Keep track of auth errors and expose them to observers in the UI. Services
// that wish to expose auth errors to the user should register an
// AuthStatusProvider to report their current authentication state, and should
// invoke AuthStatusChanged() when their authentication state may have changed.
class SigninErrorController : public KeyedService,
- public identity::IdentityManager::Observer {
+ public signin::IdentityManager::Observer {
public:
enum class AccountMode {
// Signin error controller monitors all the accounts. When multiple accounts
@@ -42,7 +42,7 @@ class SigninErrorController : public KeyedService,
};
SigninErrorController(AccountMode mode,
- identity::IdentityManager* identity_manager);
+ signin::IdentityManager* identity_manager);
~SigninErrorController() override;
// KeyedService implementation:
@@ -75,7 +75,7 @@ class SigninErrorController : public KeyedService,
const std::string& prev_account_id,
const GoogleServiceAuthError::State& prev_error_state);
- // identity::IdentityManager::Observer:
+ // signin::IdentityManager::Observer:
void OnEndBatchOfRefreshTokenStateChanges() override;
void OnErrorStateOfRefreshTokenUpdatedForAccount(
const CoreAccountInfo& account_info,
@@ -86,9 +86,9 @@ class SigninErrorController : public KeyedService,
const CoreAccountInfo& previous_primary_account_info) override;
const AccountMode account_mode_;
- identity::IdentityManager* identity_manager_;
+ signin::IdentityManager* identity_manager_;
- ScopedObserver<identity::IdentityManager, SigninErrorController>
+ ScopedObserver<signin::IdentityManager, SigninErrorController>
scoped_identity_manager_observer_;
// The account that generated the last auth error.
diff --git a/chromium/components/signin/core/browser/signin_error_controller_unittest.cc b/chromium/components/signin/core/browser/signin_error_controller_unittest.cc
index 90b353983bc..92b478fb49d 100644
--- a/chromium/components/signin/core/browser/signin_error_controller_unittest.cc
+++ b/chromium/components/signin/core/browser/signin_error_controller_unittest.cc
@@ -12,8 +12,8 @@
#include "base/scoped_observer.h"
#include "base/stl_util.h"
#include "base/test/scoped_task_environment.h"
-#include "services/identity/public/cpp/identity_test_environment.h"
-#include "services/identity/public/cpp/primary_account_mutator.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "components/signin/public/identity_manager/primary_account_mutator.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -36,7 +36,7 @@ TEST(SigninErrorControllerTest, SingleAccount) {
EXPECT_CALL(observer, OnErrorChanged()).Times(0);
base::test::ScopedTaskEnvironment task_environment;
- identity::IdentityTestEnvironment identity_test_env;
+ signin::IdentityTestEnvironment identity_test_env;
SigninErrorController error_controller(
SigninErrorController::AccountMode::ANY_ACCOUNT,
identity_test_env.identity_manager());
@@ -65,7 +65,7 @@ TEST(SigninErrorControllerTest, SingleAccount) {
::testing::Mock::VerifyAndClearExpectations(&observer);
GoogleServiceAuthError error2 =
- GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED);
+ GoogleServiceAuthError(GoogleServiceAuthError::USER_NOT_SIGNED_UP);
EXPECT_CALL(observer, OnErrorChanged()).Times(1);
identity_test_env.UpdatePersistentErrorOfRefreshTokenForAccount(
test_account_id, error2);
@@ -84,7 +84,7 @@ TEST(SigninErrorControllerTest, SingleAccount) {
TEST(SigninErrorControllerTest, AccountTransitionAnyAccount) {
base::test::ScopedTaskEnvironment task_environment;
- identity::IdentityTestEnvironment identity_test_env;
+ signin::IdentityTestEnvironment identity_test_env;
std::string test_account_id =
identity_test_env.MakeAccountAvailable(kTestEmail).account_id;
@@ -115,8 +115,8 @@ TEST(SigninErrorControllerTest, AccountTransitionAnyAccount) {
#if !defined(OS_CHROMEOS)
TEST(SigninErrorControllerTest, AccountTransitionPrimaryAccount) {
base::test::ScopedTaskEnvironment task_environment;
- identity::IdentityTestEnvironment identity_test_env;
- identity::PrimaryAccountMutator* primary_account_mutator =
+ signin::IdentityTestEnvironment identity_test_env;
+ signin::PrimaryAccountMutator* primary_account_mutator =
identity_test_env.identity_manager()->GetPrimaryAccountMutator();
std::string test_account_id =
@@ -144,7 +144,7 @@ TEST(SigninErrorControllerTest, AccountTransitionPrimaryAccount) {
// Change the primary account to the account with an error and check that the
// error controller updates its error status accordingly.
primary_account_mutator->ClearPrimaryAccount(
- identity::PrimaryAccountMutator::ClearAccountsAction::kKeepAll,
+ signin::PrimaryAccountMutator::ClearAccountsAction::kKeepAll,
signin_metrics::FORCE_SIGNOUT_ALWAYS_ALLOWED_FOR_TEST,
signin_metrics::SignoutDelete::IGNORE_METRIC);
identity_test_env.SetPrimaryAccount(kTestEmail);
@@ -160,7 +160,7 @@ TEST(SigninErrorControllerTest, AccountTransitionPrimaryAccount) {
// Change the primary account again and check that the error controller
// updates its error status accordingly.
primary_account_mutator->ClearPrimaryAccount(
- identity::PrimaryAccountMutator::ClearAccountsAction::kKeepAll,
+ signin::PrimaryAccountMutator::ClearAccountsAction::kKeepAll,
signin_metrics::FORCE_SIGNOUT_ALWAYS_ALLOWED_FOR_TEST,
signin_metrics::SignoutDelete::IGNORE_METRIC);
identity_test_env.SetPrimaryAccount(kOtherTestEmail);
@@ -170,7 +170,7 @@ TEST(SigninErrorControllerTest, AccountTransitionPrimaryAccount) {
// Sign out and check that that the error controller updates its error status
// accordingly.
primary_account_mutator->ClearPrimaryAccount(
- identity::PrimaryAccountMutator::ClearAccountsAction::kKeepAll,
+ signin::PrimaryAccountMutator::ClearAccountsAction::kKeepAll,
signin_metrics::FORCE_SIGNOUT_ALWAYS_ALLOWED_FOR_TEST,
signin_metrics::SignoutDelete::IGNORE_METRIC);
ASSERT_FALSE(error_controller.HasError());
@@ -180,7 +180,7 @@ TEST(SigninErrorControllerTest, AccountTransitionPrimaryAccount) {
// Verify that SigninErrorController handles errors properly.
TEST(SigninErrorControllerTest, AuthStatusEnumerateAllErrors) {
base::test::ScopedTaskEnvironment task_environment;
- identity::IdentityTestEnvironment identity_test_env;
+ signin::IdentityTestEnvironment identity_test_env;
std::string test_account_id =
identity_test_env.MakeAccountAvailable(kTestEmail).account_id;
@@ -193,23 +193,16 @@ TEST(SigninErrorControllerTest, AuthStatusEnumerateAllErrors) {
GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
GoogleServiceAuthError::USER_NOT_SIGNED_UP,
GoogleServiceAuthError::CONNECTION_FAILED,
- GoogleServiceAuthError::CAPTCHA_REQUIRED,
- GoogleServiceAuthError::ACCOUNT_DELETED,
- GoogleServiceAuthError::ACCOUNT_DISABLED,
GoogleServiceAuthError::SERVICE_UNAVAILABLE,
- GoogleServiceAuthError::TWO_FACTOR,
GoogleServiceAuthError::REQUEST_CANCELED,
- GoogleServiceAuthError::HOSTED_NOT_ALLOWED_DEPRECATED,
GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE,
- GoogleServiceAuthError::SERVICE_ERROR,
- GoogleServiceAuthError::WEB_LOGIN_REQUIRED};
- static_assert(base::size(table) == GoogleServiceAuthError::NUM_STATES,
- "table array does not match the number of auth error types");
+ GoogleServiceAuthError::SERVICE_ERROR};
+ static_assert(
+ base::size(table) == GoogleServiceAuthError::NUM_STATES -
+ GoogleServiceAuthError::kDeprecatedStateCount,
+ "table array does not match the number of auth error types");
for (GoogleServiceAuthError::State state : table) {
- if (GoogleServiceAuthError::IsDeprecated(state))
- continue;
-
GoogleServiceAuthError error(state);
if (error.IsTransientError())
@@ -234,7 +227,7 @@ TEST(SigninErrorControllerTest, AuthStatusEnumerateAllErrors) {
// Verify that existing error is not replaced by new error.
TEST(SigninErrorControllerTest, AuthStatusChange) {
base::test::ScopedTaskEnvironment task_environment;
- identity::IdentityTestEnvironment identity_test_env;
+ signin::IdentityTestEnvironment identity_test_env;
std::string test_account_id =
identity_test_env.MakeAccountAvailable(kTestEmail).account_id;
@@ -290,7 +283,7 @@ TEST(SigninErrorControllerTest, AuthStatusChange) {
TEST(SigninErrorControllerTest,
PrimaryAccountErrorsArePreferredToSecondaryAccountErrors) {
base::test::ScopedTaskEnvironment task_environment;
- identity::IdentityTestEnvironment identity_test_env;
+ signin::IdentityTestEnvironment identity_test_env;
AccountInfo primary_account_info =
identity_test_env.MakePrimaryAccountAvailable(kPrimaryAccountEmail);
@@ -337,7 +330,7 @@ TEST(SigninErrorControllerTest,
TEST(SigninErrorControllerTest, PrimaryAccountErrorsAreSticky) {
base::test::ScopedTaskEnvironment task_environment;
- identity::IdentityTestEnvironment identity_test_env;
+ signin::IdentityTestEnvironment identity_test_env;
AccountInfo primary_account_info =
identity_test_env.MakePrimaryAccountAvailable(kPrimaryAccountEmail);
diff --git a/chromium/components/signin/core/browser/signin_header_helper.cc b/chromium/components/signin/core/browser/signin_header_helper.cc
index 3be4ed58894..cf0a3877b3e 100644
--- a/chromium/components/signin/core/browser/signin_header_helper.cc
+++ b/chromium/components/signin/core/browser/signin_header_helper.cc
@@ -22,16 +22,6 @@
namespace signin {
-namespace {
-// Buckes of the |Signin.RequestHeaderOperation.Dice| and
-// |SigninRequestHeaderOperation.Mirror| histograms.
-enum class RequestHeaderOperation {
- kHeaderAdded = 0,
- kHeaderRemoved = 1,
- kMaxValue = kHeaderRemoved
-};
-} // namespace
-
const char kChromeConnectedHeader[] = "X-Chrome-Connected";
const char kDiceRequestHeader[] = "X-Chrome-ID-Consistency-Request";
const char kDiceResponseHeader[] = "X-Chrome-ID-Consistency-Response";
@@ -106,8 +96,7 @@ std::string BuildMirrorRequestCookieIfPossible(
url, account_id, account_consistency, cookie_settings, profile_mode_mask);
}
-SigninHeaderHelper::SigninHeaderHelper(const std::string& histogram_suffix)
- : histogram_suffix_(histogram_suffix) {}
+SigninHeaderHelper::SigninHeaderHelper() = default;
SigninHeaderHelper::~SigninHeaderHelper() = default;
bool SigninHeaderHelper::AppendOrRemoveRequestHeader(
@@ -122,16 +111,12 @@ bool SigninHeaderHelper::AppendOrRemoveRequestHeader(
if (!redirect_url.is_empty() && request->HasHeader(header_name) &&
IsUrlEligibleForRequestHeader(request->GetUrl()) &&
!IsUrlEligibleForRequestHeader(redirect_url)) {
- base::UmaHistogramEnumeration(
- GetSuffixedHistogramName("Signin.RequestHeaderOperation"),
- RequestHeaderOperation::kHeaderRemoved);
+ VLOG(1) << "Sign-in request header [" << header_name << "] removed.";
request->RemoveRequestHeaderByName(header_name);
}
return false;
}
- base::UmaHistogramEnumeration(
- GetSuffixedHistogramName("Signin.RequestHeaderOperation"),
- RequestHeaderOperation::kHeaderAdded);
+ VLOG(1) << "Sign-in request header [" << header_name << "] added.";
request->SetExtraHeaderByName(header_name, header_value);
return true;
}
@@ -159,11 +144,6 @@ SigninHeaderHelper::ParseAccountConsistencyResponseHeader(
return dictionary;
}
-std::string SigninHeaderHelper::GetSuffixedHistogramName(
- const std::string& histogram_name) {
- return histogram_name + "." + histogram_suffix_;
-}
-
void AppendOrRemoveMirrorRequestHeader(
RequestAdapter* request,
const GURL& redirect_url,
diff --git a/chromium/components/signin/core/browser/signin_header_helper.h b/chromium/components/signin/core/browser/signin_header_helper.h
index ab001f6592d..ac718de9f54 100644
--- a/chromium/components/signin/core/browser/signin_header_helper.h
+++ b/chromium/components/signin/core/browser/signin_header_helper.h
@@ -10,8 +10,8 @@
#include <vector>
#include "components/prefs/pref_member.h"
-#include "components/signin/core/browser/account_consistency_method.h"
-#include "components/signin/core/browser/signin_buildflags.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/base/signin_buildflags.h"
#include "url/gurl.h"
namespace content_settings {
@@ -42,7 +42,7 @@ extern const char kDiceResponseHeader[];
// perform.
// A Java counterpart will be generated for this enum.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.signin
-enum GAIAServiceType {
+enum GAIAServiceType : int {
GAIA_SERVICE_TYPE_NONE = 0, // No Gaia response header.
GAIA_SERVICE_TYPE_SIGNOUT, // Logout all existing sessions.
GAIA_SERVICE_TYPE_INCOGNITO, // Open an incognito tab.
@@ -181,7 +181,7 @@ class SigninHeaderHelper {
const content_settings::CookieSettings* cookie_settings) = 0;
protected:
- explicit SigninHeaderHelper(const std::string& histogram_suffix);
+ SigninHeaderHelper();
virtual ~SigninHeaderHelper();
// Dictionary of fields in a account consistency response header.
@@ -196,13 +196,6 @@ class SigninHeaderHelper {
// Returns whether the url is eligible for the request header.
virtual bool IsUrlEligibleForRequestHeader(const GURL& url) = 0;
- // Returns a string that can be used as a histogram name. Its value ios
- // "|histogram_name|.|histogram_suffix_|".
- std::string GetSuffixedHistogramName(const std::string& histogram_name);
-
- // Suffix to be used by the histograms recodered by this SigninHeaderHelper.
- std::string histogram_suffix_;
-
DISALLOW_COPY_AND_ASSIGN(SigninHeaderHelper);
};
diff --git a/chromium/components/signin/core/browser/signin_header_helper_unittest.cc b/chromium/components/signin/core/browser/signin_header_helper_unittest.cc
index 61487c836db..c36fd26f945 100644
--- a/chromium/components/signin/core/browser/signin_header_helper_unittest.cc
+++ b/chromium/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -14,9 +14,9 @@
#include "build/build_config.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/prefs/pref_member.h"
-#include "components/signin/core/browser/account_consistency_method.h"
#include "components/signin/core/browser/chrome_connected_header_helper.h"
-#include "components/signin/core/browser/signin_buildflags.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/base/signin_buildflags.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
diff --git a/chromium/components/signin/core/browser/signin_investigator.cc b/chromium/components/signin/core/browser/signin_investigator.cc
index 7dc1236ecc2..3c77124bd15 100644
--- a/chromium/components/signin/core/browser/signin_investigator.cc
+++ b/chromium/components/signin/core/browser/signin_investigator.cc
@@ -6,21 +6,13 @@
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
-#include "components/signin/core/browser/signin_metrics.h"
-#include "components/signin/core/browser/signin_pref_names.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/base/signin_pref_names.h"
#include "google_apis/gaia/gaia_auth_util.h"
using signin_metrics::AccountEquality;
using signin_metrics::LogAccountEquality;
-namespace {
-void LogSigninScenario(InvestigatedScenario scenario) {
- UMA_HISTOGRAM_ENUMERATION(
- "Signin.InvestigatedScenario", static_cast<int>(scenario),
- static_cast<int>(InvestigatedScenario::NUM_ENTRIES));
-}
-} // namespace
-
SigninInvestigator::SigninInvestigator(const std::string& current_email,
const std::string& current_id,
DependencyProvider* provider)
@@ -62,19 +54,13 @@ InvestigatedScenario SigninInvestigator::Investigate() {
if (provider_->GetPrefs()
->GetString(prefs::kGoogleServicesLastUsername)
.empty()) {
- scenario = IsUpgradeHighRisk() ? InvestigatedScenario::UPGRADE_HIGH_RISK
- : InvestigatedScenario::UPGRADE_LOW_RISK;
+ scenario = InvestigatedScenario::kFirstSignIn;
} else if (AreAccountsEqualWithFallback()) {
- scenario = InvestigatedScenario::SAME_ACCOUNT;
+ scenario = InvestigatedScenario::kSameAccount;
} else {
- scenario = InvestigatedScenario::DIFFERENT_ACCOUNT;
+ scenario = InvestigatedScenario::kDifferentAccount;
}
- LogSigninScenario(scenario);
+ UMA_HISTOGRAM_ENUMERATION("Signin.InvestigatedScenario", scenario);
return scenario;
}
-
-bool SigninInvestigator::IsUpgradeHighRisk() {
- // TODO(skym): Add logic to make this decision, crbug.com/572754.
- return false;
-}
diff --git a/chromium/components/signin/core/browser/signin_investigator.h b/chromium/components/signin/core/browser/signin_investigator.h
index ce40682bfda..301e9f9eb50 100644
--- a/chromium/components/signin/core/browser/signin_investigator.h
+++ b/chromium/components/signin/core/browser/signin_investigator.h
@@ -10,23 +10,24 @@
#include "base/macros.h"
#include "components/prefs/pref_service.h"
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
// A Java counterpart will be generated for this enum.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.signin
// Broad categorization of signin type from investigation.
enum class InvestigatedScenario : int {
// First signin and should not be warned. As little friction as possible
// should get between the user and signing in.
- UPGRADE_LOW_RISK = 0,
- // First signin but should be warned. There is a reason to believe this signin
- // may not be what the user wanted.
- UPGRADE_HIGH_RISK,
+ kFirstSignIn = 0,
+ // Was never used (see crbug.com/983183, crbug.com/572754).
+ kDeprecatedUpgradeHighRisk = 1,
// Relogging with the same account.
- SAME_ACCOUNT,
+ kSameAccount = 2,
// User is switching accounts, can be very dangerous depending on the amount
// of local syncable data.
- DIFFERENT_ACCOUNT,
+ kDifferentAccount = 3,
// Always the last enumerated type.
- NUM_ENTRIES,
+ kMaxValue = kDifferentAccount,
};
// Performs various checks with the current account being used to login in and
@@ -64,12 +65,6 @@ class SigninInvestigator {
// slightly more strict than the version AccountId defines as == operator.
bool AreAccountsEqualWithFallback();
- // Determines if the current upgrade signin is high risk or not. Reasons for
- // being high risk may include things like this profile/device may be shared
- // among multiple people, or there may be old syncable data created by other
- // users that do not currently use the profile/device.
- bool IsUpgradeHighRisk();
-
std::string current_email_;
std::string current_id_;
diff --git a/chromium/components/signin/core/browser/signin_investigator_unittest.cc b/chromium/components/signin/core/browser/signin_investigator_unittest.cc
index cb861a03128..31df9131e47 100644
--- a/chromium/components/signin/core/browser/signin_investigator_unittest.cc
+++ b/chromium/components/signin/core/browser/signin_investigator_unittest.cc
@@ -8,10 +8,10 @@
#include "base/test/scoped_task_environment.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/signin/core/browser/signin_investigator.h"
-#include "components/signin/core/browser/signin_metrics.h"
-#include "components/signin/core/browser/signin_pref_names.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "services/identity/public/cpp/identity_test_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
using signin_metrics::AccountEquality;
@@ -35,7 +35,7 @@ class FakeProvider : public SigninInvestigator::DependencyProvider {
private:
base::test::ScopedTaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable prefs_;
- identity::IdentityTestEnvironment identity_test_env_;
+ signin::IdentityTestEnvironment identity_test_env_;
};
} // namespace
@@ -116,14 +116,14 @@ TEST_F(SigninInvestigatorTest, EqualityDifferentEmailFallbackEmptyCurrentId) {
TEST_F(SigninInvestigatorTest, InvestigateSameAccount) {
AssertInvestigatedScenario(kSameEmail, kSameId,
- InvestigatedScenario::SAME_ACCOUNT);
+ InvestigatedScenario::kSameAccount);
}
-TEST_F(SigninInvestigatorTest, InvestigateUpgrade) {
- AssertInvestigatedScenario("", "", InvestigatedScenario::UPGRADE_LOW_RISK);
+TEST_F(SigninInvestigatorTest, InvestigateFirstSignIn) {
+ AssertInvestigatedScenario("", "", InvestigatedScenario::kFirstSignIn);
}
TEST_F(SigninInvestigatorTest, InvestigateDifferentAccount) {
AssertInvestigatedScenario(kDifferentEmail, kDifferentId,
- InvestigatedScenario::DIFFERENT_ACCOUNT);
+ InvestigatedScenario::kDifferentAccount);
}
diff --git a/chromium/components/signin/core/browser/signin_manager.cc b/chromium/components/signin/core/browser/signin_manager.cc
deleted file mode 100644
index d97a3e1c54a..00000000000
--- a/chromium/components/signin/core/browser/signin_manager.cc
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/core/browser/signin_manager.h"
-
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-#include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/identity_utils.h"
-#include "components/signin/core/browser/signin_metrics.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "google_apis/gaia/gaia_auth_util.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/gaia_urls.h"
-#include "google_apis/gaia/google_service_auth_error.h"
-#include "third_party/icu/source/i18n/unicode/regex.h"
-
-SigninManager::SigninManager(
- SigninClient* client,
- ProfileOAuth2TokenService* token_service,
- AccountTrackerService* account_tracker_service,
- GaiaCookieManagerService* cookie_manager_service,
- signin::AccountConsistencyMethod account_consistency)
- : SigninManagerBase(client,
- token_service,
- account_tracker_service,
- cookie_manager_service,
- account_consistency),
- weak_pointer_factory_(this) {}
-
-SigninManager::~SigninManager() {
- token_service()->RemoveObserver(this);
- local_state_pref_registrar_.RemoveAll();
-}
-
-void SigninManager::FinalizeInitBeforeLoadingRefreshTokens(
- PrefService* local_state) {
- // local_state can be null during unit tests.
- if (local_state) {
- local_state_pref_registrar_.Init(local_state);
- local_state_pref_registrar_.Add(
- prefs::kGoogleServicesUsernamePattern,
- base::Bind(&SigninManager::OnGoogleServicesUsernamePatternChanged,
- weak_pointer_factory_.GetWeakPtr()));
- }
- signin_allowed_.Init(prefs::kSigninAllowed, signin_client()->GetPrefs(),
- base::Bind(&SigninManager::OnSigninAllowedPrefChanged,
- base::Unretained(this)));
-
- AccountInfo account_info = GetAuthenticatedAccountInfo();
- if (!account_info.account_id.empty() &&
- (!IsAllowedUsername(account_info.email) || !IsSigninAllowed())) {
- // User is signed in, but the username is invalid or signin is no longer
- // allowed, so the user must be sign out.
- //
- // This may happen in the following cases:
- // a. The user has toggled off signin allowed in settings.
- // b. The administrator changed the policy since the last signin.
- //
- // Note: The token service has not yet loaded its credentials, so accounts
- // cannot be revoked here.
- //
- // On desktop, when SigninManager is initializing, the profile was not yet
- // marked with sign out allowed. Therefore sign out is not allowed and all
- // calls to SignOut methods are no-op.
- //
- // TODO(msarda): SignOut methods do not gurantee that sign out can actually
- // be done (this depends on whether sign out is allowed). Add a check here
- // on desktop to make it clear that SignOut does not do anything.
- SignOutAndKeepAllAccounts(signin_metrics::SIGNIN_PREF_CHANGED_DURING_SIGNIN,
- signin_metrics::SignoutDelete::IGNORE_METRIC);
- }
-
- // It is important to only load credentials after starting to observe the
- // token service.
- token_service()->AddObserver(this);
-}
-
-void SigninManager::OnGoogleServicesUsernamePatternChanged() {
- if (IsAuthenticated() &&
- !IsAllowedUsername(GetAuthenticatedAccountInfo().email)) {
- // Signed in user is invalid according to the current policy so sign
- // the user out.
- SignOut(signin_metrics::GOOGLE_SERVICE_NAME_PATTERN_CHANGED,
- signin_metrics::SignoutDelete::IGNORE_METRIC);
- }
-}
-
-bool SigninManager::IsSigninAllowed() const {
- return signin_allowed_.GetValue();
-}
-
-void SigninManager::SetSigninAllowed(bool allowed) {
- signin_allowed_.SetValue(allowed);
-}
-
-void SigninManager::OnSigninAllowedPrefChanged() {
- if (!IsSigninAllowed() && IsAuthenticated()) {
- VLOG(0) << "IsSigninAllowed() set to false, signing out the user";
- SignOut(signin_metrics::SIGNOUT_PREF_CHANGED,
- signin_metrics::SignoutDelete::IGNORE_METRIC);
- }
-}
-
-// static
-SigninManager* SigninManager::FromSigninManagerBase(
- SigninManagerBase* manager) {
- return static_cast<SigninManager*>(manager);
-}
-
-bool SigninManager::IsAllowedUsername(const std::string& username) const {
- const PrefService* local_state = local_state_pref_registrar_.prefs();
- if (!local_state)
- return true; // In a unit test with no local state - all names are allowed.
-
- std::string pattern =
- local_state->GetString(prefs::kGoogleServicesUsernamePattern);
- return identity::IsUsernameAllowedByPattern(username, pattern);
-}
-
-void SigninManager::SignIn(const std::string& username) {
- AccountInfo info =
- account_tracker_service()->FindAccountInfoByEmail(username);
- DCHECK(!info.gaia.empty());
- DCHECK(!info.email.empty());
-
- bool reauth_in_progress = IsAuthenticated();
-
- signin_client()->GetPrefs()->SetInt64(
- prefs::kSignedInTime,
- base::Time::Now().ToDeltaSinceWindowsEpoch().InMicroseconds());
-
- SetAuthenticatedAccountInfo(info.gaia, info.email);
-
- if (!reauth_in_progress)
- FireGoogleSigninSucceeded();
-
- signin_metrics::LogSigninProfile(signin_client()->IsFirstRun(),
- signin_client()->GetInstallDate());
-}
-
-void SigninManager::FireGoogleSigninSucceeded() {
- const AccountInfo account_info = GetAuthenticatedAccountInfo();
- if (observer_ != nullptr) {
- observer_->GoogleSigninSucceeded(account_info);
- }
-}
-
-void SigninManager::OnRefreshTokensLoaded() {
- token_service()->RemoveObserver(this);
-
- if (account_tracker_service()->GetMigrationState() ==
- AccountTrackerService::MIGRATION_IN_PROGRESS) {
- account_tracker_service()->SetMigrationDone();
- }
-
- // Remove account information from the account tracker service if needed.
- if (token_service()->HasLoadCredentialsFinishedWithNoErrors()) {
- std::vector<AccountInfo> accounts_in_tracker_service =
- account_tracker_service()->GetAccounts();
- for (const auto& account : accounts_in_tracker_service) {
- if (GetAuthenticatedAccountId() != account.account_id &&
- !token_service()->RefreshTokenIsAvailable(account.account_id)) {
- DVLOG(0) << "Removed account from account tracker service: "
- << account.account_id;
- account_tracker_service()->RemoveAccount(account.account_id);
- }
- }
- }
-}
diff --git a/chromium/components/signin/core/browser/signin_manager.h b/chromium/components/signin/core/browser/signin_manager.h
deleted file mode 100644
index c70c9d93b6b..00000000000
--- a/chromium/components/signin/core/browser/signin_manager.h
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// The signin manager encapsulates some functionality tracking
-// which user is signed in. See SigninManagerBase for full description of
-// responsibilities. The class defined in this file provides functionality
-// required by all platforms except Chrome OS.
-
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_H_
-
-#include "build/build_config.h"
-
-#if defined(OS_CHROMEOS)
-
-#include "components/signin/core/browser/signin_manager_base.h"
-
-#else
-
-#include <set>
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/gtest_prod_util.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/observer_list.h"
-#include "base/strings/string_piece.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "components/prefs/pref_change_registrar.h"
-#include "components/prefs/pref_member.h"
-#include "components/signin/core/browser/account_info.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_manager_base.h"
-#include "components/signin/core/browser/signin_metrics.h"
-#include "net/cookies/canonical_cookie.h"
-
-class PrefService;
-
-namespace identity {
-class IdentityManager;
-} // namespace identity
-
-class SigninManager : public SigninManagerBase,
- public OAuth2TokenService::Observer {
- public:
- // This is used to distinguish URLs belonging to the special web signin flow
- // running in the special signin process from other URLs on the same domain.
- // We do not grant WebUI privilieges / bindings to this process or to URLs of
- // this scheme; enforcement of privileges is handled separately by
- // OneClickSigninHelper.
- static const char kChromeSigninEffectiveSite[];
-
- SigninManager(SigninClient* client,
- ProfileOAuth2TokenService* token_service,
- AccountTrackerService* account_tracker_service,
- GaiaCookieManagerService* cookie_manager_service,
- signin::AccountConsistencyMethod account_consistency);
- ~SigninManager() override;
-
- // Returns |manager| as a SigninManager instance. Relies on the fact that on
- // platforms where signin_manager.* is built, all SigninManagerBase instances
- // are actually SigninManager instances.
- static SigninManager* FromSigninManagerBase(SigninManagerBase* manager);
-
- // On platforms where SigninManager is responsible for dealing with
- // invalid username policy updates, we need to check this during
- // initialization and sign the user out.
- void FinalizeInitBeforeLoadingRefreshTokens(
- PrefService* local_state) override;
-
- // Signs a user in. SigninManager assumes that |username| can be used to look
- // up the corresponding account_id and gaia_id for this email.
- void SignIn(const std::string& username);
-
- // Returns true if a signin to Chrome is allowed (by policy or pref).
- // TODO(crbug.com/806778): this method should not be used externally,
- // instead the value of the kSigninAllowed preference should be checked.
- // Once all external code has been modified, this method will be removed.
- bool IsSigninAllowed() const;
-
- // Sets whether sign-in is allowed or not.
- void SetSigninAllowed(bool allowed);
-
- private:
- friend class identity::IdentityManager;
- FRIEND_TEST_ALL_PREFIXES(SigninManagerTest, Prohibited);
- FRIEND_TEST_ALL_PREFIXES(SigninManagerTest, TestAlternateWildcard);
-
- // Send all observers |GoogleSigninSucceeded| notifications.
- void FireGoogleSigninSucceeded();
-
- // OAuth2TokenService::Observer:
- void OnRefreshTokensLoaded() override;
-
- void OnSigninAllowedPrefChanged();
- void OnGoogleServicesUsernamePatternChanged();
-
- // Returns true if the passed username is allowed by policy.
- bool IsAllowedUsername(const std::string& username) const;
-
- // Helper object to listen for changes to signin preferences stored in non-
- // profile-specific local prefs (like kGoogleServicesUsernamePattern).
- PrefChangeRegistrar local_state_pref_registrar_;
-
- // Helper object to listen for changes to the signin allowed preference.
- BooleanPrefMember signin_allowed_;
-
- base::WeakPtrFactory<SigninManager> weak_pointer_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(SigninManager);
-};
-
-#endif // !defined(OS_CHROMEOS)
-
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_H_
diff --git a/chromium/components/signin/core/browser/signin_status_metrics_provider.cc b/chromium/components/signin/core/browser/signin_status_metrics_provider.cc
index 5bc15bf236d..279eab33886 100644
--- a/chromium/components/signin/core/browser/signin_status_metrics_provider.cc
+++ b/chromium/components/signin/core/browser/signin_status_metrics_provider.cc
@@ -18,8 +18,7 @@ SigninStatusMetricsProvider::SigninStatusMetricsProvider(
bool is_test)
: delegate_(std::move(delegate)),
scoped_observer_(this),
- is_test_(is_test),
- weak_ptr_factory_(this) {
+ is_test_(is_test) {
DCHECK(delegate_ || is_test_);
if (is_test_)
return;
@@ -53,7 +52,7 @@ SigninStatusMetricsProvider::CreateInstance(
}
void SigninStatusMetricsProvider::OnIdentityManagerCreated(
- identity::IdentityManager* identity_manager) {
+ signin::IdentityManager* identity_manager) {
// Whenever a new profile is created, a new IdentityManager will be created
// for it. This ensures that all sign-in or sign-out actions of all opened
// profiles are being monitored.
@@ -69,7 +68,7 @@ void SigninStatusMetricsProvider::OnIdentityManagerCreated(
}
void SigninStatusMetricsProvider::OnIdentityManagerShutdown(
- identity::IdentityManager* identity_manager) {
+ signin::IdentityManager* identity_manager) {
if (scoped_observer_.IsObserving(identity_manager))
scoped_observer_.Remove(identity_manager);
}
@@ -102,7 +101,7 @@ void SigninStatusMetricsProvider::Initialize() {
delegate_->Initialize();
// Start observing all already-created IdentityManagers.
- for (identity::IdentityManager* manager :
+ for (signin::IdentityManager* manager :
delegate_->GetIdentityManagersForAllAccounts()) {
DCHECK(!scoped_observer_.IsObserving(manager));
scoped_observer_.Add(manager);
diff --git a/chromium/components/signin/core/browser/signin_status_metrics_provider.h b/chromium/components/signin/core/browser/signin_status_metrics_provider.h
index 1a027dcc951..f28f472ffc6 100644
--- a/chromium/components/signin/core/browser/signin_status_metrics_provider.h
+++ b/chromium/components/signin/core/browser/signin_status_metrics_provider.h
@@ -16,7 +16,7 @@
#include "build/build_config.h"
#include "components/signin/core/browser/signin_status_metrics_provider_base.h"
#include "components/signin/core/browser/signin_status_metrics_provider_delegate.h"
-#include "services/identity/public/cpp/identity_manager.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
namespace metrics {
class ChromeUserMetricsExtension;
@@ -28,7 +28,7 @@ class SigninStatusMetricsProviderDelegate;
// record the value into a histogram before UMA log is uploaded on platform
// Windows, Linux, Mac and Android.
class SigninStatusMetricsProvider : public SigninStatusMetricsProviderBase,
- public identity::IdentityManager::Observer {
+ public signin::IdentityManager::Observer {
public:
~SigninStatusMetricsProvider() override;
@@ -41,10 +41,10 @@ class SigninStatusMetricsProvider : public SigninStatusMetricsProviderBase,
std::unique_ptr<SigninStatusMetricsProviderDelegate> delegate);
// Update the sign-in status when a IdentityManager is created.
- void OnIdentityManagerCreated(identity::IdentityManager* identity_manager);
+ void OnIdentityManagerCreated(signin::IdentityManager* identity_manager);
// Update the sign-in status when a IdentityManager is shut down.
- void OnIdentityManagerShutdown(identity::IdentityManager* identity_manager);
+ void OnIdentityManagerShutdown(signin::IdentityManager* identity_manager);
// Updates the initial sign-in status. For testing purpose only.
void UpdateInitialSigninStatusForTesting(size_t total_count,
@@ -90,13 +90,13 @@ class SigninStatusMetricsProvider : public SigninStatusMetricsProviderBase,
// Used to track the IdentityManagers that this instance is observing so that
// this instance can be removed as an observer on its destruction.
- ScopedObserver<identity::IdentityManager, identity::IdentityManager::Observer>
+ ScopedObserver<signin::IdentityManager, signin::IdentityManager::Observer>
scoped_observer_;
// Whether the instance is for testing or not.
bool is_test_;
- base::WeakPtrFactory<SigninStatusMetricsProvider> weak_ptr_factory_;
+ base::WeakPtrFactory<SigninStatusMetricsProvider> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SigninStatusMetricsProvider);
};
diff --git a/chromium/components/signin/core/browser/signin_status_metrics_provider_delegate.h b/chromium/components/signin/core/browser/signin_status_metrics_provider_delegate.h
index 763a8b7ccda..b97ee435691 100644
--- a/chromium/components/signin/core/browser/signin_status_metrics_provider_delegate.h
+++ b/chromium/components/signin/core/browser/signin_status_metrics_provider_delegate.h
@@ -14,7 +14,7 @@
class SigninStatusMetricsProvider;
-namespace identity {
+namespace signin {
class IdentityManager;
}
@@ -48,7 +48,7 @@ class SigninStatusMetricsProviderDelegate {
virtual AccountsStatus GetStatusOfAllAccounts() = 0;
// Returns the IdentityManager instance (if any) associated with each account.
- virtual std::vector<identity::IdentityManager*>
+ virtual std::vector<signin::IdentityManager*>
GetIdentityManagersForAllAccounts() = 0;
protected:
diff --git a/chromium/components/signin/internal/identity_manager/BUILD.gn b/chromium/components/signin/internal/identity_manager/BUILD.gn
new file mode 100644
index 00000000000..40caa1eccaf
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/BUILD.gn
@@ -0,0 +1,188 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This target forms the core of the IdentityManager implementation
+# (//components/signin/public/identity_manager/identity_manager.*).
+source_set("identity_manager") {
+ sources = [
+ "account_fetcher_service.cc",
+ "account_fetcher_service.h",
+ "account_info_fetcher.cc",
+ "account_info_fetcher.h",
+ "account_info_util.cc",
+ "account_info_util.h",
+ "account_tracker_service.cc",
+ "account_tracker_service.h",
+ "accounts_cookie_mutator_impl.cc",
+ "accounts_cookie_mutator_impl.h",
+ "child_account_info_fetcher_android.cc",
+ "child_account_info_fetcher_android.h",
+ "diagnostics_provider_impl.cc",
+ "diagnostics_provider_impl.h",
+ "gaia_cookie_manager_service.cc",
+ "gaia_cookie_manager_service.h",
+ "mutable_profile_oauth2_token_service_delegate.cc",
+ "mutable_profile_oauth2_token_service_delegate.h",
+ "oauth2_token_service_delegate_android.cc",
+ "oauth2_token_service_delegate_android.h",
+ "oauth_multilogin_helper.cc",
+ "oauth_multilogin_helper.h",
+ "oauth_multilogin_token_fetcher.cc",
+ "oauth_multilogin_token_fetcher.h",
+ "primary_account_manager.cc",
+ "primary_account_manager.h",
+ "primary_account_mutator_impl.cc",
+ "primary_account_mutator_impl.h",
+ "primary_account_policy_manager.h",
+ "profile_oauth2_token_service.cc",
+ "profile_oauth2_token_service.h",
+ "profile_oauth2_token_service_builder.cc",
+ "profile_oauth2_token_service_builder.h",
+ "profile_oauth2_token_service_delegate.cc",
+ "profile_oauth2_token_service_delegate.h",
+ "profile_oauth2_token_service_delegate_chromeos.cc",
+ "profile_oauth2_token_service_delegate_chromeos.h",
+ "profile_oauth2_token_service_delegate_ios.h",
+ "profile_oauth2_token_service_delegate_ios.mm",
+ "ubertoken_fetcher_impl.cc",
+ "ubertoken_fetcher_impl.h",
+ ]
+
+ configs += [ "//build/config/compiler:wexit_time_destructors" ]
+
+ public_deps = [
+ "//base",
+ "//components/signin/public/base",
+ "//components/signin/public/base:signin_buildflags",
+ "//components/webdata/common",
+ "//google_apis",
+ "//mojo/public/cpp/bindings",
+ "//net",
+ "//services/network/public/mojom",
+ ]
+
+ deps = [
+ "//components/image_fetcher/core",
+ "//components/prefs",
+ "//components/signin/public/webdata",
+ "//services/network/public/cpp",
+ "//ui/gfx",
+ ]
+
+ if (is_android) {
+ deps += [ "//components/signin/core/browser/android:jni_headers" ]
+ }
+
+ if (is_chromeos) {
+ public_deps += [ "//chromeos/components/account_manager" ]
+
+ deps += [
+ "//chromeos/constants",
+ "//components/user_manager",
+ ]
+ } else {
+ sources += [
+ "primary_account_policy_manager_impl.cc",
+ "primary_account_policy_manager_impl.h",
+ ]
+
+ public_deps += [ "//components/prefs" ]
+ }
+
+ if (!is_android && !is_ios) {
+ sources += [
+ "accounts_mutator_impl.cc",
+ "accounts_mutator_impl.h",
+ ]
+ }
+
+ if (is_ios) {
+ configs += [ "//build/config/compiler:enable_arc" ]
+
+ sources += [
+ "device_accounts_synchronizer_impl.cc",
+ "device_accounts_synchronizer_impl.h",
+ ]
+
+ deps += [ "//components/signin/public/identity_manager/ios" ]
+ }
+}
+
+source_set("unit_tests") {
+ testonly = true
+
+ sources = [
+ "account_info_util_unittest.cc",
+ "account_tracker_service_unittest.cc",
+ "gaia_cookie_manager_service_unittest.cc",
+ "mutable_profile_oauth2_token_service_delegate_unittest.cc",
+ "oauth2_token_service_delegate_android_unittest.cc",
+ "oauth_multilogin_helper_unittest.cc",
+ "oauth_multilogin_token_fetcher_unittest.cc",
+ "primary_account_manager_unittest.cc",
+ "primary_account_policy_manager_impl_unittest.cc",
+ "profile_oauth2_token_service_delegate_chromeos_unittest.cc",
+ "profile_oauth2_token_service_delegate_ios_unittest.mm",
+ "profile_oauth2_token_service_delegate_unittest.cc",
+ "profile_oauth2_token_service_unittest.cc",
+ "ubertoken_fetcher_impl_unittest.cc",
+ ]
+
+ deps = [
+ ":identity_manager",
+ ":test_support",
+ "//base",
+ "//base/test:test_support",
+ "//components/image_fetcher/core",
+ "//components/image_fetcher/core:test_support",
+ "//components/os_crypt:test_support",
+ "//components/prefs",
+ "//components/prefs:test_support",
+ "//components/signin/public/base",
+ "//components/signin/public/base:signin_buildflags",
+ "//components/signin/public/base:test_support",
+ "//components/signin/public/identity_manager",
+ "//components/signin/public/webdata",
+ "//components/sync_preferences:test_support",
+ "//components/webdata/common",
+ "//google_apis",
+ "//net",
+ "//net:test_support",
+ "//services/network:test_support",
+ "//services/network/public/cpp",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+
+ if (is_chromeos) {
+ sources -= [ "primary_account_policy_manager_impl_unittest.cc" ]
+
+ deps += [ "//chromeos/components/account_manager" ]
+ }
+
+ if (is_ios) {
+ configs += [ "//build/config/compiler:enable_arc" ]
+
+ deps += [ "//components/signin/public/identity_manager/ios:test_support" ]
+ }
+}
+
+# This target contains test support that backs the test support for
+# IdentityManager.
+static_library("test_support") {
+ testonly = true
+
+ sources = [
+ "fake_profile_oauth2_token_service.cc",
+ "fake_profile_oauth2_token_service.h",
+ "fake_profile_oauth2_token_service_delegate.cc",
+ "fake_profile_oauth2_token_service_delegate.h",
+ ]
+
+ public_deps = [
+ ":identity_manager",
+ "//base",
+ "//google_apis:test_support",
+ ]
+}
diff --git a/chromium/components/signin/internal/identity_manager/DEPS b/chromium/components/signin/internal/identity_manager/DEPS
new file mode 100644
index 00000000000..4485df3b6a5
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/DEPS
@@ -0,0 +1,16 @@
+include_rules = [
+ "+chromeos/constants/chromeos_switches.h",
+ "+mojo/public",
+]
+
+specific_include_rules = {
+ "account_tracker_service.cc": [
+ "+components/signin/core/browser/android/jni_headers/AccountTrackerService_jni.h",
+ ],
+ "child_account_info_fetcher_android.cc": [
+ "+components/signin/core/browser/android/jni_headers/ChildAccountInfoFetcher_jni.h",
+ ],
+ "oauth2_token_service_delegate_android.cc": [
+ "+components/signin/core/browser/android/jni_headers/OAuth2TokenService_jni.h",
+ ],
+}
diff --git a/chromium/components/signin/core/browser/account_fetcher_service.cc b/chromium/components/signin/internal/identity_manager/account_fetcher_service.cc
index 6ff6a0421b4..97889b99ee8 100644
--- a/chromium/components/signin/core/browser/account_fetcher_service.cc
+++ b/chromium/components/signin/internal/identity_manager/account_fetcher_service.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/account_fetcher_service.h"
+#include "components/signin/internal/identity_manager/account_fetcher_service.h"
#include <string>
#include <utility>
@@ -17,16 +17,16 @@
#include "components/image_fetcher/core/image_fetcher_impl.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/account_info_fetcher.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/avatar_icon_util.h"
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_client.h"
-#include "components/signin/core/browser/signin_switches.h"
+#include "components/signin/internal/identity_manager/account_info_fetcher.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/public/base/avatar_icon_util.h"
+#include "components/signin/public/base/signin_client.h"
+#include "components/signin/public/base/signin_switches.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#if defined(OS_ANDROID)
-#include "components/signin/core/browser/child_account_info_fetcher_android.h"
+#include "components/signin/internal/identity_manager/child_account_info_fetcher_android.h"
#endif
namespace {
@@ -34,12 +34,12 @@ namespace {
const base::TimeDelta kRefreshFromTokenServiceDelay =
base::TimeDelta::FromHours(24);
-bool AccountSupportsUserInfo(const std::string& account_id) {
+bool AccountSupportsUserInfo(const CoreAccountId& account_id) {
// Supervised users use a specially scoped token which when used for general
// purposes causes the token service to raise spurious auth errors.
// TODO(treib): this string is also used in supervised_user_constants.cc.
// Should put in a common place.
- return account_id != "managed_user@localhost";
+ return account_id.id != "managed_user@localhost";
}
} // namespace
@@ -109,7 +109,7 @@ bool AccountFetcherService::IsAllUserInfoFetched() const {
}
void AccountFetcherService::ForceRefreshOfAccountInfo(
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
DCHECK(network_fetches_enabled_);
RefreshAccountInfo(account_id, false);
}
@@ -137,24 +137,22 @@ void AccountFetcherService::EnableAccountRemovalForTest() {
}
void AccountFetcherService::RefreshAllAccountInfo(bool only_fetch_if_invalid) {
- std::vector<std::string> accounts = token_service_->GetAccounts();
- for (std::vector<std::string>::const_iterator it = accounts.begin();
- it != accounts.end(); ++it) {
- RefreshAccountInfo(*it, only_fetch_if_invalid);
+ for (const auto& account : token_service_->GetAccounts()) {
+ RefreshAccountInfo(account, only_fetch_if_invalid);
}
}
// Child account status is refreshed through invalidations which are only
// available for the primary account. Finding the primary account requires a
-// dependency on signin_manager which we get around by only allowing a single
-// account. This is possible since we only support a single account to be a
-// child anyway.
+// dependency on PrimaryAccountManager which we get around by only allowing a
+// single account. This is possible since we only support a single account to be
+// a child anyway.
#if defined(OS_ANDROID)
void AccountFetcherService::UpdateChildInfo() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- std::vector<std::string> accounts = token_service_->GetAccounts();
+ std::vector<CoreAccountId> accounts = token_service_->GetAccounts();
if (accounts.size() == 1) {
- const std::string& candidate = accounts[0];
+ const CoreAccountId& candidate = accounts[0];
if (candidate == child_request_account_id_)
return;
if (!child_request_account_id_.empty())
@@ -208,7 +206,7 @@ void AccountFetcherService::ScheduleNextRefresh() {
// Starts fetching user information. This is called periodically to refresh.
void AccountFetcherService::StartFetchingUserInfo(
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(network_fetches_enabled_);
@@ -228,7 +226,7 @@ void AccountFetcherService::StartFetchingUserInfo(
#if defined(OS_ANDROID)
// Starts fetching whether this is a child account. Handles refresh internally.
void AccountFetcherService::StartFetchingChildInfo(
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
child_info_request_ =
ChildAccountInfoFetcherAndroid::Create(this, child_request_account_id_);
}
@@ -236,18 +234,18 @@ void AccountFetcherService::StartFetchingChildInfo(
void AccountFetcherService::ResetChildInfo() {
if (!child_request_account_id_.empty())
SetIsChildAccount(child_request_account_id_, false);
- child_request_account_id_.clear();
+ child_request_account_id_ = CoreAccountId();
child_info_request_.reset();
}
-void AccountFetcherService::SetIsChildAccount(const std::string& account_id,
+void AccountFetcherService::SetIsChildAccount(const CoreAccountId& account_id,
bool is_child_account) {
if (child_request_account_id_ == account_id)
account_tracker_service_->SetIsChildAccount(account_id, is_child_account);
}
#endif
-void AccountFetcherService::RefreshAccountInfo(const std::string& account_id,
+void AccountFetcherService::RefreshAccountInfo(const CoreAccountId& account_id,
bool only_fetch_if_invalid) {
DCHECK(network_fetches_enabled_);
account_tracker_service_->StartTrackingAccount(account_id);
@@ -268,7 +266,7 @@ void AccountFetcherService::RefreshAccountInfo(const std::string& account_id,
}
void AccountFetcherService::OnUserInfoFetchSuccess(
- const std::string& account_id,
+ const CoreAccountId& account_id,
std::unique_ptr<base::DictionaryValue> user_info) {
account_tracker_service_->SetAccountInfoFromUserInfo(account_id,
user_info.get());
@@ -287,7 +285,7 @@ AccountFetcherService::GetOrCreateImageFetcher() {
return image_fetcher_.get();
}
-void AccountFetcherService::FetchAccountImage(const std::string& account_id) {
+void AccountFetcherService::FetchAccountImage(const CoreAccountId& account_id) {
DCHECK(signin_client_);
std::string picture_url_string =
account_tracker_service_->GetAccountInfo(account_id).picture_url;
@@ -329,16 +327,16 @@ void AccountFetcherService::FetchAccountImage(const std::string& account_id) {
}
void AccountFetcherService::OnUserInfoFetchFailure(
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
LOG(WARNING) << "Failed to get UserInfo for " << account_id;
user_info_requests_.erase(account_id);
}
void AccountFetcherService::OnRefreshTokenAvailable(
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
TRACE_EVENT1("AccountFetcherService",
"AccountFetcherService::OnRefreshTokenAvailable", "account_id",
- account_id);
+ account_id.id);
DVLOG(1) << "AVAILABLE " << account_id;
// The SigninClient needs a "final init" in order to perform some actions
@@ -355,10 +353,10 @@ void AccountFetcherService::OnRefreshTokenAvailable(
}
void AccountFetcherService::OnRefreshTokenRevoked(
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
TRACE_EVENT1("AccountFetcherService",
"AccountFetcherService::OnRefreshTokenRevoked", "account_id",
- account_id);
+ account_id.id);
DVLOG(1) << "REVOKED " << account_id;
// Short-circuit out if network fetches are not enabled.
@@ -383,8 +381,8 @@ void AccountFetcherService::OnRefreshTokensLoaded() {
}
void AccountFetcherService::OnImageFetched(
- const std::string& id,
+ const CoreAccountId& account_id,
const gfx::Image& image,
const image_fetcher::RequestMetadata&) {
- account_tracker_service_->SetAccountImage(id, image);
+ account_tracker_service_->SetAccountImage(account_id, image);
}
diff --git a/chromium/components/signin/core/browser/account_fetcher_service.h b/chromium/components/signin/internal/identity_manager/account_fetcher_service.h
index 0d94fba7ff6..0cd1249ff97 100644
--- a/chromium/components/signin/core/browser/account_fetcher_service.h
+++ b/chromium/components/signin/internal/identity_manager/account_fetcher_service.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_FETCHER_SERVICE_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_FETCHER_SERVICE_H_
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_FETCHER_SERVICE_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_FETCHER_SERVICE_H_
#include <stdint.h>
@@ -15,9 +15,7 @@
#include "base/sequence_checker.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "google_apis/gaia/oauth2_token_service.h"
-#include "ui/gfx/image/image.h"
+#include "google_apis/gaia/oauth2_token_service_observer.h"
class AccountInfoFetcher;
class AccountTrackerService;
@@ -33,13 +31,17 @@ namespace base {
class DictionaryValue;
}
+namespace gfx {
+class Image;
+}
+
namespace image_fetcher {
struct RequestMetadata;
class ImageDecoder;
class ImageFetcherImpl;
} // namespace image_fetcher
-class AccountFetcherService : public OAuth2TokenService::Observer {
+class AccountFetcherService : public OAuth2TokenServiceObserver {
public:
// Name of the preference that tracks the int64_t representation of the last
// time the AccountTrackerService was updated.
@@ -65,7 +67,7 @@ class AccountFetcherService : public OAuth2TokenService::Observer {
// there are still unfininshed fetchers.
virtual bool IsAllUserInfoFetched() const;
- void ForceRefreshOfAccountInfo(const std::string& account_id);
+ void ForceRefreshOfAccountInfo(const CoreAccountId& account_id);
AccountTrackerService* account_tracker_service() const {
return account_tracker_service_;
@@ -88,12 +90,13 @@ class AccountFetcherService : public OAuth2TokenService::Observer {
#if defined(OS_ANDROID)
// Called by ChildAccountInfoFetcherAndroid.
- void SetIsChildAccount(const std::string& account_id, bool is_child_account);
+ void SetIsChildAccount(const CoreAccountId& account_id,
+ bool is_child_account);
#endif
- // OAuth2TokenService::Observer implementation.
- void OnRefreshTokenAvailable(const std::string& account_id) override;
- void OnRefreshTokenRevoked(const std::string& account_id) override;
+ // OAuth2TokenServiceObserver implementation.
+ void OnRefreshTokenAvailable(const CoreAccountId& account_id) override;
+ void OnRefreshTokenRevoked(const CoreAccountId& account_id) override;
void OnRefreshTokensLoaded() override;
private:
@@ -114,9 +117,9 @@ class AccountFetcherService : public OAuth2TokenService::Observer {
// Virtual so that tests can override the network fetching behaviour.
// Further the two fetches are managed by a different refresh logic and
// thus, can not be combined.
- void StartFetchingUserInfo(const std::string& account_id);
+ void StartFetchingUserInfo(const CoreAccountId& account_id);
#if defined(OS_ANDROID)
- void StartFetchingChildInfo(const std::string& account_id);
+ void StartFetchingChildInfo(const CoreAccountId& account_id);
// If there is more than one account in a profile, we forcibly reset the
// child status for an account to be false.
@@ -124,20 +127,20 @@ class AccountFetcherService : public OAuth2TokenService::Observer {
#endif
// Refreshes the AccountInfo associated with |account_id|.
- void RefreshAccountInfo(const std::string& account_id,
+ void RefreshAccountInfo(const CoreAccountId& account_id,
bool only_fetch_if_invalid);
// Called by AccountInfoFetcher.
- void OnUserInfoFetchSuccess(const std::string& account_id,
+ void OnUserInfoFetchSuccess(const CoreAccountId& account_id,
std::unique_ptr<base::DictionaryValue> user_info);
- void OnUserInfoFetchFailure(const std::string& account_id);
+ void OnUserInfoFetchFailure(const CoreAccountId& account_id);
image_fetcher::ImageFetcherImpl* GetOrCreateImageFetcher();
// Called in |OnUserInfoFetchSuccess| after the account info has been fetched.
- void FetchAccountImage(const std::string& account_id);
+ void FetchAccountImage(const CoreAccountId& account_id);
- void OnImageFetched(const std::string& id,
+ void OnImageFetched(const CoreAccountId& account_id,
const gfx::Image& image,
const image_fetcher::RequestMetadata& image_metadata);
@@ -153,12 +156,12 @@ class AccountFetcherService : public OAuth2TokenService::Observer {
base::OneShotTimer timer_;
#if defined(OS_ANDROID)
- std::string child_request_account_id_;
+ CoreAccountId child_request_account_id_;
std::unique_ptr<ChildAccountInfoFetcherAndroid> child_info_request_;
#endif
// Holds references to account info fetchers keyed by account_id.
- std::unordered_map<std::string, std::unique_ptr<AccountInfoFetcher>>
+ std::unordered_map<CoreAccountId, std::unique_ptr<AccountInfoFetcher>>
user_info_requests_;
// Used for fetching the account images.
@@ -170,4 +173,4 @@ class AccountFetcherService : public OAuth2TokenService::Observer {
DISALLOW_COPY_AND_ASSIGN(AccountFetcherService);
};
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_FETCHER_SERVICE_H_
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_FETCHER_SERVICE_H_
diff --git a/chromium/components/signin/core/browser/account_info_fetcher.cc b/chromium/components/signin/internal/identity_manager/account_info_fetcher.cc
index fee88e9e7b4..eedc41fb62e 100644
--- a/chromium/components/signin/core/browser/account_info_fetcher.cc
+++ b/chromium/components/signin/internal/identity_manager/account_info_fetcher.cc
@@ -2,27 +2,28 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/account_info_fetcher.h"
+#include "components/signin/internal/identity_manager/account_info_fetcher.h"
#include <utility>
#include "base/trace_event/trace_event.h"
-#include "components/signin/core/browser/account_fetcher_service.h"
+#include "components/signin/internal/identity_manager/account_fetcher_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
#include "google_apis/gaia/gaia_constants.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
AccountInfoFetcher::AccountInfoFetcher(
- OAuth2TokenService* token_service,
+ ProfileOAuth2TokenService* token_service,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
AccountFetcherService* service,
- const std::string& account_id)
- : OAuth2TokenService::Consumer("gaia_account_tracker"),
+ const CoreAccountId& account_id)
+ : OAuth2AccessTokenManager::Consumer("gaia_account_tracker"),
token_service_(token_service),
url_loader_factory_(std::move(url_loader_factory)),
service_(service),
account_id_(account_id) {
TRACE_EVENT_ASYNC_BEGIN1("AccountFetcherService", "AccountIdFetcher", this,
- "account_id", account_id);
+ "account_id", account_id.id);
}
AccountInfoFetcher::~AccountInfoFetcher() {
@@ -30,7 +31,7 @@ AccountInfoFetcher::~AccountInfoFetcher() {
}
void AccountInfoFetcher::Start() {
- OAuth2TokenService::ScopeSet scopes;
+ OAuth2AccessTokenManager::ScopeSet scopes;
scopes.insert(GaiaConstants::kGoogleUserInfoEmail);
scopes.insert(GaiaConstants::kGoogleUserInfoProfile);
login_token_request_ =
@@ -38,7 +39,7 @@ void AccountInfoFetcher::Start() {
}
void AccountInfoFetcher::OnGetTokenSuccess(
- const OAuth2TokenService::Request* request,
+ const OAuth2AccessTokenManager::Request* request,
const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
TRACE_EVENT_ASYNC_STEP_PAST0("AccountFetcherService", "AccountIdFetcher",
this, "OnGetTokenSuccess");
@@ -51,7 +52,7 @@ void AccountInfoFetcher::OnGetTokenSuccess(
}
void AccountInfoFetcher::OnGetTokenFailure(
- const OAuth2TokenService::Request* request,
+ const OAuth2AccessTokenManager::Request* request,
const GoogleServiceAuthError& error) {
TRACE_EVENT_ASYNC_STEP_PAST1("AccountFetcherService", "AccountIdFetcher",
this, "OnGetTokenFailure",
@@ -65,7 +66,7 @@ void AccountInfoFetcher::OnGetUserInfoResponse(
std::unique_ptr<base::DictionaryValue> user_info) {
TRACE_EVENT_ASYNC_STEP_PAST1("AccountFetcherService", "AccountIdFetcher",
this, "OnGetUserInfoResponse", "account_id",
- account_id_);
+ account_id_.id);
service_->OnUserInfoFetchSuccess(account_id_, std::move(user_info));
}
diff --git a/chromium/components/signin/core/browser/account_info_fetcher.h b/chromium/components/signin/internal/identity_manager/account_info_fetcher.h
index 27cec56b3eb..c43ba6dbfb2 100644
--- a/chromium/components/signin/core/browser/account_info_fetcher.h
+++ b/chromium/components/signin/internal/identity_manager/account_info_fetcher.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_INFO_FETCHER_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_INFO_FETCHER_H_
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_INFO_FETCHER_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_INFO_FETCHER_H_
#include <memory>
@@ -11,37 +11,38 @@
#include "base/memory/scoped_refptr.h"
#include "google_apis/gaia/gaia_auth_consumer.h"
#include "google_apis/gaia/gaia_oauth_client.h"
-#include "google_apis/gaia/oauth2_token_service.h"
+#include "google_apis/gaia/oauth2_access_token_manager.h"
namespace network {
class SharedURLLoaderFactory;
}
class AccountFetcherService;
+class ProfileOAuth2TokenService;
// An account information fetcher that gets an OAuth token of appropriate
-// scope and uses it to fetch account infromation. This does not handle
+// scope and uses it to fetch account information. This does not handle
// refreshing the information and is meant to be used in a one shot fashion.
-class AccountInfoFetcher : public OAuth2TokenService::Consumer,
+class AccountInfoFetcher : public OAuth2AccessTokenManager::Consumer,
public gaia::GaiaOAuthClient::Delegate {
public:
AccountInfoFetcher(
- OAuth2TokenService* token_service,
+ ProfileOAuth2TokenService* token_service,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
AccountFetcherService* service,
- const std::string& account_id);
+ const CoreAccountId& account_id);
~AccountInfoFetcher() override;
- const std::string& account_id() { return account_id_; }
+ const CoreAccountId& account_id() { return account_id_; }
// Start fetching the account information.
void Start();
- // OAuth2TokenService::Consumer implementation.
+ // OAuth2AccessTokenManager::Consumer implementation.
void OnGetTokenSuccess(
- const OAuth2TokenService::Request* request,
+ const OAuth2AccessTokenManager::Request* request,
const OAuth2AccessTokenConsumer::TokenResponse& token_response) override;
- void OnGetTokenFailure(const OAuth2TokenService::Request* request,
+ void OnGetTokenFailure(const OAuth2AccessTokenManager::Request* request,
const GoogleServiceAuthError& error) override;
// gaia::GaiaOAuthClient::Delegate implementation.
@@ -51,15 +52,15 @@ class AccountInfoFetcher : public OAuth2TokenService::Consumer,
void OnNetworkError(int response_code) override;
private:
- OAuth2TokenService* token_service_;
+ ProfileOAuth2TokenService* token_service_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
AccountFetcherService* service_;
- const std::string account_id_;
+ const CoreAccountId account_id_;
- std::unique_ptr<OAuth2TokenService::Request> login_token_request_;
+ std::unique_ptr<OAuth2AccessTokenManager::Request> login_token_request_;
std::unique_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_;
DISALLOW_COPY_AND_ASSIGN(AccountInfoFetcher);
};
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_INFO_FETCHER_H_
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_INFO_FETCHER_H_
diff --git a/chromium/components/signin/core/browser/account_info_util.cc b/chromium/components/signin/internal/identity_manager/account_info_util.cc
index 878adeb5f62..cb77753ba13 100644
--- a/chromium/components/signin/core/browser/account_info_util.cc
+++ b/chromium/components/signin/internal/identity_manager/account_info_util.cc
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/account_info_util.h"
+#include "components/signin/internal/identity_manager/account_info_util.h"
-#include "components/signin/core/browser/account_info.h"
+#include "components/signin/public/identity_manager/account_info.h"
namespace {
// Keys used to store the different values in the JSON dictionary received
diff --git a/chromium/components/signin/core/browser/account_info_util.h b/chromium/components/signin/internal/identity_manager/account_info_util.h
index fb2058a6674..53207e5c483 100644
--- a/chromium/components/signin/core/browser/account_info_util.h
+++ b/chromium/components/signin/internal/identity_manager/account_info_util.h
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_INFO_UTIL_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_INFO_UTIL_H_
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_INFO_UTIL_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_INFO_UTIL_H_
#include "base/optional.h"
#include "base/values.h"
-#include "components/signin/core/browser/account_info.h"
+#include "components/signin/public/identity_manager/account_info.h"
// Builds an AccountInfo from the JSON data returned by the gaia servers (the
// data should have been converted to base::Value), if possible.
base::Optional<AccountInfo> AccountInfoFromUserInfo(
const base::Value& user_info);
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_INFO_UTIL_H_
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_INFO_UTIL_H_
diff --git a/chromium/components/signin/core/browser/account_info_util_unittest.cc b/chromium/components/signin/internal/identity_manager/account_info_util_unittest.cc
index da0c76f172f..cc658a06104 100644
--- a/chromium/components/signin/core/browser/account_info_util_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/account_info_util_unittest.cc
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/account_info_util.h"
+#include "components/signin/internal/identity_manager/account_info_util.h"
-#include "components/signin/core/browser/account_info.h"
+#include "components/signin/public/identity_manager/account_info.h"
#include "testing/platform_test.h"
namespace {
diff --git a/chromium/components/signin/core/browser/account_tracker_service.cc b/chromium/components/signin/internal/identity_manager/account_tracker_service.cc
index c30ba074019..710345b7cf6 100644
--- a/chromium/components/signin/core/browser/account_tracker_service.cc
+++ b/chromium/components/signin/internal/identity_manager/account_tracker_service.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
#include <stddef.h>
@@ -23,13 +23,13 @@
#include "build/build_config.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/scoped_user_pref_update.h"
-#include "components/signin/core/browser/account_info_util.h"
-#include "components/signin/core/browser/signin_manager.h"
-#include "components/signin/core/browser/signin_pref_names.h"
+#include "components/signin/internal/identity_manager/account_info_util.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "ui/gfx/image/image.h"
#if defined(OS_ANDROID)
#include "base/android/jni_array.h"
-#include "jni/AccountTrackerService_jni.h"
+#include "components/signin/core/browser/android/jni_headers/AccountTrackerService_jni.h"
#endif
namespace {
@@ -94,7 +94,7 @@ void RemoveImage(const base::FilePath& image_path) {
} // namespace
-AccountTrackerService::AccountTrackerService() : weak_factory_(this) {
+AccountTrackerService::AccountTrackerService() {
#if defined(OS_ANDROID)
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> java_ref =
@@ -136,14 +136,6 @@ void AccountTrackerService::Shutdown() {
accounts_.clear();
}
-void AccountTrackerService::AddObserver(Observer* observer) {
- observer_list_.AddObserver(observer);
-}
-
-void AccountTrackerService::RemoveObserver(Observer* observer) {
- observer_list_.RemoveObserver(observer);
-}
-
std::vector<AccountInfo> AccountTrackerService::GetAccounts() const {
std::vector<AccountInfo> accounts;
for (const auto& pair : accounts_) {
@@ -209,20 +201,20 @@ void AccountTrackerService::SetMigrationDone() {
void AccountTrackerService::NotifyAccountUpdated(
const AccountInfo& account_info) {
DCHECK(!account_info.gaia.empty());
- for (auto& observer : observer_list_)
- observer.OnAccountUpdated(account_info);
+ if (on_account_updated_callback_)
+ on_account_updated_callback_.Run(account_info);
}
void AccountTrackerService::NotifyAccountRemoved(
const AccountInfo& account_info) {
DCHECK(!account_info.gaia.empty());
- for (auto& observer : observer_list_)
- observer.OnAccountRemoved(account_info);
+ if (on_account_removed_callback_)
+ on_account_removed_callback_.Run(account_info);
}
void AccountTrackerService::StartTrackingAccount(
const CoreAccountId& account_id) {
- if (!base::ContainsKey(accounts_, account_id)) {
+ if (!base::Contains(accounts_, account_id)) {
DVLOG(1) << "StartTracking " << account_id;
AccountInfo account_info;
account_info.account_id = account_id;
@@ -234,7 +226,7 @@ void AccountTrackerService::StartTrackingAccount(
void AccountTrackerService::StopTrackingAccount(
const CoreAccountId& account_id) {
DVLOG(1) << "StopTracking " << account_id;
- if (base::ContainsKey(accounts_, account_id)) {
+ if (base::Contains(accounts_, account_id)) {
AccountInfo account_info = std::move(accounts_[account_id]);
RemoveFromPrefs(account_info);
RemoveAccountImageFromDisk(account_id);
@@ -248,7 +240,7 @@ void AccountTrackerService::StopTrackingAccount(
void AccountTrackerService::SetAccountInfoFromUserInfo(
const CoreAccountId& account_id,
const base::DictionaryValue* user_info) {
- DCHECK(base::ContainsKey(accounts_, account_id));
+ DCHECK(base::Contains(accounts_, account_id));
AccountInfo& account_info = accounts_[account_id];
base::Optional<AccountInfo> maybe_account_info =
@@ -271,7 +263,7 @@ void AccountTrackerService::SetAccountInfoFromUserInfo(
void AccountTrackerService::SetAccountImage(const CoreAccountId& account_id,
const gfx::Image& image) {
- if (!base::ContainsKey(accounts_, account_id))
+ if (!base::Contains(accounts_, account_id))
return;
AccountInfo& account_info = accounts_[account_id];
account_info.account_image = image;
@@ -281,7 +273,7 @@ void AccountTrackerService::SetAccountImage(const CoreAccountId& account_id,
void AccountTrackerService::SetIsChildAccount(const CoreAccountId& account_id,
bool is_child_account) {
- DCHECK(base::ContainsKey(accounts_, account_id));
+ DCHECK(base::Contains(accounts_, account_id));
AccountInfo& account_info = accounts_[account_id];
if (account_info.is_child_account == is_child_account)
return;
@@ -294,7 +286,7 @@ void AccountTrackerService::SetIsChildAccount(const CoreAccountId& account_id,
void AccountTrackerService::SetIsAdvancedProtectionAccount(
const CoreAccountId& account_id,
bool is_under_advanced_protection) {
- DCHECK(base::ContainsKey(accounts_, account_id));
+ DCHECK(base::Contains(accounts_, account_id));
AccountInfo& account_info = accounts_[account_id];
if (account_info.is_under_advanced_protection == is_under_advanced_protection)
return;
@@ -304,6 +296,18 @@ void AccountTrackerService::SetIsAdvancedProtectionAccount(
SaveToPrefs(account_info);
}
+void AccountTrackerService::SetOnAccountUpdatedCallback(
+ AccountInfoCallback callback) {
+ DCHECK(!on_account_updated_callback_);
+ on_account_updated_callback_ = callback;
+}
+
+void AccountTrackerService::SetOnAccountRemovedCallback(
+ AccountInfoCallback callback) {
+ DCHECK(!on_account_removed_callback_);
+ on_account_removed_callback_ = callback;
+}
+
void AccountTrackerService::MigrateToGaiaId() {
DCHECK_EQ(GetMigrationState(), MIGRATION_IN_PROGRESS);
@@ -319,7 +323,7 @@ void AccountTrackerService::MigrateToGaiaId() {
// If there is already an account keyed to the current account's gaia id,
// assume this is the result of a partial migration and skip the account
// that is currently inspected.
- if (base::ContainsKey(accounts_, new_account_id))
+ if (base::Contains(accounts_, new_account_id))
continue;
AccountInfo new_account_info = pair.second;
@@ -340,7 +344,7 @@ void AccountTrackerService::MigrateToGaiaId() {
// Remove any obsolete account.
for (const auto& account_id : to_remove) {
- DCHECK(base::ContainsKey(accounts_, account_id));
+ DCHECK(base::Contains(accounts_, account_id));
AccountInfo& account_info = accounts_[account_id];
RemoveAccountImageFromDisk(account_id);
RemoveFromPrefs(account_info);
@@ -353,7 +357,7 @@ bool AccountTrackerService::IsMigrationDone() const {
return false;
for (const auto& pair : accounts_) {
- if (pair.first != pair.second.gaia)
+ if (pair.first.id != pair.second.gaia)
return false;
}
@@ -374,7 +378,7 @@ AccountTrackerService::ComputeNewMigrationState() const {
// Migration is required if at least one account is not keyed to its
// gaia id.
- migration_required |= (pair.first != pair.second.gaia);
+ migration_required |= (pair.first.id != pair.second.gaia);
}
return migration_required ? MIGRATION_IN_PROGRESS : MIGRATION_DONE;
@@ -402,7 +406,7 @@ base::FilePath AccountTrackerService::GetImagePathFor(
void AccountTrackerService::OnAccountImageLoaded(
const CoreAccountId& account_id,
gfx::Image image) {
- if (base::ContainsKey(accounts_, account_id) &&
+ if (base::Contains(accounts_, account_id) &&
accounts_[account_id].account_image.IsEmpty()) {
AccountInfo& account_info = accounts_[account_id];
account_info.account_image = image;
@@ -626,7 +630,7 @@ CoreAccountId AccountTrackerService::SeedAccountInfo(const std::string& gaia,
CoreAccountId AccountTrackerService::SeedAccountInfo(AccountInfo info) {
info.account_id = PickAccountIdForAccount(info.gaia, info.email);
- const bool already_exists = base::ContainsKey(accounts_, info.account_id);
+ const bool already_exists = base::Contains(accounts_, info.account_id);
StartTrackingAccount(info.account_id);
AccountInfo& account_info = accounts_[info.account_id];
DCHECK(!already_exists || account_info.gaia.empty() ||
diff --git a/chromium/components/signin/core/browser/account_tracker_service.h b/chromium/components/signin/internal/identity_manager/account_tracker_service.h
index e0511f891da..5fc76f4f017 100644
--- a/chromium/components/signin/core/browser/account_tracker_service.h
+++ b/chromium/components/signin/internal/identity_manager/account_tracker_service.h
@@ -2,14 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_TRACKER_SERVICE_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_TRACKER_SERVICE_H_
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_TRACKER_SERVICE_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_TRACKER_SERVICE_H_
#include <list>
#include <map>
#include <string>
#include <vector>
+#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -17,11 +18,9 @@
#include "base/sequence_checker.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "components/signin/core/browser/account_info.h"
+#include "components/signin/public/identity_manager/account_info.h"
#include "google_apis/gaia/core_account_id.h"
#include "google_apis/gaia/gaia_auth_util.h"
-#include "ui/gfx/image/image.h"
#if defined(OS_ANDROID)
#include "base/android/scoped_java_ref.h"
@@ -34,7 +33,11 @@ namespace base {
class DictionaryValue;
}
-namespace identity {
+namespace gfx {
+class Image;
+}
+
+namespace signin {
class IdentityManager;
void SimulateSuccessfulFetchOfAccountInfo(IdentityManager*,
const std::string&,
@@ -45,19 +48,13 @@ void SimulateSuccessfulFetchOfAccountInfo(IdentityManager*,
const std::string&,
const std::string&,
const std::string&);
-}
+} // namespace signin
// Retrieves and caches GAIA information about Google Accounts.
class AccountTrackerService {
public:
- // Clients of AccountTrackerService can implement this interface and register
- // with AddObserver() to learn about account information changes.
- class Observer {
- public:
- virtual ~Observer() {}
- virtual void OnAccountUpdated(const AccountInfo& info) {}
- virtual void OnAccountRemoved(const AccountInfo& info) {}
- };
+ typedef base::RepeatingCallback<void(const AccountInfo& info)>
+ AccountInfoCallback;
// Possible values for the kAccountIdMigrationState preference.
// Keep in sync with OAuth2LoginAccountRevokedMigrationState histogram enum.
@@ -78,9 +75,6 @@ class AccountTrackerService {
void Shutdown();
- void AddObserver(Observer* observer);
- void RemoveObserver(Observer* observer);
-
// Initializes the list of accounts from |pref_service| and load images from
// |user_data_dir|. If |user_data_dir| is empty, images will not be saved to
// nor loaded from disk.
@@ -134,6 +128,14 @@ class AccountTrackerService {
base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
#endif
+ // If set, this callback will be invoked whenever the details of a tracked
+ // account changes (e.g. account's info, image, |is_child_account|...).
+ void SetOnAccountUpdatedCallback(AccountInfoCallback callback);
+
+ // If set, this callback will be invoked whenever an existing account with a
+ // valid GaiaId gets removed from |accounts_| (i.e. stops being tracked).
+ void SetOnAccountRemovedCallback(AccountInfoCallback callback);
+
protected:
// Available to be called in tests.
void SetAccountInfoFromUserInfo(const CoreAccountId& account_id,
@@ -146,8 +148,8 @@ class AccountTrackerService {
private:
friend class AccountFetcherService;
- friend void identity::SimulateSuccessfulFetchOfAccountInfo(
- identity::IdentityManager*,
+ friend void signin::SimulateSuccessfulFetchOfAccountInfo(
+ signin::IdentityManager*,
const std::string&,
const std::string&,
const std::string&,
@@ -198,10 +200,11 @@ class AccountTrackerService {
PrefService* pref_service_ = nullptr; // Not owned.
std::map<CoreAccountId, AccountInfo> accounts_;
- base::ObserverList<Observer>::Unchecked observer_list_;
-
base::FilePath user_data_dir_;
+ AccountInfoCallback on_account_updated_callback_;
+ AccountInfoCallback on_account_removed_callback_;
+
// Task runner used for file operations on avatar images.
scoped_refptr<base::SequencedTaskRunner> image_storage_task_runner_;
@@ -214,9 +217,9 @@ class AccountTrackerService {
// Used to pass weak pointers of |this| to tasks created by
// |image_storage_task_runner_|.
- base::WeakPtrFactory<AccountTrackerService> weak_factory_;
+ base::WeakPtrFactory<AccountTrackerService> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(AccountTrackerService);
};
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_TRACKER_SERVICE_H_
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_TRACKER_SERVICE_H_
diff --git a/chromium/components/signin/core/browser/account_tracker_service_unittest.cc b/chromium/components/signin/internal/identity_manager/account_tracker_service_unittest.cc
index 46eac21d21b..a11e96f3681 100644
--- a/chromium/components/signin/core/browser/account_tracker_service_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/account_tracker_service_unittest.cc
@@ -15,17 +15,16 @@
#include "build/build_config.h"
#include "components/image_fetcher/core/fake_image_decoder.h"
#include "components/image_fetcher/core/image_data_fetcher.h"
-#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/prefs/testing_pref_service.h"
-#include "components/signin/core/browser/account_fetcher_service.h"
-#include "components/signin/core/browser/account_info.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/avatar_icon_util.h"
-#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "components/signin/core/browser/test_signin_client.h"
-#include "google_apis/gaia/fake_oauth2_token_service.h"
+#include "components/signin/internal/identity_manager/account_fetcher_service.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h"
+#include "components/signin/public/base/avatar_icon_util.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/base/test_signin_client.h"
+#include "components/signin/public/identity_manager/account_info.h"
#include "google_apis/gaia/gaia_oauth_client.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/http/http_status_code.h"
@@ -34,7 +33,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_ANDROID)
-#include "components/signin/core/browser/child_account_info_fetcher_android.h"
+#include "components/signin/internal/identity_manager/child_account_info_fetcher_android.h"
#endif
namespace {
@@ -147,19 +146,12 @@ class TrackingEvent {
account_id_.c_str(), gaia_id_.c_str(), email_.c_str());
}
- private:
- friend bool CompareByUser(TrackingEvent a, TrackingEvent b);
-
TrackingEventType type_;
std::string account_id_;
std::string gaia_id_;
std::string email_;
};
-bool CompareByUser(TrackingEvent a, TrackingEvent b) {
- return a.account_id_ < b.account_id_;
-}
-
std::string Str(const std::vector<TrackingEvent>& events) {
std::string str = "[";
bool needs_comma = false;
@@ -173,60 +165,6 @@ std::string Str(const std::vector<TrackingEvent>& events) {
return str;
}
-class AccountTrackerObserver : public AccountTrackerService::Observer {
- public:
- AccountTrackerObserver() {}
- ~AccountTrackerObserver() override {}
-
- void Clear();
- void SortEventsByUser();
-
- testing::AssertionResult CheckEvents(
- const std::vector<TrackingEvent>& events);
-
- private:
- // AccountTrackerService::Observer implementation
- void OnAccountUpdated(const AccountInfo& ids) override;
- void OnAccountRemoved(const AccountInfo& ids) override;
-
- std::vector<TrackingEvent> events_;
-};
-
-void AccountTrackerObserver::OnAccountUpdated(const AccountInfo& ids) {
- events_.push_back(
- TrackingEvent(UPDATED, ids.account_id, ids.gaia, ids.email));
-}
-
-void AccountTrackerObserver::OnAccountRemoved(const AccountInfo& ids) {
- events_.push_back(
- TrackingEvent(REMOVED, ids.account_id, ids.gaia, ids.email));
-}
-
-void AccountTrackerObserver::Clear() {
- events_.clear();
-}
-
-void AccountTrackerObserver::SortEventsByUser() {
- std::stable_sort(events_.begin(), events_.end(), CompareByUser);
-}
-
-testing::AssertionResult AccountTrackerObserver::CheckEvents(
- const std::vector<TrackingEvent>& events) {
- std::string maybe_newline;
- if ((events.size() + events_.size()) > 2)
- maybe_newline = "\n";
-
- testing::AssertionResult result(
- (events_ == events)
- ? testing::AssertionSuccess()
- : (testing::AssertionFailure()
- << "Expected " << maybe_newline << Str(events) << ", "
- << maybe_newline << "Got " << maybe_newline << Str(events_)));
-
- events_.clear();
- return result;
-}
-
} // namespace
class AccountTrackerServiceTest : public testing::Test {
@@ -240,6 +178,7 @@ class AccountTrackerServiceTest : public testing::Test {
AccountTrackerService::RegisterPrefs(pref_service_.registry());
AccountFetcherService::RegisterPrefs(pref_service_.registry());
+ ProfileOAuth2TokenService::RegisterProfilePrefs(pref_service_.registry());
}
~AccountTrackerServiceTest() override {}
@@ -247,7 +186,7 @@ class AccountTrackerServiceTest : public testing::Test {
void SetUp() override {
testing::Test::SetUp();
CreateAccountTracker(base::FilePath(), /*network_enabled=*/true);
- observer_.Clear();
+ fake_oauth2_token_service_.LoadCredentials("");
}
void TearDown() override {
@@ -300,6 +239,36 @@ class AccountTrackerServiceTest : public testing::Test {
EXPECT_EQ(AccountKeyToLocale(account_key), info.locale);
}
+ testing::AssertionResult CheckAccountTrackerEvents(
+ const std::vector<TrackingEvent>& events) {
+ std::string maybe_newline;
+ if ((events.size() + account_tracker_events_.size()) > 2)
+ maybe_newline = "\n";
+
+ testing::AssertionResult result(
+ (account_tracker_events_ == events)
+ ? testing::AssertionSuccess()
+ : (testing::AssertionFailure()
+ << "Expected " << maybe_newline << Str(events) << ", "
+ << maybe_newline << "Got " << maybe_newline
+ << Str(account_tracker_events_)));
+
+ account_tracker_events_.clear();
+ return result;
+ }
+
+ void ClearAccountTrackerEvents() { account_tracker_events_.clear(); }
+
+ void OnAccountUpdated(const AccountInfo& ids) {
+ account_tracker_events_.push_back(
+ TrackingEvent(UPDATED, ids.account_id, ids.gaia, ids.email));
+ }
+
+ void OnAccountRemoved(const AccountInfo& ids) {
+ account_tracker_events_.push_back(
+ TrackingEvent(REMOVED, ids.account_id, ids.gaia, ids.email));
+ }
+
// Helpers to fake access token and user info fetching
void IssueAccessToken(AccountKey account_key) {
fake_oauth2_token_service_.IssueAllTokensForAccount(
@@ -337,7 +306,6 @@ class AccountTrackerServiceTest : public testing::Test {
}
SigninClient* signin_client() { return &signin_client_; }
PrefService* prefs() { return &pref_service_; }
- AccountTrackerObserver* observer() { return &observer_; }
network::TestURLLoaderFactory* GetTestURLLoaderFactory() {
return signin_client_.GetTestURLLoaderFactory();
@@ -364,10 +332,12 @@ class AccountTrackerServiceTest : public testing::Test {
account_tracker_ = std::make_unique<AccountTrackerService>();
account_fetcher_ = std::make_unique<AccountFetcherService>();
- // Register observer before initialisation to allow the tests to check the
- // events that are triggered during the initialisation. If a test is not
- // interested in them, it can clear the observer before using it.
- account_tracker_->AddObserver(&observer_);
+ // Register callbacks before initialisation to allow the tests to check the
+ // events that are triggered during the initialisation.
+ account_tracker_->SetOnAccountUpdatedCallback(base::BindRepeating(
+ &AccountTrackerServiceTest::OnAccountUpdated, base::Unretained(this)));
+ account_tracker_->SetOnAccountRemovedCallback(base::BindRepeating(
+ &AccountTrackerServiceTest::OnAccountRemoved, base::Unretained(this)));
account_tracker_->Initialize(&pref_service_, std::move(path));
account_fetcher_->Initialize(
@@ -385,9 +355,6 @@ class AccountTrackerServiceTest : public testing::Test {
}
if (account_tracker_) {
- account_tracker_->RemoveObserver(&observer_);
- observer_.Clear();
-
account_tracker_->Shutdown();
account_tracker_.reset();
}
@@ -395,10 +362,10 @@ class AccountTrackerServiceTest : public testing::Test {
TestingPrefServiceSimple pref_service_;
TestSigninClient signin_client_;
- AccountTrackerObserver observer_;
FakeProfileOAuth2TokenService fake_oauth2_token_service_;
std::unique_ptr<AccountFetcherService> account_fetcher_;
std::unique_ptr<AccountTrackerService> account_tracker_;
+ std::vector<TrackingEvent> account_tracker_events_;
bool force_account_id_to_email_for_legacy_tests_ = false;
};
@@ -456,21 +423,21 @@ TEST_F(AccountTrackerServiceTest, Basic) {}
TEST_F(AccountTrackerServiceTest, TokenAvailable) {
SimulateTokenAvailable(kAccountKeyAlpha);
EXPECT_FALSE(account_fetcher()->IsAllUserInfoFetched());
- EXPECT_TRUE(observer()->CheckEvents({}));
+ EXPECT_TRUE(CheckAccountTrackerEvents({}));
}
TEST_F(AccountTrackerServiceTest, TokenAvailable_Revoked) {
SimulateTokenAvailable(kAccountKeyAlpha);
SimulateTokenRevoked(kAccountKeyAlpha);
EXPECT_TRUE(account_fetcher()->IsAllUserInfoFetched());
- EXPECT_TRUE(observer()->CheckEvents({}));
+ EXPECT_TRUE(CheckAccountTrackerEvents({}));
}
TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfo_ImageSuccess) {
SimulateTokenAvailable(kAccountKeyAlpha);
ReturnAccountInfoFetchSuccess(kAccountKeyAlpha);
EXPECT_TRUE(account_fetcher()->IsAllUserInfoFetched());
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
AccountKeyToGaiaId(kAccountKeyAlpha),
AccountKeyToEmail(kAccountKeyAlpha)),
@@ -480,7 +447,7 @@ TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfo_ImageSuccess) {
->GetAccountInfo(AccountKeyToAccountId(kAccountKeyAlpha))
.account_image.IsEmpty());
ReturnAccountImageFetchSuccess(kAccountKeyAlpha);
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
AccountKeyToGaiaId(kAccountKeyAlpha),
AccountKeyToEmail(kAccountKeyAlpha)),
@@ -494,7 +461,7 @@ TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfo_ImageFailure) {
SimulateTokenAvailable(kAccountKeyAlpha);
ReturnAccountInfoFetchSuccess(kAccountKeyAlpha);
EXPECT_TRUE(account_fetcher()->IsAllUserInfoFetched());
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
AccountKeyToGaiaId(kAccountKeyAlpha),
AccountKeyToEmail(kAccountKeyAlpha)),
@@ -513,13 +480,13 @@ TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfo_Revoked) {
SimulateTokenAvailable(kAccountKeyAlpha);
ReturnAccountInfoFetchSuccess(kAccountKeyAlpha);
EXPECT_TRUE(account_fetcher()->IsAllUserInfoFetched());
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
AccountKeyToGaiaId(kAccountKeyAlpha),
AccountKeyToEmail(kAccountKeyAlpha)),
}));
SimulateTokenRevoked(kAccountKeyAlpha);
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(REMOVED, AccountKeyToAccountId(kAccountKeyAlpha),
AccountKeyToGaiaId(kAccountKeyAlpha),
AccountKeyToEmail(kAccountKeyAlpha)),
@@ -530,14 +497,14 @@ TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfoFailed) {
SimulateTokenAvailable(kAccountKeyAlpha);
ReturnAccountInfoFetchFailure(kAccountKeyAlpha);
EXPECT_TRUE(account_fetcher()->IsAllUserInfoFetched());
- EXPECT_TRUE(observer()->CheckEvents({}));
+ EXPECT_TRUE(CheckAccountTrackerEvents({}));
}
TEST_F(AccountTrackerServiceTest, TokenAvailableTwice_UserInfoOnce) {
SimulateTokenAvailable(kAccountKeyAlpha);
ReturnAccountInfoFetchSuccess(kAccountKeyAlpha);
EXPECT_TRUE(account_fetcher()->IsAllUserInfoFetched());
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
AccountKeyToGaiaId(kAccountKeyAlpha),
AccountKeyToEmail(kAccountKeyAlpha)),
@@ -545,14 +512,14 @@ TEST_F(AccountTrackerServiceTest, TokenAvailableTwice_UserInfoOnce) {
SimulateTokenAvailable(kAccountKeyAlpha);
EXPECT_TRUE(account_fetcher()->IsAllUserInfoFetched());
- EXPECT_TRUE(observer()->CheckEvents({}));
+ EXPECT_TRUE(CheckAccountTrackerEvents({}));
}
TEST_F(AccountTrackerServiceTest, TokenAlreadyExists) {
SimulateTokenAvailable(kAccountKeyAlpha);
EXPECT_FALSE(account_fetcher()->IsAllUserInfoFetched());
- EXPECT_TRUE(observer()->CheckEvents({}));
+ EXPECT_TRUE(CheckAccountTrackerEvents({}));
}
TEST_F(AccountTrackerServiceTest, TwoTokenAvailable_TwoUserInfo) {
@@ -561,7 +528,7 @@ TEST_F(AccountTrackerServiceTest, TwoTokenAvailable_TwoUserInfo) {
ReturnAccountInfoFetchSuccess(kAccountKeyAlpha);
ReturnAccountInfoFetchSuccess(kAccountKeyBeta);
EXPECT_TRUE(account_fetcher()->IsAllUserInfoFetched());
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
AccountKeyToGaiaId(kAccountKeyAlpha),
AccountKeyToEmail(kAccountKeyAlpha)),
@@ -576,14 +543,14 @@ TEST_F(AccountTrackerServiceTest, TwoTokenAvailable_OneUserInfo) {
SimulateTokenAvailable(kAccountKeyBeta);
ReturnAccountInfoFetchSuccess(kAccountKeyBeta);
EXPECT_FALSE(account_fetcher()->IsAllUserInfoFetched());
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyBeta),
AccountKeyToGaiaId(kAccountKeyBeta),
AccountKeyToEmail(kAccountKeyBeta)),
}));
ReturnAccountInfoFetchSuccess(kAccountKeyAlpha);
EXPECT_TRUE(account_fetcher()->IsAllUserInfoFetched());
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
AccountKeyToGaiaId(kAccountKeyAlpha),
AccountKeyToEmail(kAccountKeyAlpha)),
@@ -703,9 +670,10 @@ TEST_F(AccountTrackerServiceTest, Persistence) {
// Create a new tracker and make sure it loads the accounts (including the
// images) correctly from persistence.
+ ClearAccountTrackerEvents();
ResetAccountTrackerWithPersistence(scoped_user_data_dir.GetPath());
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
AccountKeyToGaiaId(kAccountKeyAlpha),
AccountKeyToEmail(kAccountKeyAlpha)),
@@ -715,7 +683,7 @@ TEST_F(AccountTrackerServiceTest, Persistence) {
}));
// Wait until all account images are loaded.
scoped_task_environment_.RunUntilIdle();
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
AccountKeyToGaiaId(kAccountKeyAlpha),
AccountKeyToEmail(kAccountKeyAlpha)),
@@ -776,7 +744,7 @@ TEST_F(AccountTrackerServiceTest, SeedAccountInfo) {
EXPECT_EQ(account_id, infos[0].account_id);
EXPECT_EQ(gaia_id, infos[0].gaia);
EXPECT_EQ(email, infos[0].email);
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, account_id, gaia_id, email),
}));
@@ -789,7 +757,7 @@ TEST_F(AccountTrackerServiceTest, SeedAccountInfo) {
"remain the same";
EXPECT_EQ(gaia_id, infos[0].gaia);
EXPECT_EQ(email_dotted, infos[0].email) << "Email should be changed";
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, account_id, gaia_id, email_dotted),
}));
}
@@ -807,7 +775,7 @@ TEST_F(AccountTrackerServiceTest, SeedAccountInfoFull) {
EXPECT_EQ(info.gaia, stored_info.gaia);
EXPECT_EQ(info.email, stored_info.email);
EXPECT_EQ(info.full_name, stored_info.full_name);
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, info.account_id, info.gaia, info.email),
}));
@@ -822,7 +790,7 @@ TEST_F(AccountTrackerServiceTest, SeedAccountInfoFull) {
EXPECT_EQ(info.gaia, stored_info.gaia);
EXPECT_EQ(info.email, stored_info.email);
EXPECT_EQ(info.given_name, stored_info.given_name);
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, info.account_id, info.gaia, info.email),
}));
@@ -833,7 +801,7 @@ TEST_F(AccountTrackerServiceTest, SeedAccountInfoFull) {
stored_info = account_tracker()->GetAccountInfo(info.account_id);
EXPECT_EQ(info.gaia, stored_info.gaia);
EXPECT_NE(info.given_name, stored_info.given_name);
- EXPECT_TRUE(observer()->CheckEvents({}));
+ EXPECT_TRUE(CheckAccountTrackerEvents({}));
}
TEST_F(AccountTrackerServiceTest, UpgradeToFullAccountInfo) {
@@ -861,9 +829,10 @@ TEST_F(AccountTrackerServiceTest, UpgradeToFullAccountInfo) {
// Reinstantiate a tracker to validate that the AccountInfo saved to prefs
// is now the upgraded one, considered valid.
+ ClearAccountTrackerEvents();
ResetAccountTrackerNetworkDisabled();
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyIncomplete),
AccountKeyToGaiaId(kAccountKeyIncomplete),
AccountKeyToEmail(kAccountKeyIncomplete)),
@@ -877,7 +846,7 @@ TEST_F(AccountTrackerServiceTest, UpgradeToFullAccountInfo) {
ASSERT_EQ(1u, infos.size());
EXPECT_TRUE(infos[0].IsValid());
// Check that no network fetches were made.
- EXPECT_TRUE(observer()->CheckEvents({}));
+ EXPECT_TRUE(CheckAccountTrackerEvents({}));
}
TEST_F(AccountTrackerServiceTest, TimerRefresh) {
@@ -1134,7 +1103,7 @@ TEST_F(AccountTrackerServiceTest, ChildAccountBasic) {
#endif
// Response was processed but observer is not notified as the account
// state is invalid.
- EXPECT_TRUE(observer()->CheckEvents({}));
+ EXPECT_TRUE(CheckAccountTrackerEvents({}));
AccountInfo info = account_tracker()->GetAccountInfo(
AccountKeyToAccountId(kAccountKeyChild));
EXPECT_TRUE(info.is_child_account);
@@ -1153,7 +1122,7 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedAndRevoked) {
#endif
ReturnFetchResults(net::HTTP_OK,
GenerateValidTokenInfoResponse(kAccountKeyChild));
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyChild),
AccountKeyToGaiaId(kAccountKeyChild),
AccountKeyToEmail(kAccountKeyChild)),
@@ -1162,7 +1131,7 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedAndRevoked) {
AccountKeyToAccountId(kAccountKeyChild));
EXPECT_FALSE(info.is_child_account);
SimulateTokenRevoked(kAccountKeyChild);
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(REMOVED, AccountKeyToAccountId(kAccountKeyChild),
AccountKeyToGaiaId(kAccountKeyChild),
AccountKeyToEmail(kAccountKeyChild)),
@@ -1181,7 +1150,7 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedAndRevokedWithUpdate) {
#endif
ReturnFetchResults(net::HTTP_OK,
GenerateValidTokenInfoResponse(kAccountKeyChild));
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyChild),
AccountKeyToGaiaId(kAccountKeyChild),
AccountKeyToEmail(kAccountKeyChild)),
@@ -1192,7 +1161,7 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedAndRevokedWithUpdate) {
SimulateTokenRevoked(kAccountKeyChild);
#if defined(OS_ANDROID)
// On Android, is_child_account is set to false before removing it.
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyChild),
AccountKeyToGaiaId(kAccountKeyChild),
AccountKeyToEmail(kAccountKeyChild)),
@@ -1201,7 +1170,7 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedAndRevokedWithUpdate) {
AccountKeyToEmail(kAccountKeyChild)),
}));
#else
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(REMOVED, AccountKeyToAccountId(kAccountKeyChild),
AccountKeyToGaiaId(kAccountKeyChild),
AccountKeyToEmail(kAccountKeyChild)),
@@ -1222,7 +1191,7 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedTwiceThenRevoked) {
account_tracker()->SetIsChildAccount(AccountKeyToAccountId(kAccountKeyChild),
true);
#endif
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyChild),
AccountKeyToGaiaId(kAccountKeyChild),
AccountKeyToEmail(kAccountKeyChild)),
@@ -1233,7 +1202,7 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedTwiceThenRevoked) {
SimulateTokenRevoked(kAccountKeyChild);
#if defined(OS_ANDROID)
// On Android, is_child_account is set to false before removing it.
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyChild),
AccountKeyToGaiaId(kAccountKeyChild),
AccountKeyToEmail(kAccountKeyChild)),
@@ -1242,7 +1211,7 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedTwiceThenRevoked) {
AccountKeyToEmail(kAccountKeyChild)),
}));
#else
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(REMOVED, AccountKeyToAccountId(kAccountKeyChild),
AccountKeyToGaiaId(kAccountKeyChild),
AccountKeyToEmail(kAccountKeyChild)),
@@ -1267,7 +1236,7 @@ TEST_F(AccountTrackerServiceTest, ChildAccountGraduation) {
EXPECT_TRUE(info.is_child_account);
ReturnFetchResults(net::HTTP_OK,
GenerateValidTokenInfoResponse(kAccountKeyChild));
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyChild),
AccountKeyToGaiaId(kAccountKeyChild),
AccountKeyToEmail(kAccountKeyChild)),
@@ -1284,14 +1253,14 @@ TEST_F(AccountTrackerServiceTest, ChildAccountGraduation) {
info = account_tracker()->GetAccountInfo(
AccountKeyToAccountId(kAccountKeyChild));
EXPECT_FALSE(info.is_child_account);
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyChild),
AccountKeyToGaiaId(kAccountKeyChild),
AccountKeyToEmail(kAccountKeyChild)),
}));
SimulateTokenRevoked(kAccountKeyChild);
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(REMOVED, AccountKeyToAccountId(kAccountKeyChild),
AccountKeyToGaiaId(kAccountKeyChild),
AccountKeyToEmail(kAccountKeyChild)),
@@ -1302,7 +1271,7 @@ TEST_F(AccountTrackerServiceTest, RemoveAccountBeforeImageFetchDone) {
SimulateTokenAvailable(kAccountKeyAlpha);
ReturnAccountInfoFetchSuccess(kAccountKeyAlpha);
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
AccountKeyToGaiaId(kAccountKeyAlpha),
AccountKeyToEmail(kAccountKeyAlpha)),
@@ -1310,7 +1279,7 @@ TEST_F(AccountTrackerServiceTest, RemoveAccountBeforeImageFetchDone) {
SimulateTokenRevoked(kAccountKeyAlpha);
ReturnAccountImageFetchFailure(kAccountKeyAlpha);
- EXPECT_TRUE(observer()->CheckEvents({
+ EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(REMOVED, AccountKeyToAccountId(kAccountKeyAlpha),
AccountKeyToGaiaId(kAccountKeyAlpha),
AccountKeyToEmail(kAccountKeyAlpha)),
diff --git a/chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc b/chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc
new file mode 100644
index 00000000000..d2b158e4d04
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc
@@ -0,0 +1,66 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h"
+
+#include <utility>
+
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h"
+#include "google_apis/gaia/core_account_id.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+
+namespace signin {
+
+AccountsCookieMutatorImpl::AccountsCookieMutatorImpl(
+ GaiaCookieManagerService* gaia_cookie_manager_service,
+ AccountTrackerService* account_tracker_service)
+ : gaia_cookie_manager_service_(gaia_cookie_manager_service),
+ account_tracker_service_(account_tracker_service) {
+ DCHECK(gaia_cookie_manager_service_);
+ DCHECK(account_tracker_service_);
+}
+
+AccountsCookieMutatorImpl::~AccountsCookieMutatorImpl() {}
+
+void AccountsCookieMutatorImpl::AddAccountToCookie(
+ const CoreAccountId& account_id,
+ gaia::GaiaSource source,
+ AddAccountToCookieCompletedCallback completion_callback) {
+ gaia_cookie_manager_service_->AddAccountToCookie(
+ account_id, source, std::move(completion_callback));
+}
+
+void AccountsCookieMutatorImpl::AddAccountToCookieWithToken(
+ const CoreAccountId& account_id,
+ const std::string& access_token,
+ gaia::GaiaSource source,
+ AddAccountToCookieCompletedCallback completion_callback) {
+ gaia_cookie_manager_service_->AddAccountToCookieWithToken(
+ account_id, access_token, source, std::move(completion_callback));
+}
+
+void AccountsCookieMutatorImpl::SetAccountsInCookie(
+ const std::vector<CoreAccountId>& account_ids,
+ gaia::GaiaSource source,
+ base::OnceCallback<void(SetAccountsInCookieResult)>
+ set_accounts_in_cookies_completed_callback) {
+ std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair> accounts;
+ for (const auto& account_id : account_ids) {
+ accounts.push_back(make_pair(
+ account_id, account_tracker_service_->GetAccountInfo(account_id).gaia));
+ }
+ gaia_cookie_manager_service_->SetAccountsInCookie(
+ accounts, source, std::move(set_accounts_in_cookies_completed_callback));
+}
+
+void AccountsCookieMutatorImpl::TriggerCookieJarUpdate() {
+ gaia_cookie_manager_service_->TriggerListAccounts();
+}
+
+void AccountsCookieMutatorImpl::LogOutAllAccounts(gaia::GaiaSource source) {
+ gaia_cookie_manager_service_->LogOutAllAccounts(source);
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h b/chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h
new file mode 100644
index 00000000000..a083bbb1915
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h
@@ -0,0 +1,61 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNTS_COOKIE_MUTATOR_IMPL_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNTS_COOKIE_MUTATOR_IMPL_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "components/signin/public/identity_manager/accounts_cookie_mutator.h"
+
+class AccountTrackerService;
+class GaiaCookieManagerService;
+
+namespace gaia {
+class GaiaSource;
+}
+
+namespace signin {
+
+// Concrete implementation of the AccountsCookieMutator interface.
+class AccountsCookieMutatorImpl : public AccountsCookieMutator {
+ public:
+ explicit AccountsCookieMutatorImpl(
+ GaiaCookieManagerService* gaia_cookie_manager_service,
+ AccountTrackerService* account_tracker_service);
+ ~AccountsCookieMutatorImpl() override;
+
+ void AddAccountToCookie(
+ const CoreAccountId& account_id,
+ gaia::GaiaSource source,
+ AddAccountToCookieCompletedCallback completion_callback) override;
+
+ void AddAccountToCookieWithToken(
+ const CoreAccountId& account_id,
+ const std::string& access_token,
+ gaia::GaiaSource source,
+ AddAccountToCookieCompletedCallback completion_callback) override;
+
+ void SetAccountsInCookie(
+ const std::vector<CoreAccountId>& account_ids,
+ gaia::GaiaSource source,
+ base::OnceCallback<void(SetAccountsInCookieResult)>
+ set_accounts_in_cookies_completed_callback) override;
+
+ void TriggerCookieJarUpdate() override;
+
+ void LogOutAllAccounts(gaia::GaiaSource source) override;
+
+ private:
+ GaiaCookieManagerService* gaia_cookie_manager_service_;
+ AccountTrackerService* account_tracker_service_;
+
+ DISALLOW_COPY_AND_ASSIGN(AccountsCookieMutatorImpl);
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNTS_COOKIE_MUTATOR_IMPL_H_
diff --git a/chromium/components/signin/internal/identity_manager/accounts_mutator_impl.cc b/chromium/components/signin/internal/identity_manager/accounts_mutator_impl.cc
new file mode 100644
index 00000000000..bff6a3de620
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/accounts_mutator_impl.cc
@@ -0,0 +1,116 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/internal/identity_manager/accounts_mutator_impl.h"
+
+#include "base/optional.h"
+#include "components/prefs/pref_service.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/primary_account_manager.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/public/base/device_id_helper.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/identity_manager/account_info.h"
+#include "google_apis/gaia/core_account_id.h"
+#include "google_apis/gaia/gaia_constants.h"
+
+namespace signin {
+
+AccountsMutatorImpl::AccountsMutatorImpl(
+ ProfileOAuth2TokenService* token_service,
+ AccountTrackerService* account_tracker_service,
+ PrimaryAccountManager* primary_account_manager,
+ PrefService* pref_service)
+ : token_service_(token_service),
+ account_tracker_service_(account_tracker_service),
+ primary_account_manager_(primary_account_manager) {
+ DCHECK(token_service_);
+ DCHECK(account_tracker_service_);
+ DCHECK(primary_account_manager_);
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+ pref_service_ = pref_service;
+ DCHECK(pref_service_);
+#endif
+}
+
+AccountsMutatorImpl::~AccountsMutatorImpl() {}
+
+CoreAccountId AccountsMutatorImpl::AddOrUpdateAccount(
+ const std::string& gaia_id,
+ const std::string& email,
+ const std::string& refresh_token,
+ bool is_under_advanced_protection,
+ signin_metrics::SourceForRefreshTokenOperation source) {
+ CoreAccountId account_id =
+ account_tracker_service_->SeedAccountInfo(gaia_id, email);
+ account_tracker_service_->SetIsAdvancedProtectionAccount(
+ account_id, is_under_advanced_protection);
+ token_service_->UpdateCredentials(account_id, refresh_token, source);
+
+ return account_id;
+}
+
+void AccountsMutatorImpl::UpdateAccountInfo(
+ const CoreAccountId& account_id,
+ base::Optional<bool> is_child_account,
+ base::Optional<bool> is_under_advanced_protection) {
+ if (is_child_account.has_value()) {
+ account_tracker_service_->SetIsChildAccount(account_id,
+ is_child_account.value());
+ }
+
+ if (is_under_advanced_protection.has_value()) {
+ account_tracker_service_->SetIsAdvancedProtectionAccount(
+ account_id, is_under_advanced_protection.value());
+ }
+}
+
+void AccountsMutatorImpl::RemoveAccount(
+ const CoreAccountId& account_id,
+ signin_metrics::SourceForRefreshTokenOperation source) {
+ token_service_->RevokeCredentials(account_id, source);
+}
+
+void AccountsMutatorImpl::RemoveAllAccounts(
+ signin_metrics::SourceForRefreshTokenOperation source) {
+ token_service_->RevokeAllCredentials(source);
+}
+
+void AccountsMutatorImpl::InvalidateRefreshTokenForPrimaryAccount(
+ signin_metrics::SourceForRefreshTokenOperation source) {
+ DCHECK(primary_account_manager_->IsAuthenticated());
+ AccountInfo primary_account_info =
+ primary_account_manager_->GetAuthenticatedAccountInfo();
+ AddOrUpdateAccount(primary_account_info.gaia, primary_account_info.email,
+ GaiaConstants::kInvalidRefreshToken,
+ primary_account_info.is_under_advanced_protection, source);
+}
+
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+void AccountsMutatorImpl::MoveAccount(AccountsMutator* target,
+ const CoreAccountId& account_id) {
+ AccountInfo account_info =
+ account_tracker_service_->GetAccountInfo(account_id);
+ DCHECK(!account_info.account_id.empty());
+
+ auto* target_impl = static_cast<AccountsMutatorImpl*>(target);
+ target_impl->account_tracker_service_->SeedAccountInfo(account_info);
+ token_service_->ExtractCredentials(target_impl->token_service_, account_id);
+
+ // Reset the device ID from the source mutator: the exported token is linked
+ // to the device ID of the current mutator on the server. Reset the device ID
+ // of the current mutator to avoid tying it with the new mutator. See
+ // https://crbug.com/813928#c16
+ RecreateSigninScopedDeviceId(pref_service_);
+}
+#endif
+
+void AccountsMutatorImpl::LegacySetRefreshTokenForSupervisedUser(
+ const std::string& refresh_token) {
+ token_service_->UpdateCredentials(
+ CoreAccountId("managed_user@localhost"), refresh_token,
+ signin_metrics::SourceForRefreshTokenOperation::kSupervisedUser_InitSync);
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/internal/identity_manager/accounts_mutator_impl.h b/chromium/components/signin/internal/identity_manager/accounts_mutator_impl.h
new file mode 100644
index 00000000000..0dc2ca05dc2
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/accounts_mutator_impl.h
@@ -0,0 +1,75 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNTS_MUTATOR_IMPL_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNTS_MUTATOR_IMPL_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "components/signin/public/base/signin_buildflags.h"
+#include "components/signin/public/identity_manager/accounts_mutator.h"
+
+namespace signin_metrics {
+enum class SourceForRefreshTokenOperation;
+}
+
+class AccountTrackerService;
+struct CoreAccountId;
+class PrefService;
+class PrimaryAccountManager;
+class ProfileOAuth2TokenService;
+
+namespace signin {
+
+// Concrete implementation of the AccountsMutatorImpl interface.
+class AccountsMutatorImpl : public AccountsMutator {
+ public:
+ explicit AccountsMutatorImpl(ProfileOAuth2TokenService* token_service,
+ AccountTrackerService* account_tracker_service,
+ PrimaryAccountManager* primary_account_manager,
+ PrefService* pref_service);
+ ~AccountsMutatorImpl() override;
+
+ // AccountsMutator:
+ CoreAccountId AddOrUpdateAccount(
+ const std::string& gaia_id,
+ const std::string& email,
+ const std::string& refresh_token,
+ bool is_under_advanced_protection,
+ signin_metrics::SourceForRefreshTokenOperation source) override;
+ void UpdateAccountInfo(
+ const CoreAccountId& account_id,
+ base::Optional<bool> is_child_account,
+ base::Optional<bool> is_under_advanced_protection) override;
+ void RemoveAccount(
+ const CoreAccountId& account_id,
+ signin_metrics::SourceForRefreshTokenOperation source) override;
+ void RemoveAllAccounts(
+ signin_metrics::SourceForRefreshTokenOperation source) override;
+ void InvalidateRefreshTokenForPrimaryAccount(
+ signin_metrics::SourceForRefreshTokenOperation source) override;
+
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+ void MoveAccount(AccountsMutator* target,
+ const CoreAccountId& account_id) override;
+#endif
+
+ void LegacySetRefreshTokenForSupervisedUser(
+ const std::string& refresh_token) override;
+
+ private:
+ ProfileOAuth2TokenService* token_service_;
+ AccountTrackerService* account_tracker_service_;
+ PrimaryAccountManager* primary_account_manager_;
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+ PrefService* pref_service_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(AccountsMutatorImpl);
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNTS_MUTATOR_IMPL_H_
diff --git a/chromium/components/signin/core/browser/child_account_info_fetcher_android.cc b/chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.cc
index 85c6304d81b..77f1d593643 100644
--- a/chromium/components/signin/core/browser/child_account_info_fetcher_android.cc
+++ b/chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.cc
@@ -2,23 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/child_account_info_fetcher_android.h"
+#include "components/signin/internal/identity_manager/child_account_info_fetcher_android.h"
#include <memory>
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/memory/ptr_util.h"
-#include "components/signin/core/browser/account_fetcher_service.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "jni/ChildAccountInfoFetcher_jni.h"
+#include "components/signin/core/browser/android/jni_headers/ChildAccountInfoFetcher_jni.h"
+#include "components/signin/internal/identity_manager/account_fetcher_service.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
using base::android::JavaParamRef;
// static
std::unique_ptr<ChildAccountInfoFetcherAndroid>
ChildAccountInfoFetcherAndroid::Create(AccountFetcherService* service,
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
std::string account_name =
service->account_tracker_service()->GetAccountInfo(account_id).email;
// The AccountTrackerService may not be populated correctly in tests.
@@ -38,12 +38,12 @@ void ChildAccountInfoFetcherAndroid::InitializeForTests() {
ChildAccountInfoFetcherAndroid::ChildAccountInfoFetcherAndroid(
AccountFetcherService* service,
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& account_name) {
JNIEnv* env = base::android::AttachCurrentThread();
j_child_account_info_fetcher_.Reset(Java_ChildAccountInfoFetcher_create(
env, reinterpret_cast<jlong>(service),
- base::android::ConvertUTF8ToJavaString(env, account_id),
+ base::android::ConvertUTF8ToJavaString(env, account_id.id),
base::android::ConvertUTF8ToJavaString(env, account_name)));
}
@@ -60,6 +60,6 @@ void JNI_ChildAccountInfoFetcher_SetIsChildAccount(
AccountFetcherService* service =
reinterpret_cast<AccountFetcherService*>(native_service);
service->SetIsChildAccount(
- base::android::ConvertJavaStringToUTF8(env, j_account_id),
+ CoreAccountId(base::android::ConvertJavaStringToUTF8(env, j_account_id)),
is_child_account);
}
diff --git a/chromium/components/signin/core/browser/child_account_info_fetcher_android.h b/chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.h
index 1007fe59fd3..2b08d1229fb 100644
--- a/chromium/components/signin/core/browser/child_account_info_fetcher_android.h
+++ b/chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.h
@@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_CHILD_ACCOUNT_INFO_FETCHER_ANDROID_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_CHILD_ACCOUNT_INFO_FETCHER_ANDROID_H_
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_CHILD_ACCOUNT_INFO_FETCHER_ANDROID_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_CHILD_ACCOUNT_INFO_FETCHER_ANDROID_H_
#include <jni.h>
#include <string>
#include "base/android/scoped_java_ref.h"
+#include "google_apis/gaia/core_account_id.h"
class AccountFetcherService;
@@ -16,14 +17,14 @@ class ChildAccountInfoFetcherAndroid {
public:
static std::unique_ptr<ChildAccountInfoFetcherAndroid> Create(
AccountFetcherService* service,
- const std::string& account_id);
+ const CoreAccountId& account_id);
~ChildAccountInfoFetcherAndroid();
static void InitializeForTests();
private:
ChildAccountInfoFetcherAndroid(AccountFetcherService* service,
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& account_name);
base::android::ScopedJavaGlobalRef<jobject> j_child_account_info_fetcher_;
@@ -31,4 +32,4 @@ class ChildAccountInfoFetcherAndroid {
DISALLOW_COPY_AND_ASSIGN(ChildAccountInfoFetcherAndroid);
};
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_CHILD_ACCOUNT_INFO_FETCHER_ANDROID_H_
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_CHILD_ACCOUNT_INFO_FETCHER_ANDROID_H_
diff --git a/chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.cc b/chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.cc
new file mode 100644
index 00000000000..d2a4f923394
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.cc
@@ -0,0 +1,29 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h"
+
+#include "base/logging.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
+
+namespace signin {
+
+DeviceAccountsSynchronizerImpl::DeviceAccountsSynchronizerImpl(
+ ProfileOAuth2TokenServiceDelegate* token_service_delegate)
+ : token_service_delegate_(token_service_delegate) {
+ DCHECK(token_service_delegate_);
+}
+
+DeviceAccountsSynchronizerImpl::~DeviceAccountsSynchronizerImpl() = default;
+
+void DeviceAccountsSynchronizerImpl::ReloadAllAccountsFromSystem() {
+ token_service_delegate_->ReloadAllAccountsFromSystem();
+}
+
+void DeviceAccountsSynchronizerImpl::ReloadAccountFromSystem(
+ const CoreAccountId& account_id) {
+ token_service_delegate_->ReloadAccountFromSystem(account_id);
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h b/chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h
new file mode 100644
index 00000000000..74679a0a9a1
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h
@@ -0,0 +1,31 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_DEVICE_ACCOUNTS_SYNCHRONIZER_IMPL_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_DEVICE_ACCOUNTS_SYNCHRONIZER_IMPL_H_
+
+#include "components/signin/public/identity_manager/device_accounts_synchronizer.h"
+
+class ProfileOAuth2TokenServiceDelegate;
+
+namespace signin {
+
+// Concrete implementation of DeviceAccountsSynchronizer interface.
+class DeviceAccountsSynchronizerImpl : public DeviceAccountsSynchronizer {
+ public:
+ explicit DeviceAccountsSynchronizerImpl(
+ ProfileOAuth2TokenServiceDelegate* token_service_delegate);
+ ~DeviceAccountsSynchronizerImpl() override;
+
+ // DeviceAccountsSynchronizer implementation.
+ void ReloadAllAccountsFromSystem() override;
+ void ReloadAccountFromSystem(const CoreAccountId& account_id) override;
+
+ private:
+ ProfileOAuth2TokenServiceDelegate* token_service_delegate_ = nullptr;
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_DEVICE_ACCOUNTS_SYNCHRONIZER_IMPL_H_
diff --git a/chromium/components/signin/internal/identity_manager/diagnostics_provider_impl.cc b/chromium/components/signin/internal/identity_manager/diagnostics_provider_impl.cc
new file mode 100644
index 00000000000..b69036efb23
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/diagnostics_provider_impl.cc
@@ -0,0 +1,44 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/internal/identity_manager/diagnostics_provider_impl.h"
+
+#include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
+
+namespace signin {
+
+DiagnosticsProviderImpl::DiagnosticsProviderImpl(
+ ProfileOAuth2TokenService* profile_oauth2_token_service,
+ GaiaCookieManagerService* gaia_cookie_manager_service)
+ : gaia_cookie_manager_service_(gaia_cookie_manager_service),
+ profile_oauth2_token_service_(profile_oauth2_token_service) {
+ DCHECK(gaia_cookie_manager_service_);
+ DCHECK(profile_oauth2_token_service_);
+}
+
+DiagnosticsProviderImpl::~DiagnosticsProviderImpl() {}
+
+signin::LoadCredentialsState
+DiagnosticsProviderImpl::GetDetailedStateOfLoadingOfRefreshTokens() const {
+ DCHECK(profile_oauth2_token_service_->GetDelegate());
+ return profile_oauth2_token_service_->GetDelegate()->load_credentials_state();
+}
+
+base::TimeDelta
+DiagnosticsProviderImpl::GetDelayBeforeMakingAccessTokenRequests() const {
+ const net::BackoffEntry* backoff_entry =
+ profile_oauth2_token_service_->GetDelegateBackoffEntry();
+ return backoff_entry ? backoff_entry->GetTimeUntilRelease()
+ : base::TimeDelta();
+}
+
+base::TimeDelta DiagnosticsProviderImpl::GetDelayBeforeMakingCookieRequests()
+ const {
+ DCHECK(gaia_cookie_manager_service_->GetBackoffEntry());
+ return gaia_cookie_manager_service_->GetBackoffEntry()->GetTimeUntilRelease();
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/internal/identity_manager/diagnostics_provider_impl.h b/chromium/components/signin/internal/identity_manager/diagnostics_provider_impl.h
new file mode 100644
index 00000000000..2035715c708
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/diagnostics_provider_impl.h
@@ -0,0 +1,45 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_DIAGNOSTICS_PROVIDER_IMPL_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_DIAGNOSTICS_PROVIDER_IMPL_H_
+
+#include "base/macros.h"
+#include "components/signin/public/identity_manager/diagnostics_provider.h"
+
+class GaiaCookieManagerService;
+class ProfileOAuth2TokenService;
+
+namespace signin {
+
+// Concrete implementation of the DiagnosticsProvider interface.
+class DiagnosticsProviderImpl final : public DiagnosticsProvider {
+ public:
+ DiagnosticsProviderImpl(
+ ProfileOAuth2TokenService* profile_oauth2_token_service,
+ GaiaCookieManagerService* gaia_cookie_manager_service);
+ ~DiagnosticsProviderImpl() override;
+
+ // Returns the state of the load credentials operation.
+ signin::LoadCredentialsState GetDetailedStateOfLoadingOfRefreshTokens()
+ const override;
+
+ // Returns the time until a access token request can be sent (will be zero if
+ // the release time is in the past).
+ base::TimeDelta GetDelayBeforeMakingAccessTokenRequests() const override;
+
+ // Returns the time until a cookie request can be sent (will be zero if the
+ // release time is in the past).
+ base::TimeDelta GetDelayBeforeMakingCookieRequests() const override;
+
+ private:
+ GaiaCookieManagerService* gaia_cookie_manager_service_;
+ ProfileOAuth2TokenService* profile_oauth2_token_service_;
+
+ DISALLOW_COPY_AND_ASSIGN(DiagnosticsProviderImpl);
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_DIAGNOSTICS_PROVIDER_IMPL_H_
diff --git a/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.cc b/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.cc
new file mode 100644
index 00000000000..586ce74d74f
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.cc
@@ -0,0 +1,101 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h"
+
+#include <memory>
+
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.h"
+
+FakeProfileOAuth2TokenService::FakeProfileOAuth2TokenService(
+ PrefService* user_prefs)
+ : FakeProfileOAuth2TokenService(
+ user_prefs,
+ std::make_unique<FakeProfileOAuth2TokenServiceDelegate>()) {}
+
+FakeProfileOAuth2TokenService::FakeProfileOAuth2TokenService(
+ PrefService* user_prefs,
+ std::unique_ptr<ProfileOAuth2TokenServiceDelegate> delegate)
+ : ProfileOAuth2TokenService(user_prefs, std::move(delegate)) {
+ OverrideAccessTokenManagerForTesting(
+ std::make_unique<FakeOAuth2AccessTokenManager>(
+ this /* OAuth2AccessTokenManager::Delegate* */));
+}
+
+FakeProfileOAuth2TokenService::~FakeProfileOAuth2TokenService() {}
+
+void FakeProfileOAuth2TokenService::IssueAllTokensForAccount(
+ const std::string& account_id,
+ const std::string& access_token,
+ const base::Time& expiration) {
+ GetFakeAccessTokenManager()->IssueAllTokensForAccount(
+ account_id, access_token, expiration);
+}
+
+void FakeProfileOAuth2TokenService::IssueAllTokensForAccount(
+ const std::string& account_id,
+ const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
+ GetFakeAccessTokenManager()->IssueAllTokensForAccount(account_id,
+ token_response);
+}
+
+void FakeProfileOAuth2TokenService::IssueErrorForAllPendingRequestsForAccount(
+ const std::string& account_id,
+ const GoogleServiceAuthError& error) {
+ GetFakeAccessTokenManager()->IssueErrorForAllPendingRequestsForAccount(
+ account_id, error);
+}
+
+void FakeProfileOAuth2TokenService::IssueTokenForScope(
+ const OAuth2AccessTokenManager::ScopeSet& scope,
+ const std::string& access_token,
+ const base::Time& expiration) {
+ GetFakeAccessTokenManager()->IssueTokenForScope(scope, access_token,
+ expiration);
+}
+
+void FakeProfileOAuth2TokenService::IssueTokenForScope(
+ const OAuth2AccessTokenManager::ScopeSet& scope,
+ const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
+ GetFakeAccessTokenManager()->IssueTokenForScope(scope, token_response);
+}
+
+void FakeProfileOAuth2TokenService::IssueErrorForScope(
+ const OAuth2AccessTokenManager::ScopeSet& scope,
+ const GoogleServiceAuthError& error) {
+ GetFakeAccessTokenManager()->IssueErrorForScope(scope, error);
+}
+
+void FakeProfileOAuth2TokenService::IssueErrorForAllPendingRequests(
+ const GoogleServiceAuthError& error) {
+ GetFakeAccessTokenManager()->IssueErrorForAllPendingRequests(error);
+}
+
+void FakeProfileOAuth2TokenService::
+ set_auto_post_fetch_response_on_message_loop(bool auto_post_response) {
+ GetFakeAccessTokenManager()->set_auto_post_fetch_response_on_message_loop(
+ auto_post_response);
+}
+
+void FakeProfileOAuth2TokenService::IssueTokenForAllPendingRequests(
+ const std::string& access_token,
+ const base::Time& expiration) {
+ GetFakeAccessTokenManager()->IssueTokenForAllPendingRequests(access_token,
+ expiration);
+}
+
+void FakeProfileOAuth2TokenService::IssueTokenForAllPendingRequests(
+ const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
+ GetFakeAccessTokenManager()->IssueTokenForAllPendingRequests(token_response);
+}
+
+std::vector<FakeOAuth2AccessTokenManager::PendingRequest>
+FakeProfileOAuth2TokenService::GetPendingRequests() {
+ return GetFakeAccessTokenManager()->GetPendingRequests();
+}
+
+FakeOAuth2AccessTokenManager*
+FakeProfileOAuth2TokenService::GetFakeAccessTokenManager() {
+ return static_cast<FakeOAuth2AccessTokenManager*>(GetAccessTokenManager());
+}
diff --git a/chromium/components/signin/core/browser/fake_profile_oauth2_token_service.h b/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h
index be71e20267d..f06a83a1b14 100644
--- a/chromium/components/signin/core/browser/fake_profile_oauth2_token_service.h
+++ b/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h
@@ -2,20 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
-
-namespace network {
-class SharedURLLoaderFactory;
-}
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "google_apis/gaia/fake_oauth2_access_token_manager.h"
// Helper class to simplify writing unittests that depend on an instance of
// ProfileOAuth2TokenService.
@@ -30,7 +26,7 @@ class SharedURLLoaderFactory;
// EXPECT_GT(0U, service.GetPendingRequests().size());
// ...
// // Make any pending token fetches for a given scope succeed.
-// ScopeSet scopes;
+// OAuth2AccessTokenManager::ScopeSet scopes;
// scopes.insert(GaiaConstants::kYourServiceScope);
// IssueTokenForScope(scopes, "access_token", base::Time()::Max());
// ...
@@ -39,28 +35,16 @@ class SharedURLLoaderFactory;
//
class FakeProfileOAuth2TokenService : public ProfileOAuth2TokenService {
public:
- struct PendingRequest {
- PendingRequest();
- PendingRequest(const PendingRequest& other);
- ~PendingRequest();
-
- std::string account_id;
- std::string client_id;
- std::string client_secret;
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory;
- ScopeSet scopes;
- base::WeakPtr<RequestImpl> request;
- };
-
explicit FakeProfileOAuth2TokenService(PrefService* user_prefs);
FakeProfileOAuth2TokenService(
PrefService* user_prefs,
- std::unique_ptr<OAuth2TokenServiceDelegate> delegate);
+ std::unique_ptr<ProfileOAuth2TokenServiceDelegate> delegate);
~FakeProfileOAuth2TokenService() override;
// Gets a list of active requests (can be used by tests to validate that the
// correct request has been issued).
- std::vector<PendingRequest> GetPendingRequests();
+ std::vector<FakeOAuth2AccessTokenManager::PendingRequest>
+ GetPendingRequests();
// Helper routines to issue tokens for pending requests.
void IssueAllTokensForAccount(const std::string& account_id,
@@ -76,15 +60,15 @@ class FakeProfileOAuth2TokenService : public ProfileOAuth2TokenService {
const std::string& account_id,
const GoogleServiceAuthError& error);
- void IssueTokenForScope(const ScopeSet& scopes,
+ void IssueTokenForScope(const OAuth2AccessTokenManager::ScopeSet& scopes,
const std::string& access_token,
const base::Time& expiration);
void IssueTokenForScope(
- const ScopeSet& scopes,
+ const OAuth2AccessTokenManager::ScopeSet& scopes,
const OAuth2AccessTokenConsumer::TokenResponse& token_response);
- void IssueErrorForScope(const ScopeSet& scopes,
+ void IssueErrorForScope(const OAuth2AccessTokenManager::ScopeSet& scopes,
const GoogleServiceAuthError& error);
void IssueTokenForAllPendingRequests(const std::string& access_token,
@@ -95,52 +79,12 @@ class FakeProfileOAuth2TokenService : public ProfileOAuth2TokenService {
void IssueErrorForAllPendingRequests(const GoogleServiceAuthError& error);
- void set_auto_post_fetch_response_on_message_loop(bool auto_post_response) {
- auto_post_fetch_response_on_message_loop_ = auto_post_response;
- }
-
- protected:
- // OAuth2TokenService overrides.
- void CancelAllRequests() override;
-
- void CancelRequestsForAccount(const std::string& account_id) override;
-
- void FetchOAuth2Token(
- RequestImpl* request,
- const std::string& account_id,
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- const std::string& client_id,
- const std::string& client_secret,
- const ScopeSet& scopes) override;
-
- void InvalidateAccessTokenImpl(const std::string& account_id,
- const std::string& client_id,
- const ScopeSet& scopes,
- const std::string& access_token) override;
+ void set_auto_post_fetch_response_on_message_loop(bool auto_post_response);
private:
- // Helper function to complete pending requests - if |all_scopes| is true,
- // then all pending requests are completed, otherwise, only those requests
- // matching |scopes| are completed. If |account_id| is empty, then pending
- // requests for all accounts are completed, otherwise only requests for the
- // given account.
- void CompleteRequests(
- const std::string& account_id,
- bool all_scopes,
- const ScopeSet& scopes,
- const GoogleServiceAuthError& error,
- const OAuth2AccessTokenConsumer::TokenResponse& token_response);
-
- std::vector<PendingRequest> pending_requests_;
-
- // If true, then this fake service will post responses to
- // |FetchOAuth2Token| on the current run loop. There is no need to call
- // |IssueTokenForScope| in this case.
- bool auto_post_fetch_response_on_message_loop_;
-
- base::WeakPtrFactory<FakeProfileOAuth2TokenService> weak_ptr_factory_;
+ FakeOAuth2AccessTokenManager* GetFakeAccessTokenManager();
DISALLOW_COPY_AND_ASSIGN(FakeProfileOAuth2TokenService);
};
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
diff --git a/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.cc b/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.cc
new file mode 100644
index 00000000000..701bbe89c68
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.cc
@@ -0,0 +1,170 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.h"
+
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
+
+namespace {
+// Values used from |MutableProfileOAuth2TokenServiceDelegate|.
+const net::BackoffEntry::Policy kBackoffPolicy = {
+ 0 /* int num_errors_to_ignore */,
+
+ 1000 /* int initial_delay_ms */,
+
+ 2.0 /* double multiply_factor */,
+
+ 0.2 /* double jitter_factor */,
+
+ 15 * 60 * 1000 /* int64_t maximum_backoff_ms */,
+
+ -1 /* int64_t entry_lifetime_ms */,
+
+ false /* bool always_use_initial_delay */,
+};
+} // namespace
+
+FakeProfileOAuth2TokenServiceDelegate::AccountInfo::AccountInfo(
+ const std::string& refresh_token)
+ : refresh_token(refresh_token), error(GoogleServiceAuthError::NONE) {}
+
+FakeProfileOAuth2TokenServiceDelegate::FakeProfileOAuth2TokenServiceDelegate()
+ : shared_factory_(
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ &test_url_loader_factory_)),
+ backoff_entry_(&kBackoffPolicy) {}
+
+FakeProfileOAuth2TokenServiceDelegate::
+ ~FakeProfileOAuth2TokenServiceDelegate() = default;
+
+std::unique_ptr<OAuth2AccessTokenFetcher>
+FakeProfileOAuth2TokenServiceDelegate::CreateAccessTokenFetcher(
+ const CoreAccountId& account_id,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ OAuth2AccessTokenConsumer* consumer) {
+ auto it = refresh_tokens_.find(account_id);
+ DCHECK(it != refresh_tokens_.end());
+ return std::make_unique<OAuth2AccessTokenFetcherImpl>(
+ consumer, url_loader_factory, it->second->refresh_token);
+}
+
+bool FakeProfileOAuth2TokenServiceDelegate::RefreshTokenIsAvailable(
+ const CoreAccountId& account_id) const {
+ return !GetRefreshToken(account_id).empty();
+}
+
+GoogleServiceAuthError FakeProfileOAuth2TokenServiceDelegate::GetAuthError(
+ const CoreAccountId& account_id) const {
+ auto it = refresh_tokens_.find(account_id);
+ return (it == refresh_tokens_.end()) ? GoogleServiceAuthError::AuthErrorNone()
+ : it->second->error;
+}
+
+std::string FakeProfileOAuth2TokenServiceDelegate::GetRefreshToken(
+ const CoreAccountId& account_id) const {
+ auto it = refresh_tokens_.find(account_id);
+ if (it != refresh_tokens_.end())
+ return it->second->refresh_token;
+ return std::string();
+}
+
+const net::BackoffEntry* FakeProfileOAuth2TokenServiceDelegate::BackoffEntry()
+ const {
+ return &backoff_entry_;
+}
+
+std::vector<CoreAccountId> FakeProfileOAuth2TokenServiceDelegate::GetAccounts()
+ const {
+ std::vector<CoreAccountId> account_ids;
+ for (const auto& token : refresh_tokens_)
+ account_ids.push_back(token.first);
+ return account_ids;
+}
+
+void FakeProfileOAuth2TokenServiceDelegate::RevokeAllCredentials() {
+ std::vector<CoreAccountId> account_ids = GetAccounts();
+ for (const auto& account : account_ids)
+ RevokeCredentials(account);
+}
+
+void FakeProfileOAuth2TokenServiceDelegate::LoadCredentials(
+ const CoreAccountId& primary_account_id) {
+ set_load_credentials_state(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
+ FireRefreshTokensLoaded();
+}
+
+void FakeProfileOAuth2TokenServiceDelegate::UpdateCredentials(
+ const CoreAccountId& account_id,
+ const std::string& refresh_token) {
+ IssueRefreshTokenForUser(account_id, refresh_token);
+}
+
+void FakeProfileOAuth2TokenServiceDelegate::IssueRefreshTokenForUser(
+ const CoreAccountId& account_id,
+ const std::string& token) {
+ ScopedBatchChange batch(this);
+ if (token.empty()) {
+ refresh_tokens_.erase(account_id);
+ FireRefreshTokenRevoked(account_id);
+ } else {
+ refresh_tokens_[account_id].reset(new AccountInfo(token));
+ // If the token is a special "invalid" value, then that means the token was
+ // rejected by the client and is thus not valid. So set the appropriate
+ // error in that case. This logic is essentially duplicated from
+ // MutableProfileOAuth2TokenServiceDelegate.
+ if (token == GaiaConstants::kInvalidRefreshToken) {
+ refresh_tokens_[account_id]->error =
+ GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
+ GoogleServiceAuthError::InvalidGaiaCredentialsReason::
+ CREDENTIALS_REJECTED_BY_CLIENT);
+ }
+ FireRefreshTokenAvailable(account_id);
+ }
+}
+
+void FakeProfileOAuth2TokenServiceDelegate::RevokeCredentials(
+ const CoreAccountId& account_id) {
+ IssueRefreshTokenForUser(account_id, std::string());
+}
+
+void FakeProfileOAuth2TokenServiceDelegate::ExtractCredentials(
+ ProfileOAuth2TokenService* to_service,
+ const CoreAccountId& account_id) {
+ auto it = refresh_tokens_.find(account_id);
+ DCHECK(it != refresh_tokens_.end());
+ to_service->GetDelegate()->UpdateCredentials(account_id,
+ it->second->refresh_token);
+ RevokeCredentials(account_id);
+}
+
+scoped_refptr<network::SharedURLLoaderFactory>
+FakeProfileOAuth2TokenServiceDelegate::GetURLLoaderFactory() const {
+ return shared_factory_;
+}
+
+bool FakeProfileOAuth2TokenServiceDelegate::FixRequestErrorIfPossible() {
+ return fix_request_if_possible_;
+}
+
+void FakeProfileOAuth2TokenServiceDelegate::UpdateAuthError(
+ const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error) {
+ backoff_entry_.InformOfRequest(!error.IsTransientError());
+ // Drop transient errors to match OAuth2TokenService's stated contract for
+ // GetAuthError() and to allow clients to test proper behavior in the case of
+ // transient errors.
+ if (error.IsTransientError())
+ return;
+
+ if (GetAuthError(account_id) == error)
+ return;
+
+ auto it = refresh_tokens_.find(account_id);
+ DCHECK(it != refresh_tokens_.end());
+ it->second->error = error;
+ FireAuthErrorChanged(account_id, error);
+}
diff --git a/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.h b/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.h
new file mode 100644
index 00000000000..f47aa8ff5f2
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.h
@@ -0,0 +1,87 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
+
+namespace network {
+class SharedURLLoaderFactory;
+}
+
+class FakeProfileOAuth2TokenServiceDelegate
+ : public ProfileOAuth2TokenServiceDelegate {
+ public:
+ FakeProfileOAuth2TokenServiceDelegate();
+ ~FakeProfileOAuth2TokenServiceDelegate() override;
+
+ std::unique_ptr<OAuth2AccessTokenFetcher> CreateAccessTokenFetcher(
+ const CoreAccountId& account_id,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ OAuth2AccessTokenConsumer* consumer) override;
+
+ // Overriden to make sure it works on Android.
+ bool RefreshTokenIsAvailable(const CoreAccountId& account_id) const override;
+
+ GoogleServiceAuthError GetAuthError(
+ const CoreAccountId& account_id) const override;
+ void UpdateAuthError(const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error) override;
+ std::vector<CoreAccountId> GetAccounts() const override;
+ void RevokeAllCredentials() override;
+ void LoadCredentials(const CoreAccountId& primary_account_id) override;
+ void UpdateCredentials(const CoreAccountId& account_id,
+ const std::string& refresh_token) override;
+ void RevokeCredentials(const CoreAccountId& account_id) override;
+ void ExtractCredentials(ProfileOAuth2TokenService* to_service,
+ const CoreAccountId& account_id) override;
+
+ scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory()
+ const override;
+
+ bool FixRequestErrorIfPossible() override;
+
+ std::string GetRefreshToken(const CoreAccountId& account_id) const;
+
+ network::TestURLLoaderFactory* test_url_loader_factory() {
+ return &test_url_loader_factory_;
+ }
+
+ void set_fix_request_if_possible(bool value) {
+ fix_request_if_possible_ = value;
+ }
+
+ const net::BackoffEntry* BackoffEntry() const override;
+
+ private:
+ struct AccountInfo {
+ AccountInfo(const std::string& refresh_token);
+
+ const std::string refresh_token;
+ GoogleServiceAuthError error;
+ };
+
+ void IssueRefreshTokenForUser(const CoreAccountId& account_id,
+ const std::string& token);
+
+ // Maps account ids to info.
+ std::map<CoreAccountId, std::unique_ptr<AccountInfo>> refresh_tokens_;
+
+ network::TestURLLoaderFactory test_url_loader_factory_;
+ scoped_refptr<network::SharedURLLoaderFactory> shared_factory_;
+ bool fix_request_if_possible_ = false;
+
+ net::BackoffEntry backoff_entry_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeProfileOAuth2TokenServiceDelegate);
+};
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_
diff --git a/chromium/components/signin/core/browser/gaia_cookie_manager_service.cc b/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc
index 7f95e128b2f..6cddb7a2071 100644
--- a/chromium/components/signin/core/browser/gaia_cookie_manager_service.cc
+++ b/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/gaia_cookie_manager_service.h"
+#include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h"
#include <stddef.h>
@@ -22,13 +22,13 @@
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/set_accounts_in_cookie_result.h"
-#include "components/signin/core/browser/signin_metrics.h"
-#include "components/signin/core/browser/ubertoken_fetcher_impl.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/oauth_multilogin_helper.h"
+#include "components/signin/internal/identity_manager/ubertoken_fetcher_impl.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h"
#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/gaia_urls.h"
-#include "google_apis/gaia/oauth2_token_service.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/cookies/cookie_change_dispatcher.h"
@@ -38,33 +38,11 @@
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
-#if defined(OS_CHROMEOS)
-#include "chromeos/constants/chromeos_switches.h"
-#endif
-
-namespace signin {
-MultiloginParameters::MultiloginParameters(
- const gaia::MultiloginMode mode,
- const std::vector<std::string>& accounts_to_send)
- : mode(mode), accounts_to_send(accounts_to_send) {}
-
-MultiloginParameters::~MultiloginParameters() {}
-
-MultiloginParameters::MultiloginParameters(const MultiloginParameters& other) {
- mode = other.mode;
- accounts_to_send = other.accounts_to_send;
-}
-
-MultiloginParameters& MultiloginParameters::operator=(
- const MultiloginParameters& other) {
- mode = other.mode;
- accounts_to_send = other.accounts_to_send;
- return *this;
-}
-} // namespace signin
-
namespace {
+// The maximum number of retries for a fetcher used in this class.
+constexpr int kMaxFetcherRetries = 8;
+
// In case of an error while fetching using the GaiaAuthFetcher or
// SimpleURLLoader, retry with exponential backoff. Try up to 7 times within 15
// minutes.
@@ -145,27 +123,26 @@ void RecordListAccountsRetryResult(GoogleServiceAuthError error,
GaiaCookieManagerService::GaiaCookieRequest::GaiaCookieRequest(
GaiaCookieRequestType request_type,
- const std::vector<std::string>& account_ids,
gaia::GaiaSource source)
- : request_type_(request_type), account_ids_(account_ids), source_(source) {}
+ : request_type_(request_type), source_(source) {}
GaiaCookieManagerService::GaiaCookieRequest::GaiaCookieRequest(
GaiaCookieRequestType request_type,
- const std::vector<std::string>& account_ids,
+ const std::vector<AccountIdGaiaIdPair>& accounts,
gaia::GaiaSource source,
SetAccountsInCookieCompletedCallback callback)
: request_type_(request_type),
- account_ids_(account_ids),
+ accounts_(accounts),
source_(source),
set_accounts_in_cookie_completed_callback_(std::move(callback)) {}
GaiaCookieManagerService::GaiaCookieRequest::GaiaCookieRequest(
GaiaCookieRequestType request_type,
- const std::vector<std::string>& account_ids,
+ const CoreAccountId& account_id,
gaia::GaiaSource source,
AddAccountToCookieCompletedCallback callback)
: request_type_(request_type),
- account_ids_(account_ids),
+ account_id_(account_id),
source_(source),
add_account_to_cookie_completed_callback_(std::move(callback)) {}
@@ -178,10 +155,16 @@ GaiaCookieManagerService::GaiaCookieRequest&
GaiaCookieManagerService::GaiaCookieRequest::operator=(GaiaCookieRequest&&) =
default;
-const std::string GaiaCookieManagerService::GaiaCookieRequest::GetAccountID() {
+const CoreAccountId
+GaiaCookieManagerService::GaiaCookieRequest::GetAccountID() {
DCHECK_EQ(request_type_, GaiaCookieRequestType::ADD_ACCOUNT);
- DCHECK_EQ(1u, account_ids_.size());
- return account_ids_[0];
+ DCHECK_EQ(0u, accounts_.size());
+ return account_id_;
+}
+
+void GaiaCookieManagerService::GaiaCookieRequest::SetSourceSuffix(
+ std::string suffix) {
+ source_.SetGaiaSourceSuffix(suffix);
}
void GaiaCookieManagerService::GaiaCookieRequest::
@@ -193,7 +176,7 @@ void GaiaCookieManagerService::GaiaCookieRequest::
void GaiaCookieManagerService::GaiaCookieRequest::
RunAddAccountToCookieCompletedCallback(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const GoogleServiceAuthError& error) {
if (add_account_to_cookie_completed_callback_)
std::move(add_account_to_cookie_completed_callback_).Run(account_id, error);
@@ -202,22 +185,22 @@ void GaiaCookieManagerService::GaiaCookieRequest::
// static
GaiaCookieManagerService::GaiaCookieRequest
GaiaCookieManagerService::GaiaCookieRequest::CreateAddAccountRequest(
- const std::string& account_id,
+ const CoreAccountId& account_id,
gaia::GaiaSource source,
AddAccountToCookieCompletedCallback callback) {
return GaiaCookieManagerService::GaiaCookieRequest(
- GaiaCookieRequestType::ADD_ACCOUNT, {account_id}, source,
+ GaiaCookieRequestType::ADD_ACCOUNT, account_id, source,
std::move(callback));
}
// static
GaiaCookieManagerService::GaiaCookieRequest
GaiaCookieManagerService::GaiaCookieRequest::CreateSetAccountsRequest(
- const std::vector<std::string>& account_ids,
+ const std::vector<AccountIdGaiaIdPair>& accounts,
gaia::GaiaSource source,
SetAccountsInCookieCompletedCallback callback) {
return GaiaCookieManagerService::GaiaCookieRequest(
- GaiaCookieRequestType::SET_ACCOUNTS, account_ids, source,
+ GaiaCookieRequestType::SET_ACCOUNTS, accounts, source,
std::move(callback));
}
@@ -226,14 +209,14 @@ GaiaCookieManagerService::GaiaCookieRequest
GaiaCookieManagerService::GaiaCookieRequest::CreateLogOutRequest(
gaia::GaiaSource source) {
return GaiaCookieManagerService::GaiaCookieRequest(
- GaiaCookieRequestType::LOG_OUT, {}, source);
+ GaiaCookieRequestType::LOG_OUT, source);
}
// static
GaiaCookieManagerService::GaiaCookieRequest
GaiaCookieManagerService::GaiaCookieRequest::CreateListAccountsRequest() {
return GaiaCookieManagerService::GaiaCookieRequest(
- GaiaCookieRequestType::LIST_ACCOUNTS, {}, gaia::GaiaSource::kChrome);
+ GaiaCookieRequestType::LIST_ACCOUNTS, gaia::GaiaSource::kChrome);
}
GaiaCookieManagerService::ExternalCcResultFetcher::ExternalCcResultFetcher(
@@ -451,17 +434,17 @@ void GaiaCookieManagerService::ExternalCcResultFetcher::
}
GaiaCookieManagerService::GaiaCookieManagerService(
- OAuth2TokenService* token_service,
+ ProfileOAuth2TokenService* token_service,
SigninClient* signin_client)
: token_service_(token_service),
signin_client_(signin_client),
external_cc_result_fetcher_(this),
fetcher_backoff_(&kBackoffPolicy),
fetcher_retries_(0),
+ listAccountsUnexpectedServerResponseRetried_(false),
cookie_listener_binding_(this),
external_cc_result_fetched_(false),
- list_accounts_stale_(true),
- weak_ptr_factory_(this) {}
+ list_accounts_stale_(true) {}
GaiaCookieManagerService::~GaiaCookieManagerService() {
CancelAll();
@@ -493,15 +476,17 @@ void GaiaCookieManagerService::Shutdown() {
}
void GaiaCookieManagerService::SetAccountsInCookie(
- const std::vector<std::string>& account_ids,
+ const std::vector<AccountIdGaiaIdPair>& accounts,
gaia::GaiaSource source,
SetAccountsInCookieCompletedCallback
set_accounts_in_cookies_completed_callback) {
+ std::vector<std::string> account_ids;
+ for (const auto& id : accounts)
+ account_ids.push_back(id.first.id);
VLOG(1) << "GaiaCookieManagerService::SetAccountsInCookie: "
<< base::JoinString(account_ids, " ");
requests_.push_back(GaiaCookieRequest::CreateSetAccountsRequest(
- account_ids, source,
- std::move(set_accounts_in_cookies_completed_callback)));
+ accounts, source, std::move(set_accounts_in_cookies_completed_callback)));
if (!signin_client_->AreSigninCookiesAllowed()) {
OnSetAccountsFinished(signin::SetAccountsInCookieResult::kPersistentError);
return;
@@ -513,7 +498,7 @@ void GaiaCookieManagerService::SetAccountsInCookie(
}
void GaiaCookieManagerService::AddAccountToCookieInternal(
- const std::string& account_id,
+ const CoreAccountId& account_id,
gaia::GaiaSource source,
AddAccountToCookieCompletedCallback completion_callback) {
DCHECK(!account_id.empty());
@@ -535,7 +520,7 @@ void GaiaCookieManagerService::AddAccountToCookieInternal(
}
void GaiaCookieManagerService::AddAccountToCookie(
- const std::string& account_id,
+ const CoreAccountId& account_id,
gaia::GaiaSource source,
AddAccountToCookieCompletedCallback completion_callback) {
VLOG(1) << "GaiaCookieManagerService::AddAccountToCookie: " << account_id;
@@ -545,7 +530,7 @@ void GaiaCookieManagerService::AddAccountToCookie(
}
void GaiaCookieManagerService::AddAccountToCookieWithToken(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& access_token,
gaia::GaiaSource source,
AddAccountToCookieCompletedCallback completion_callback) {
@@ -579,6 +564,7 @@ bool GaiaCookieManagerService::ListAccounts(
void GaiaCookieManagerService::TriggerListAccounts() {
if (requests_.empty()) {
fetcher_retries_ = 0;
+ listAccountsUnexpectedServerResponseRetried_ = false;
requests_.push_back(GaiaCookieRequest::CreateListAccountsRequest());
signin_client_->DelayNetworkCall(
base::BindOnce(&GaiaCookieManagerService::StartFetchingListAccounts,
@@ -651,14 +637,6 @@ void GaiaCookieManagerService::LogOutAllAccounts(gaia::GaiaSource source) {
}
}
-void GaiaCookieManagerService::AddObserver(Observer* observer) {
- observer_list_.AddObserver(observer);
-}
-
-void GaiaCookieManagerService::RemoveObserver(Observer* observer) {
- observer_list_.RemoveObserver(observer);
-}
-
void GaiaCookieManagerService::CancelAll() {
VLOG(1) << "GaiaCookieManagerService::CancelAll";
gaia_auth_fetcher_.reset();
@@ -692,8 +670,8 @@ void GaiaCookieManagerService::OnCookieChange(
if (cause == network::mojom::CookieChangeCause::EXPLICIT) {
DCHECK(net::CookieChangeCauseIsDeletion(net::CookieChangeCause::EXPLICIT));
- for (auto& observer : observer_list_) {
- observer.OnGaiaCookieDeletedByUserAction();
+ if (gaia_cookie_deleted_by_user_action_callback_) {
+ gaia_cookie_deleted_by_user_action_callback_.Run();
}
}
@@ -705,6 +683,7 @@ void GaiaCookieManagerService::OnCookieChange(
if (requests_.empty()) {
requests_.push_back(GaiaCookieRequest::CreateListAccountsRequest());
fetcher_retries_ = 0;
+ listAccountsUnexpectedServerResponseRetried_ = false;
signin_client_->DelayNetworkCall(
base::BindOnce(&GaiaCookieManagerService::StartFetchingListAccounts,
weak_ptr_factory_.GetWeakPtr()));
@@ -741,12 +720,24 @@ void GaiaCookieManagerService::SignalSetAccountsComplete(
requests_.front().RunSetAccountsInCookieCompletedCallback(result);
}
+void GaiaCookieManagerService::SetGaiaAccountsInCookieUpdatedCallback(
+ GaiaAccountsInCookieUpdatedCallback callback) {
+ DCHECK(!gaia_accounts_updated_in_cookie_callback_);
+ gaia_accounts_updated_in_cookie_callback_ = std::move(callback);
+}
+
+void GaiaCookieManagerService::SetGaiaCookieDeletedByUserActionCallback(
+ GaiaCookieDeletedByUserActionCallback callback) {
+ DCHECK(!gaia_cookie_deleted_by_user_action_callback_);
+ gaia_cookie_deleted_by_user_action_callback_ = std::move(callback);
+}
+
void GaiaCookieManagerService::OnUbertokenFetchComplete(
GoogleServiceAuthError error,
const std::string& uber_token) {
if (error != GoogleServiceAuthError::AuthErrorNone()) {
// Note that the UberToken fetcher already retries transient errors.
- const std::string account_id = requests_.front().GetAccountID();
+ const CoreAccountId account_id = requests_.front().GetAccountID();
VLOG(1) << "Failed to retrieve ubertoken"
<< " account=" << account_id << " error=" << error.ToString();
SignalAddToCookieComplete(requests_.begin(), error);
@@ -775,7 +766,7 @@ void GaiaCookieManagerService::OnUbertokenFetchComplete(
}
void GaiaCookieManagerService::OnMergeSessionSuccess(const std::string& data) {
- const std::string account_id = requests_.front().GetAccountID();
+ const CoreAccountId account_id = requests_.front().GetAccountID();
VLOG(1) << "MergeSession successful account=" << account_id;
DCHECK(requests_.front().request_type() ==
GaiaCookieRequestType::ADD_ACCOUNT);
@@ -793,11 +784,10 @@ void GaiaCookieManagerService::OnMergeSessionFailure(
const GoogleServiceAuthError& error) {
DCHECK(requests_.front().request_type() ==
GaiaCookieRequestType::ADD_ACCOUNT);
- const std::string account_id = requests_.front().GetAccountID();
+ const CoreAccountId account_id = requests_.front().GetAccountID();
VLOG(1) << "Failed MergeSession"
<< " account=" << account_id << " error=" << error.ToString();
- if (++fetcher_retries_ < signin::kMaxFetcherRetries &&
- error.IsTransientError()) {
+ if (++fetcher_retries_ < kMaxFetcherRetries && error.IsTransientError()) {
fetcher_backoff_.InformOfRequest(false);
UMA_HISTOGRAM_ENUMERATION("OAuth2Login.MergeSessionRetry", error.state(),
GoogleServiceAuthError::NUM_STATES);
@@ -830,7 +820,6 @@ void GaiaCookieManagerService::OnListAccountsSuccess(const std::string& data) {
signed_out_accounts_.clear();
GoogleServiceAuthError error(
GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE);
- RecordListAccountsFailure(error.state());
OnListAccountsFailure(error);
return;
}
@@ -851,8 +840,8 @@ void GaiaCookieManagerService::OnListAccountsSuccess(const std::string& data) {
// services, in response to OnGaiaAccountsInCookieUpdated, may try in return
// to call ListAccounts, which would immediately return false if the
// ListAccounts request is still sitting in queue.
- for (auto& observer : observer_list_) {
- observer.OnGaiaAccountsInCookieUpdated(
+ if (gaia_accounts_updated_in_cookie_callback_) {
+ gaia_accounts_updated_in_cookie_callback_.Run(
listed_accounts_, signed_out_accounts_,
GoogleServiceAuthError(GoogleServiceAuthError::NONE));
}
@@ -865,8 +854,16 @@ void GaiaCookieManagerService::OnListAccountsFailure(
GaiaCookieRequestType::LIST_ACCOUNTS);
RecordListAccountsRetryResult(error, fetcher_retries_);
- if (++fetcher_retries_ < signin::kMaxFetcherRetries &&
- error.IsTransientError()) {
+ bool should_retry =
+ (++fetcher_retries_ < kMaxFetcherRetries && error.IsTransientError()) ||
+ (!listAccountsUnexpectedServerResponseRetried_ &&
+ error.state() == GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE);
+ if (should_retry) {
+ if (error.state() == GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE) {
+ listAccountsUnexpectedServerResponseRetried_ = true;
+ requests_.front().SetSourceSuffix(
+ GaiaConstants::kUnexpectedServiceResponse);
+ }
fetcher_backoff_.InformOfRequest(false);
UMA_HISTOGRAM_ENUMERATION("Signin.ListAccountsRetry", error.state(),
GoogleServiceAuthError::NUM_STATES);
@@ -880,10 +877,12 @@ void GaiaCookieManagerService::OnListAccountsFailure(
}
RecordListAccountsFailure(error.state());
- for (auto& observer : observer_list_) {
- observer.OnGaiaAccountsInCookieUpdated(listed_accounts_,
- signed_out_accounts_, error);
+
+ if (gaia_accounts_updated_in_cookie_callback_) {
+ gaia_accounts_updated_in_cookie_callback_.Run(listed_accounts_,
+ signed_out_accounts_, error);
}
+
HandleNextRequest();
}
@@ -903,7 +902,7 @@ void GaiaCookieManagerService::OnLogOutFailure(
VLOG(1) << "GaiaCookieManagerService::OnLogOutFailure";
RecordLogoutRequestState(LogoutRequestState::kFailed);
- if (++fetcher_retries_ < signin::kMaxFetcherRetries) {
+ if (++fetcher_retries_ < kMaxFetcherRetries) {
fetcher_backoff_.InformOfRequest(false);
fetcher_timer_.Start(
FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(),
@@ -918,7 +917,7 @@ void GaiaCookieManagerService::OnLogOutFailure(
}
void GaiaCookieManagerService::StartFetchingUbertoken() {
- const std::string account_id = requests_.front().GetAccountID();
+ const CoreAccountId account_id = requests_.front().GetAccountID();
VLOG(1) << "GaiaCookieManagerService::StartFetchingUbertoken account_id="
<< requests_.front().GetAccountID();
uber_token_fetcher_ = std::make_unique<signin::UbertokenFetcherImpl>(
@@ -956,17 +955,7 @@ void GaiaCookieManagerService::StartFetchingLogOut() {
RecordLogoutRequestState(LogoutRequestState::kStarted);
gaia_auth_fetcher_ =
signin_client_->CreateGaiaAuthFetcher(this, requests_.front().source());
- bool use_continue_url = false;
-#if defined(OS_ANDROID)
- use_continue_url = base::FeatureList::IsEnabled(signin::kMiceFeature);
-#elif defined(OS_CHROMEOS)
- use_continue_url = chromeos::switches::IsAccountManagerEnabled();
-#endif
- if (use_continue_url) {
- gaia_auth_fetcher_->StartLogOutWithBlankContinueURL();
- } else {
- gaia_auth_fetcher_->StartLogOut();
- }
+ gaia_auth_fetcher_->StartLogOut();
}
void GaiaCookieManagerService::StartFetchingListAccounts() {
@@ -980,7 +969,7 @@ void GaiaCookieManagerService::StartSetAccounts() {
DCHECK(!requests_.empty());
DCHECK_EQ(GaiaCookieRequestType::SET_ACCOUNTS,
requests_.front().request_type());
- DCHECK(!requests_.front().account_ids().empty());
+ DCHECK(!requests_.front().accounts().empty());
if (!external_cc_result_fetched_ &&
!external_cc_result_fetcher_.IsRunning()) {
@@ -991,7 +980,7 @@ void GaiaCookieManagerService::StartSetAccounts() {
}
oauth_multilogin_helper_ = std::make_unique<signin::OAuthMultiloginHelper>(
- signin_client_, token_service_, requests_.front().account_ids(),
+ signin_client_, token_service_, requests_.front().accounts(),
external_cc_result_fetcher_.GetExternalCcResult(),
base::BindOnce(&GaiaCookieManagerService::OnSetAccountsFinished,
weak_ptr_factory_.GetWeakPtr()));
@@ -1027,22 +1016,24 @@ void GaiaCookieManagerService::HandleNextRequest() {
} else {
switch (requests_.front().request_type()) {
case GaiaCookieRequestType::ADD_ACCOUNT:
- DCHECK_EQ(1u, requests_.front().account_ids().size());
+ DCHECK_EQ(0u, requests_.front().accounts().size());
signin_client_->DelayNetworkCall(
base::BindOnce(&GaiaCookieManagerService::StartFetchingUbertoken,
weak_ptr_factory_.GetWeakPtr()));
break;
- case GaiaCookieRequestType::SET_ACCOUNTS:
+ case GaiaCookieRequestType::SET_ACCOUNTS: {
StartSetAccounts();
break;
+ }
case GaiaCookieRequestType::LOG_OUT:
- DCHECK(requests_.front().account_ids().empty());
+ DCHECK(requests_.front().accounts().empty());
signin_client_->DelayNetworkCall(
base::BindOnce(&GaiaCookieManagerService::StartGaiaLogOut,
weak_ptr_factory_.GetWeakPtr()));
break;
case GaiaCookieRequestType::LIST_ACCOUNTS:
- DCHECK(requests_.front().account_ids().empty());
+ listAccountsUnexpectedServerResponseRetried_ = false;
+ DCHECK(requests_.front().accounts().empty());
uber_token_fetcher_.reset();
signin_client_->DelayNetworkCall(
base::BindOnce(&GaiaCookieManagerService::StartFetchingListAccounts,
diff --git a/chromium/components/signin/core/browser/gaia_cookie_manager_service.h b/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.h
index 94901f4e0a5..7886970f94d 100644
--- a/chromium/components/signin/core/browser/gaia_cookie_manager_service.h
+++ b/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_GAIA_COOKIE_MANAGER_SERVICE_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_GAIA_COOKIE_MANAGER_SERVICE_H_
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_GAIA_COOKIE_MANAGER_SERVICE_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_GAIA_COOKIE_MANAGER_SERVICE_H_
#include <map>
#include <memory>
@@ -18,12 +18,11 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/timer/timer.h"
-#include "components/signin/core/browser/oauth_multilogin_helper.h"
-#include "components/signin/core/browser/signin_client.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/public/base/signin_client.h"
#include "google_apis/gaia/gaia_auth_consumer.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
#include "google_apis/gaia/gaia_auth_util.h"
-#include "google_apis/gaia/oauth2_token_service.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/base/backoff_entry.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
@@ -39,27 +38,10 @@ class SimpleURLLoader;
namespace signin {
+class OAuthMultiloginHelper;
class UbertokenFetcherImpl;
enum class SetAccountsInCookieResult;
-// The maximum number of retries for a fetcher used in this class.
-constexpr int kMaxFetcherRetries = 8;
-
-struct MultiloginParameters {
- MultiloginParameters(gaia::MultiloginMode mode,
- const std::vector<std::string>& accounts_to_send);
- MultiloginParameters(const MultiloginParameters& other);
- MultiloginParameters& operator=(const MultiloginParameters& other);
- ~MultiloginParameters();
-
- // Needed for testing.
- bool operator==(const MultiloginParameters& other) const {
- return mode == other.mode && accounts_to_send == other.accounts_to_send;
- }
-
- gaia::MultiloginMode mode;
- std::vector<std::string> accounts_to_send;
-};
} // namespace signin
// Merges a Google account known to Chrome into the cookie jar. When merging
@@ -73,6 +55,8 @@ struct MultiloginParameters {
class GaiaCookieManagerService : public GaiaAuthConsumer,
public network::mojom::CookieChangeListener {
public:
+ using AccountIdGaiaIdPair = std::pair<CoreAccountId, std::string>;
+
enum GaiaCookieRequestType {
ADD_ACCOUNT,
LOG_OUT,
@@ -82,10 +66,16 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
typedef base::OnceCallback<void(signin::SetAccountsInCookieResult)>
SetAccountsInCookieCompletedCallback;
- typedef base::OnceCallback<void(const std::string&,
+ typedef base::OnceCallback<void(const CoreAccountId&,
const GoogleServiceAuthError&)>
AddAccountToCookieCompletedCallback;
+ typedef base::RepeatingCallback<void(const std::vector<gaia::ListedAccount>&,
+ const std::vector<gaia::ListedAccount>&,
+ const GoogleServiceAuthError&)>
+ GaiaAccountsInCookieUpdatedCallback;
+ typedef base::RepeatingCallback<void()> GaiaCookieDeletedByUserActionCallback;
+
// Contains the information and parameters for any request.
class GaiaCookieRequest {
public:
@@ -94,45 +84,50 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
GaiaCookieRequest& operator=(GaiaCookieRequest&&);
GaiaCookieRequestType request_type() const { return request_type_; }
- const std::vector<std::string>& account_ids() const { return account_ids_; }
+ const std::vector<AccountIdGaiaIdPair>& accounts() const {
+ return accounts_;
+ }
// For use in the Request of type ADD_ACCOUNT which must have exactly one
- // account_id in the array. It checks this condition and extracts this one
- // account.
- const std::string GetAccountID();
+ // account_id.
+ const CoreAccountId GetAccountID();
gaia::GaiaSource source() const { return source_; }
+ // Sets GaiaSource suffix.
+ void SetSourceSuffix(std::string suffix);
void RunSetAccountsInCookieCompletedCallback(
signin::SetAccountsInCookieResult result);
void RunAddAccountToCookieCompletedCallback(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const GoogleServiceAuthError& error);
static GaiaCookieRequest CreateAddAccountRequest(
- const std::string& account_id,
+ const CoreAccountId& account_id,
gaia::GaiaSource source,
AddAccountToCookieCompletedCallback callback);
static GaiaCookieRequest CreateLogOutRequest(gaia::GaiaSource source);
static GaiaCookieRequest CreateListAccountsRequest();
static GaiaCookieRequest CreateSetAccountsRequest(
- const std::vector<std::string>& account_ids,
+ const std::vector<AccountIdGaiaIdPair>& account_ids,
gaia::GaiaSource source,
SetAccountsInCookieCompletedCallback callback);
private:
GaiaCookieRequest(GaiaCookieRequestType request_type,
- const std::vector<std::string>& account_ids,
gaia::GaiaSource source);
GaiaCookieRequest(GaiaCookieRequestType request_type,
- const std::vector<std::string>& account_ids,
+ const std::vector<AccountIdGaiaIdPair>& accounts,
gaia::GaiaSource source,
SetAccountsInCookieCompletedCallback callback);
GaiaCookieRequest(GaiaCookieRequestType request_type,
- const std::vector<std::string>& account_ids,
+ const CoreAccountId& account_id,
gaia::GaiaSource source,
AddAccountToCookieCompletedCallback callback);
GaiaCookieRequestType request_type_;
- std::vector<std::string> account_ids_;
+ // For use in the request of type ADD_ACCOUNT.
+ CoreAccountId account_id_;
+ // For use in the request of type SET_ACCOUNT.
+ std::vector<AccountIdGaiaIdPair> accounts_;
gaia::GaiaSource source_;
SetAccountsInCookieCompletedCallback
@@ -143,28 +138,6 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
DISALLOW_COPY_AND_ASSIGN(GaiaCookieRequest);
};
- class Observer {
- public:
- // Called whenever the GaiaCookieManagerService's list of GAIA accounts is
- // updated. The GCMS monitors the APISID cookie and triggers a /ListAccounts
- // call on change. The GCMS will also call ListAccounts upon the first call
- // to ListAccounts(). The GCMS will delay calling ListAccounts if other
- // requests are in queue that would modify the APISID cookie.
- // If the ListAccounts call fails and the GCMS cannot recover, the reason
- // is passed in |error|.
- virtual void OnGaiaAccountsInCookieUpdated(
- const std::vector<gaia::ListedAccount>& accounts,
- const std::vector<gaia::ListedAccount>& signed_out_accounts,
- const GoogleServiceAuthError& error) {}
-
- // Called when the Gaia cookie has been deleted explicitly by a user action,
- // e.g. from the settings or by an extension.
- virtual void OnGaiaCookieDeletedByUserAction() {}
-
- protected:
- virtual ~Observer() {}
- };
-
// Class to retrieve the external connection check results from gaia.
// Declared publicly for unit tests.
class ExternalCcResultFetcher : public GaiaAuthConsumer {
@@ -226,7 +199,7 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
DISALLOW_COPY_AND_ASSIGN(ExternalCcResultFetcher);
};
- GaiaCookieManagerService(OAuth2TokenService* token_service,
+ GaiaCookieManagerService(ProfileOAuth2TokenService* token_service,
SigninClient* signin_client);
~GaiaCookieManagerService() override;
@@ -235,11 +208,11 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
void Shutdown();
void AddAccountToCookie(
- const std::string& account_id,
+ const CoreAccountId& account_id,
gaia::GaiaSource source,
AddAccountToCookieCompletedCallback completion_callback);
void AddAccountToCookieWithToken(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& access_token,
gaia::GaiaSource source,
AddAccountToCookieCompletedCallback completion_callback);
@@ -247,7 +220,7 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
// Takes list of account_ids and sets the cookie for these accounts regardless
// of the current cookie state. Removes the accounts that are not in
// account_ids and add the missing ones.
- void SetAccountsInCookie(const std::vector<std::string>& account_ids,
+ void SetAccountsInCookie(const std::vector<AccountIdGaiaIdPair>& account_ids,
gaia::GaiaSource source,
SetAccountsInCookieCompletedCallback
set_accounts_in_cookies_completed_callback);
@@ -270,10 +243,6 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
// service. Virtual for testing.
virtual void ForceOnCookieChangeProcessing();
- // Add or remove observers of this helper.
- void AddObserver(Observer* observer);
- void RemoveObserver(Observer* observer);
-
// Cancel all login requests.
void CancelAll();
@@ -295,7 +264,26 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
list_accounts_stale_ = stale;
}
- // Returns a non-NULL pointer to its instance of net::BackoffEntry
+ // If set, this callback will be invoked whenever the
+ // GaiaCookieManagerService's list of GAIA accounts is updated. The GCMS
+ // monitors the APISID cookie and triggers a /ListAccounts call on change.
+ // The GCMS will also call ListAccounts upon the first call to
+ // ListAccounts(). The GCMS will delay calling ListAccounts if other
+ // requests are in queue that would modify the APISID cookie.
+ // If the ListAccounts call fails and the GCMS cannot recover, the reason
+ // is passed in |error|.
+ // This method can only be called once.
+ void SetGaiaAccountsInCookieUpdatedCallback(
+ GaiaAccountsInCookieUpdatedCallback callback);
+
+ // If set, this callback will be invoked whenever the Gaia cookie has
+ // been deleted explicitly by a user action, e.g. from the settings or by an
+ // extension.
+ // This method can only be called once.
+ void SetGaiaCookieDeletedByUserActionCallback(
+ GaiaCookieDeletedByUserActionCallback callback);
+
+ // Returns a non-null pointer to its instance of net::BackoffEntry
const net::BackoffEntry* GetBackoffEntry() { return &fetcher_backoff_; }
// Ubertoken fetch completion callback. Called by unittests directly.
@@ -334,7 +322,7 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
// Helper method for AddAccountToCookie* methods.
void AddAccountToCookieInternal(
- const std::string& account_id,
+ const CoreAccountId& account_id,
gaia::GaiaSource source,
AddAccountToCookieCompletedCallback completion_callback);
@@ -361,9 +349,13 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
// Start the next request, if needed.
void HandleNextRequest();
- OAuth2TokenService* token_service_;
+ ProfileOAuth2TokenService* token_service_;
SigninClient* signin_client_;
+ GaiaAccountsInCookieUpdatedCallback gaia_accounts_updated_in_cookie_callback_;
+ GaiaCookieDeletedByUserActionCallback
+ gaia_cookie_deleted_by_user_action_callback_;
+
std::unique_ptr<GaiaAuthFetcher> gaia_auth_fetcher_;
std::unique_ptr<signin::UbertokenFetcherImpl> uber_token_fetcher_;
ExternalCcResultFetcher external_cc_result_fetcher_;
@@ -375,6 +367,10 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
base::OneShotTimer fetcher_timer_;
int fetcher_retries_;
+ // If list accounts retried after a failure because of getting an unexpected
+ // service response.
+ bool listAccountsUnexpectedServerResponseRetried_;
+
// The last fetched ubertoken, for use in MergeSession retries.
std::string uber_token_;
@@ -389,10 +385,6 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
// executed at a time.
base::circular_deque<GaiaCookieRequest> requests_;
- // List of observers to notify when merge session completes.
- // Makes sure list is empty on destruction.
- base::ObserverList<Observer, true>::Unchecked observer_list_;
-
// True once the ExternalCCResultFetcher has completed once.
bool external_cc_result_fetched_;
@@ -401,9 +393,9 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
bool list_accounts_stale_;
- base::WeakPtrFactory<GaiaCookieManagerService> weak_ptr_factory_;
+ base::WeakPtrFactory<GaiaCookieManagerService> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(GaiaCookieManagerService);
};
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_GAIA_COOKIE_MANAGER_SERVICE_H_
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_GAIA_COOKIE_MANAGER_SERVICE_H_
diff --git a/chromium/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc b/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service_unittest.cc
index 85a5c442b00..492ee78b725 100644
--- a/chromium/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/gaia_cookie_manager_service.h"
+#include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h"
#include <algorithm>
#include <memory>
@@ -21,12 +21,11 @@
#include "base/test/scoped_task_environment.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "components/signin/core/browser/test_signin_client.h"
-#include "google_apis/gaia/fake_oauth2_token_service.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/base/test_signin_client.h"
#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/gaia_urls.h"
#include "services/network/test/test_url_loader_factory.h"
@@ -35,25 +34,26 @@
namespace {
+const char kAccountId1[] = "acc1@gmail.com";
+const char kAccountId2[] = "acc2@gmail.com";
+const char kAccountId3[] = "acc3@gmail.com";
+
using MockAddAccountToCookieCompletedCallback = base::MockCallback<
GaiaCookieManagerService::AddAccountToCookieCompletedCallback>;
-class MockObserver : public GaiaCookieManagerService::Observer {
+class MockObserver {
public:
- explicit MockObserver(GaiaCookieManagerService* helper) : helper_(helper) {
- helper_->AddObserver(this);
+ explicit MockObserver(GaiaCookieManagerService* helper) {
+ helper->SetGaiaAccountsInCookieUpdatedCallback(base::BindRepeating(
+ &MockObserver::OnGaiaAccountsInCookieUpdated, base::Unretained(this)));
}
- ~MockObserver() override { helper_->RemoveObserver(this); }
-
MOCK_METHOD3(OnGaiaAccountsInCookieUpdated,
void(const std::vector<gaia::ListedAccount>&,
const std::vector<gaia::ListedAccount>&,
const GoogleServiceAuthError&));
private:
- GaiaCookieManagerService* helper_;
-
DISALLOW_COPY_AND_ASSIGN(MockObserver);
};
@@ -94,7 +94,7 @@ MATCHER_P(ListedAccountEquals, expected, "") {
class InstrumentedGaiaCookieManagerService : public GaiaCookieManagerService {
public:
- InstrumentedGaiaCookieManagerService(OAuth2TokenService* token_service,
+ InstrumentedGaiaCookieManagerService(ProfileOAuth2TokenService* token_service,
SigninClient* signin_client)
: GaiaCookieManagerService(token_service, signin_client) {
total++;
@@ -114,14 +114,19 @@ class InstrumentedGaiaCookieManagerService : public GaiaCookieManagerService {
class GaiaCookieManagerServiceTest : public testing::Test {
public:
GaiaCookieManagerServiceTest()
- : no_error_(GoogleServiceAuthError::NONE),
+ : account_id1_(kAccountId1),
+ account_id2_(kAccountId2),
+ account_id3_(kAccountId3),
+ no_error_(GoogleServiceAuthError::NONE),
error_(GoogleServiceAuthError::SERVICE_ERROR),
canceled_(GoogleServiceAuthError::REQUEST_CANCELED) {
AccountTrackerService::RegisterPrefs(pref_service_.registry());
- signin_client_.reset(new TestSigninClient(&pref_service_));
+ signin_client_ = std::make_unique<TestSigninClient>(&pref_service_);
+ token_service_ =
+ std::make_unique<FakeProfileOAuth2TokenService>(&pref_service_);
}
- OAuth2TokenService* token_service() { return &token_service_; }
+ ProfileOAuth2TokenService* token_service() { return token_service_.get(); }
TestSigninClient* signin_client() { return signin_client_.get(); }
void SimulateUbertokenSuccess(GaiaCookieManagerService* gcms,
@@ -135,14 +140,14 @@ class GaiaCookieManagerServiceTest : public testing::Test {
gcms->OnUbertokenFetchComplete(error, /*uber_token=*/std::string());
}
- void SimulateAccessTokenFailure(OAuth2TokenService::Consumer* consumer,
- OAuth2TokenService::Request* request,
+ void SimulateAccessTokenFailure(OAuth2AccessTokenManager::Consumer* consumer,
+ OAuth2AccessTokenManager::Request* request,
const GoogleServiceAuthError& error) {
consumer->OnGetTokenFailure(request, error);
}
- void SimulateAccessTokenSuccess(OAuth2TokenService::Consumer* consumer,
- OAuth2TokenService::Request* request) {
+ void SimulateAccessTokenSuccess(OAuth2AccessTokenManager::Consumer* consumer,
+ OAuth2AccessTokenManager::Request* request) {
OAuth2AccessTokenConsumer::TokenResponse token_response =
OAuth2AccessTokenConsumer::TokenResponse("AccessToken", base::Time(),
"Idtoken");
@@ -217,14 +222,18 @@ class GaiaCookieManagerServiceTest : public testing::Test {
return signin_client_->GetURLLoaderFactory();
}
+ const CoreAccountId account_id1_;
+ const CoreAccountId account_id2_;
+ const CoreAccountId account_id3_;
+
private:
base::test::ScopedTaskEnvironment task_environment_;
- FakeOAuth2TokenService token_service_;
GoogleServiceAuthError no_error_;
GoogleServiceAuthError error_;
GoogleServiceAuthError canceled_;
TestingPrefServiceSimple pref_service_;
std::unique_ptr<TestSigninClient> signin_client_;
+ std::unique_ptr<FakeProfileOAuth2TokenService> token_service_;
};
} // namespace
@@ -238,10 +247,9 @@ TEST_F(GaiaCookieManagerServiceTest, Success) {
EXPECT_CALL(helper, StartFetchingUbertoken());
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed;
- EXPECT_CALL(add_account_to_cookie_completed,
- Run("acc1@gmail.com", no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed, Run(account_id1_, no_error()));
- helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed.Get());
SimulateMergeSessionSuccess(&helper, "token");
}
@@ -254,9 +262,9 @@ TEST_F(GaiaCookieManagerServiceTest, FailedMergeSession) {
EXPECT_CALL(helper, StartFetchingUbertoken());
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed;
- EXPECT_CALL(add_account_to_cookie_completed, Run("acc1@gmail.com", error()));
+ EXPECT_CALL(add_account_to_cookie_completed, Run(account_id1_, error()));
- helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed.Get());
SimulateMergeSessionFailure(&helper, error());
// Persistent error incurs no further retries.
@@ -271,10 +279,9 @@ TEST_F(GaiaCookieManagerServiceTest, AddAccountCookiesDisabled) {
signin_client()->set_are_signin_cookies_allowed(false);
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed;
- EXPECT_CALL(add_account_to_cookie_completed,
- Run("acc1@gmail.com", canceled()));
+ EXPECT_CALL(add_account_to_cookie_completed, Run(account_id1_, canceled()));
- helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed.Get());
}
@@ -290,10 +297,9 @@ TEST_F(GaiaCookieManagerServiceTest, MergeSessionRetried) {
EXPECT_CALL(helper, StartFetchingMergeSession());
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed;
- EXPECT_CALL(add_account_to_cookie_completed,
- Run("acc1@gmail.com", no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed, Run(account_id1_, no_error()));
- helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed.Get());
SimulateMergeSessionFailure(&helper, canceled());
DCHECK(helper.is_running());
@@ -315,10 +321,9 @@ TEST_F(GaiaCookieManagerServiceTest, MergeSessionRetriedTwice) {
EXPECT_CALL(helper, StartFetchingMergeSession()).Times(2);
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed;
- EXPECT_CALL(add_account_to_cookie_completed,
- Run("acc1@gmail.com", no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed, Run(account_id1_, no_error()));
- helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed.Get());
SimulateMergeSessionFailure(&helper, canceled());
DCHECK(helper.is_running());
@@ -339,9 +344,9 @@ TEST_F(GaiaCookieManagerServiceTest, FailedUbertoken) {
EXPECT_CALL(helper, StartFetchingUbertoken());
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed;
- EXPECT_CALL(add_account_to_cookie_completed, Run("acc1@gmail.com", error()));
+ EXPECT_CALL(add_account_to_cookie_completed, Run(account_id1_, error()));
- helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed.Get());
SimulateUbertokenFailure(&helper, error());
}
@@ -354,14 +359,12 @@ TEST_F(GaiaCookieManagerServiceTest, ContinueAfterSuccess) {
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed1,
add_account_to_cookie_completed2;
- EXPECT_CALL(add_account_to_cookie_completed1,
- Run("acc1@gmail.com", no_error()));
- EXPECT_CALL(add_account_to_cookie_completed2,
- Run("acc2@gmail.com", no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed1, Run(account_id1_, no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed2, Run(account_id2_, no_error()));
- helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed1.Get());
- helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id2_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed2.Get());
SimulateMergeSessionSuccess(&helper, "token1");
SimulateMergeSessionSuccess(&helper, "token2");
@@ -375,13 +378,12 @@ TEST_F(GaiaCookieManagerServiceTest, ContinueAfterFailure1) {
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed1,
add_account_to_cookie_completed2;
- EXPECT_CALL(add_account_to_cookie_completed1, Run("acc1@gmail.com", error()));
- EXPECT_CALL(add_account_to_cookie_completed2,
- Run("acc2@gmail.com", no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed1, Run(account_id1_, error()));
+ EXPECT_CALL(add_account_to_cookie_completed2, Run(account_id2_, no_error()));
- helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed1.Get());
- helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id2_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed2.Get());
SimulateMergeSessionFailure(&helper, error());
SimulateMergeSessionSuccess(&helper, "token2");
@@ -395,13 +397,12 @@ TEST_F(GaiaCookieManagerServiceTest, ContinueAfterFailure2) {
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed1,
add_account_to_cookie_completed2;
- EXPECT_CALL(add_account_to_cookie_completed1, Run("acc1@gmail.com", error()));
- EXPECT_CALL(add_account_to_cookie_completed2,
- Run("acc2@gmail.com", no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed1, Run(account_id1_, error()));
+ EXPECT_CALL(add_account_to_cookie_completed2, Run(account_id2_, no_error()));
- helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed1.Get());
- helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id2_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed2.Get());
SimulateUbertokenFailure(&helper, error());
SimulateMergeSessionSuccess(&helper, "token2");
@@ -416,14 +417,14 @@ TEST_F(GaiaCookieManagerServiceTest, AllRequestsInMultipleGoes) {
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed;
EXPECT_CALL(add_account_to_cookie_completed, Run(_, no_error())).Times(4);
- helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed.Get());
- helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id2_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed.Get());
SimulateMergeSessionSuccess(&helper, "token1");
- helper.AddAccountToCookie("acc3@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id3_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed.Get());
SimulateMergeSessionSuccess(&helper, "token2");
@@ -443,10 +444,9 @@ TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsNoQueue) {
EXPECT_CALL(helper, StartFetchingLogOut());
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed;
- EXPECT_CALL(add_account_to_cookie_completed,
- Run("acc2@gmail.com", no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed, Run(account_id2_, no_error()));
- helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id2_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed.Get());
SimulateMergeSessionSuccess(&helper, "token1");
@@ -463,10 +463,9 @@ TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsFails) {
EXPECT_CALL(helper, StartFetchingLogOut());
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed;
- EXPECT_CALL(add_account_to_cookie_completed,
- Run("acc2@gmail.com", no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed, Run(account_id2_, no_error()));
- helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id2_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed.Get());
SimulateMergeSessionSuccess(&helper, "token1");
@@ -484,10 +483,9 @@ TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsAfterOneAddInQueue) {
EXPECT_CALL(helper, StartFetchingLogOut());
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed;
- EXPECT_CALL(add_account_to_cookie_completed,
- Run("acc2@gmail.com", no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed, Run(account_id2_, no_error()));
- helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id2_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed.Get());
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
@@ -504,15 +502,13 @@ TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsAfterTwoAddsInQueue) {
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed1,
add_account_to_cookie_completed2;
- EXPECT_CALL(add_account_to_cookie_completed1,
- Run("acc1@gmail.com", no_error()));
- EXPECT_CALL(add_account_to_cookie_completed2,
- Run("acc2@gmail.com", canceled()));
+ EXPECT_CALL(add_account_to_cookie_completed1, Run(account_id1_, no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed2, Run(account_id2_, canceled()));
- helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed1.Get());
// The Log Out should prevent this AddAccount from being fetched.
- helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id2_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed2.Get());
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
@@ -528,10 +524,9 @@ TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsTwice) {
EXPECT_CALL(helper, StartFetchingLogOut());
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed;
- EXPECT_CALL(add_account_to_cookie_completed,
- Run("acc2@gmail.com", no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed, Run(account_id2_, no_error()));
- helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id2_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed.Get());
SimulateMergeSessionSuccess(&helper, "token1");
@@ -550,17 +545,15 @@ TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsBeforeAdd) {
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed2,
add_account_to_cookie_completed3;
- EXPECT_CALL(add_account_to_cookie_completed2,
- Run("acc2@gmail.com", no_error()));
- EXPECT_CALL(add_account_to_cookie_completed3,
- Run("acc3@gmail.com", no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed2, Run(account_id2_, no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed3, Run(account_id3_, no_error()));
- helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id2_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed2.Get());
SimulateMergeSessionSuccess(&helper, "token1");
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
- helper.AddAccountToCookie("acc3@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id3_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed3.Get());
SimulateLogOutSuccess(&helper);
@@ -577,19 +570,17 @@ TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsBeforeLogoutAndAdd) {
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed2,
add_account_to_cookie_completed3;
- EXPECT_CALL(add_account_to_cookie_completed2,
- Run("acc2@gmail.com", no_error()));
- EXPECT_CALL(add_account_to_cookie_completed3,
- Run("acc3@gmail.com", no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed2, Run(account_id2_, no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed3, Run(account_id3_, no_error()));
- helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id2_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed2.Get());
SimulateMergeSessionSuccess(&helper, "token1");
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
// Second LogOut will never be fetched.
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
- helper.AddAccountToCookie("acc3@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id3_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed3.Get());
SimulateLogOutSuccess(&helper);
@@ -603,27 +594,25 @@ TEST_F(GaiaCookieManagerServiceTest, PendingSigninThenSignout) {
// From the first Signin.
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed1;
- EXPECT_CALL(add_account_to_cookie_completed1,
- Run("acc1@gmail.com", no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed1, Run(account_id1_, no_error()));
// From the sign out and then re-sign in.
EXPECT_CALL(helper, StartFetchingLogOut());
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed3;
- EXPECT_CALL(add_account_to_cookie_completed3,
- Run("acc3@gmail.com", no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed3, Run(account_id3_, no_error()));
// Total sign in 2 times, not enforcing ordered sequences.
EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2);
- helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed1.Get());
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
SimulateMergeSessionSuccess(&helper, "token1");
SimulateLogOutSuccess(&helper);
- helper.AddAccountToCookie("acc3@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id3_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed3.Get());
SimulateMergeSessionSuccess(&helper, "token3");
}
@@ -635,15 +624,13 @@ TEST_F(GaiaCookieManagerServiceTest, CancelSignIn) {
EXPECT_CALL(helper, StartFetchingUbertoken());
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed1,
add_account_to_cookie_completed2;
- EXPECT_CALL(add_account_to_cookie_completed1,
- Run("acc1@gmail.com", no_error()));
- EXPECT_CALL(add_account_to_cookie_completed2,
- Run("acc2@gmail.com", canceled()));
+ EXPECT_CALL(add_account_to_cookie_completed1, Run(account_id1_, no_error()));
+ EXPECT_CALL(add_account_to_cookie_completed2, Run(account_id2_, canceled()));
EXPECT_CALL(helper, StartFetchingLogOut());
- helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed1.Get());
- helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome,
+ helper.AddAccountToCookie(account_id2_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed2.Get());
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
@@ -891,7 +878,7 @@ TEST_F(GaiaCookieManagerServiceTest, UbertokenSuccessFetchesExternalCC) {
EXPECT_CALL(helper, StartFetchingUbertoken());
helper.AddAccountToCookie(
- "acc1@gmail.com", gaia::GaiaSource::kChrome,
+ account_id1_, gaia::GaiaSource::kChrome,
GaiaCookieManagerService::AddAccountToCookieCompletedCallback());
ASSERT_FALSE(IsLoadPending());
@@ -917,7 +904,7 @@ TEST_F(GaiaCookieManagerServiceTest, UbertokenSuccessFetchesExternalCCOnce) {
EXPECT_CALL(helper, StartFetchingUbertoken());
helper.AddAccountToCookie(
- "acc2@gmail.com", gaia::GaiaSource::kChrome,
+ account_id2_, gaia::GaiaSource::kChrome,
GaiaCookieManagerService::AddAccountToCookieCompletedCallback());
// There is already a ExternalCCResultFetch underway. This will trigger
// StartFetchingMergeSession.
diff --git a/chromium/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate.cc b/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc
index b32db5def12..0364fbc2ce2 100644
--- a/chromium/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate.cc
+++ b/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/mutable_profile_oauth2_token_service_delegate.h"
+#include "components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.h"
#include <stddef.h>
@@ -16,11 +16,11 @@
#include "build/build_config.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/account_info.h"
-#include "components/signin/core/browser/signin_client.h"
-#include "components/signin/core/browser/signin_metrics.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "components/signin/core/browser/webdata/token_web_data.h"
+#include "components/signin/public/base/signin_client.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/identity_manager/account_info.h"
+#include "components/signin/public/webdata/token_web_data.h"
#include "components/webdata/common/web_data_service_base.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
#include "google_apis/gaia/gaia_auth_util.h"
@@ -112,15 +112,14 @@ void RecordTokenChanged(const std::string& existing_token,
DCHECK(!new_token.empty());
TokenStateTransition transition = TokenStateTransition::kCount;
if (existing_token.empty()) {
- transition = (new_token == OAuth2TokenServiceDelegate::kInvalidRefreshToken)
+ transition = (new_token == GaiaConstants::kInvalidRefreshToken)
? TokenStateTransition::kNoneToInvalid
: TokenStateTransition::kNoneToRegular;
- } else if (existing_token ==
- OAuth2TokenServiceDelegate::kInvalidRefreshToken) {
+ } else if (existing_token == GaiaConstants::kInvalidRefreshToken) {
transition = TokenStateTransition::kInvalidToRegular;
} else {
// Existing token is a regular token.
- transition = (new_token == OAuth2TokenServiceDelegate::kInvalidRefreshToken)
+ transition = (new_token == GaiaConstants::kInvalidRefreshToken)
? TokenStateTransition::kRegularToInvalid
: TokenStateTransition::kRegularToRegular;
}
@@ -130,18 +129,16 @@ void RecordTokenChanged(const std::string& existing_token,
// Record metrics when a token was loaded.
void RecordTokenLoaded(const std::string& token) {
- RecordTokenStateTransition(
- (token == OAuth2TokenServiceDelegate::kInvalidRefreshToken)
- ? TokenStateTransition::kLoadInvalid
- : TokenStateTransition::kLoadRegular);
+ RecordTokenStateTransition((token == GaiaConstants::kInvalidRefreshToken)
+ ? TokenStateTransition::kLoadInvalid
+ : TokenStateTransition::kLoadRegular);
}
// Record metrics when a token was revoked.
void RecordTokenRevoked(const std::string& token) {
- RecordTokenStateTransition(
- (token == OAuth2TokenServiceDelegate::kInvalidRefreshToken)
- ? TokenStateTransition::kInvalidToNone
- : TokenStateTransition::kRegularToNone);
+ RecordTokenStateTransition((token == GaiaConstants::kInvalidRefreshToken)
+ ? TokenStateTransition::kInvalidToNone
+ : TokenStateTransition::kRegularToNone);
}
std::string ApplyAccountIdPrefix(const std::string& account_id) {
@@ -156,25 +153,26 @@ bool IsLegacyServiceId(const std::string& account_id) {
return account_id.compare(0u, kAccountIdPrefixLength, kAccountIdPrefix) != 0;
}
-std::string RemoveAccountIdPrefix(const std::string& prefixed_account_id) {
- return prefixed_account_id.substr(kAccountIdPrefixLength);
+CoreAccountId RemoveAccountIdPrefix(const std::string& prefixed_account_id) {
+ return CoreAccountId(prefixed_account_id.substr(kAccountIdPrefixLength));
}
-OAuth2TokenServiceDelegate::LoadCredentialsState
-LoadCredentialsStateFromTokenResult(TokenServiceTable::Result token_result) {
+signin::LoadCredentialsState LoadCredentialsStateFromTokenResult(
+ TokenServiceTable::Result token_result) {
switch (token_result) {
case TokenServiceTable::TOKEN_DB_RESULT_SQL_INVALID_STATEMENT:
case TokenServiceTable::TOKEN_DB_RESULT_BAD_ENTRY:
- return OAuth2TokenServiceDelegate::
+ return signin::LoadCredentialsState::
LOAD_CREDENTIALS_FINISHED_WITH_DB_ERRORS;
case TokenServiceTable::TOKEN_DB_RESULT_DECRYPT_ERROR:
- return OAuth2TokenServiceDelegate::
+ return signin::LoadCredentialsState::
LOAD_CREDENTIALS_FINISHED_WITH_DECRYPT_ERRORS;
case TokenServiceTable::TOKEN_DB_RESULT_SUCCESS:
- return OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS;
+ return signin::LoadCredentialsState::
+ LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS;
}
NOTREACHED();
- return OAuth2TokenServiceDelegate::
+ return signin::LoadCredentialsState::
LOAD_CREDENTIALS_FINISHED_WITH_UNKNOWN_ERRORS;
}
@@ -203,7 +201,7 @@ bool ShouldMigrateToDice(signin::AccountConsistencyMethod account_consistency,
// Do not migrate if some accounts are not valid.
for (auto iter = db_tokens.begin(); iter != db_tokens.end(); ++iter) {
const std::string& prefixed_account_id = iter->first;
- std::string account_id = RemoveAccountIdPrefix(prefixed_account_id);
+ CoreAccountId account_id = RemoveAccountIdPrefix(prefixed_account_id);
AccountInfo account_info = account_tracker->GetAccountInfo(account_id);
if (!account_info.IsValid()) {
return false;
@@ -240,7 +238,7 @@ class MutableProfileOAuth2TokenServiceDelegate::RevokeServerRefreshToken
GaiaAuthFetcher fetcher_;
std::string refresh_token_;
int attempt_;
- base::WeakPtrFactory<RevokeServerRefreshToken> weak_ptr_factory_;
+ base::WeakPtrFactory<RevokeServerRefreshToken> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(RevokeServerRefreshToken);
};
@@ -256,8 +254,7 @@ MutableProfileOAuth2TokenServiceDelegate::RevokeServerRefreshToken::
gaia::GaiaSource::kChrome,
token_service_delegate_->GetURLLoaderFactory()),
refresh_token_(refresh_token),
- attempt_(attempt),
- weak_ptr_factory_(this) {
+ attempt_(attempt) {
RecordRefreshTokenRevocationRequestEvent(
TokenRevocationRequestProgress::kRequestCreated);
client->DelayNetworkCall(
@@ -372,9 +369,9 @@ void MutableProfileOAuth2TokenServiceDelegate::RegisterProfilePrefs(
registry->RegisterBooleanPref(prefs::kTokenServiceDiceCompatible, false);
}
-OAuth2AccessTokenFetcher*
+std::unique_ptr<OAuth2AccessTokenFetcher>
MutableProfileOAuth2TokenServiceDelegate::CreateAccessTokenFetcher(
- const std::string& account_id,
+ const CoreAccountId& account_id,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
OAuth2AccessTokenConsumer* consumer) {
ValidateAccountId(account_id);
@@ -382,29 +379,30 @@ MutableProfileOAuth2TokenServiceDelegate::CreateAccessTokenFetcher(
if (refresh_tokens_[account_id].last_auth_error.IsPersistentError()) {
VLOG(1) << "Request for token has been rejected due to persistent error #"
<< refresh_tokens_[account_id].last_auth_error.state();
- return new OAuth2AccessTokenFetcherImmediateError(
+ return std::make_unique<OAuth2AccessTokenFetcherImmediateError>(
consumer, refresh_tokens_[account_id].last_auth_error);
}
if (backoff_entry_.ShouldRejectRequest()) {
VLOG(1) << "Request for token has been rejected due to backoff rules from"
<< " previous error #" << backoff_error_.state();
- return new OAuth2AccessTokenFetcherImmediateError(consumer, backoff_error_);
+ return std::make_unique<OAuth2AccessTokenFetcherImmediateError>(
+ consumer, backoff_error_);
}
std::string refresh_token = GetRefreshToken(account_id);
DCHECK(!refresh_token.empty());
- return new OAuth2AccessTokenFetcherImpl(consumer, url_loader_factory,
- refresh_token);
+ return std::make_unique<OAuth2AccessTokenFetcherImpl>(
+ consumer, url_loader_factory, refresh_token);
}
GoogleServiceAuthError MutableProfileOAuth2TokenServiceDelegate::GetAuthError(
- const std::string& account_id) const {
+ const CoreAccountId& account_id) const {
auto it = refresh_tokens_.find(account_id);
return (it == refresh_tokens_.end()) ? GoogleServiceAuthError::AuthErrorNone()
: it->second.last_auth_error;
}
void MutableProfileOAuth2TokenServiceDelegate::UpdateAuthError(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const GoogleServiceAuthError& error) {
VLOG(1) << "MutablePO2TS::UpdateAuthError. Error: " << error.state()
<< " account_id=" << account_id;
@@ -436,7 +434,7 @@ void MutableProfileOAuth2TokenServiceDelegate::UpdateAuthError(
}
std::string MutableProfileOAuth2TokenServiceDelegate::GetTokenForMultilogin(
- const std::string& account_id) const {
+ const CoreAccountId& account_id) const {
auto iter = refresh_tokens_.find(account_id);
if (iter == refresh_tokens_.end() ||
iter->second.last_auth_error != GoogleServiceAuthError::AuthErrorNone()) {
@@ -448,13 +446,13 @@ std::string MutableProfileOAuth2TokenServiceDelegate::GetTokenForMultilogin(
}
bool MutableProfileOAuth2TokenServiceDelegate::RefreshTokenIsAvailable(
- const std::string& account_id) const {
+ const CoreAccountId& account_id) const {
VLOG(1) << "MutablePO2TS::RefreshTokenIsAvailable";
return !GetRefreshToken(account_id).empty();
}
std::string MutableProfileOAuth2TokenServiceDelegate::GetRefreshToken(
- const std::string& account_id) const {
+ const CoreAccountId& account_id) const {
auto iter = refresh_tokens_.find(account_id);
if (iter != refresh_tokens_.end()) {
const std::string refresh_token = iter->second.refresh_token;
@@ -465,13 +463,13 @@ std::string MutableProfileOAuth2TokenServiceDelegate::GetRefreshToken(
}
std::string MutableProfileOAuth2TokenServiceDelegate::GetRefreshTokenForTest(
- const std::string& account_id) const {
+ const CoreAccountId& account_id) const {
return GetRefreshToken(account_id);
}
-std::vector<std::string>
-MutableProfileOAuth2TokenServiceDelegate::GetAccounts() {
- std::vector<std::string> account_ids;
+std::vector<CoreAccountId>
+MutableProfileOAuth2TokenServiceDelegate::GetAccounts() const {
+ std::vector<CoreAccountId> account_ids;
for (auto& token : refresh_tokens_) {
account_ids.push_back(token.first);
}
@@ -484,27 +482,30 @@ MutableProfileOAuth2TokenServiceDelegate::GetURLLoaderFactory() const {
}
void MutableProfileOAuth2TokenServiceDelegate::InvalidateTokenForMultilogin(
- const std::string& failed_account) {
+ const CoreAccountId& failed_account) {
UpdateAuthError(
failed_account,
GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
}
void MutableProfileOAuth2TokenServiceDelegate::LoadCredentials(
- const std::string& primary_account_id) {
- if (load_credentials_state() == LOAD_CREDENTIALS_IN_PROGRESS) {
+ const CoreAccountId& primary_account_id) {
+ if (load_credentials_state() ==
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS) {
VLOG(1) << "Load credentials operation already in progress";
return;
}
- set_load_credentials_state(LOAD_CREDENTIALS_IN_PROGRESS);
+ set_load_credentials_state(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS);
#if defined(OS_CHROMEOS)
// TODO(sinhak): Remove this ifdef block after Account Manager is switched on.
// ChromeOS OOBE loads credentials without a primary account and expects this
// to be a no-op. See http://crbug.com/891818
if (primary_account_id.empty()) {
- set_load_credentials_state(LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
+ set_load_credentials_state(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
FinishLoadingCredentials();
return;
}
@@ -520,7 +521,9 @@ void MutableProfileOAuth2TokenServiceDelegate::LoadCredentials(
if (!token_web_data_) {
// This case only exists in unit tests that do not care about loading
// credentials.
- set_load_credentials_state(LOAD_CREDENTIALS_FINISHED_WITH_UNKNOWN_ERRORS);
+ set_load_credentials_state(
+ signin::LoadCredentialsState::
+ LOAD_CREDENTIALS_FINISHED_WITH_UNKNOWN_ERRORS);
FinishLoadingCredentials();
return;
}
@@ -528,8 +531,9 @@ void MutableProfileOAuth2TokenServiceDelegate::LoadCredentials(
// If |account_id| is an email address, then canonicalize it. This is needed
// to support legacy account IDs, and will not be needed after switching to
// gaia IDs.
- if (primary_account_id.find('@') != std::string::npos) {
- loading_primary_account_id_ = gaia::CanonicalizeEmail(primary_account_id);
+ if (primary_account_id.id.find('@') != std::string::npos) {
+ loading_primary_account_id_ =
+ CoreAccountId(gaia::CanonicalizeEmail(primary_account_id.id));
} else {
loading_primary_account_id_ = primary_account_id;
}
@@ -555,7 +559,9 @@ void MutableProfileOAuth2TokenServiceDelegate::OnWebDataServiceRequestDone(
set_load_credentials_state(LoadCredentialsStateFromTokenResult(
token_result->GetValue().db_result));
} else {
- set_load_credentials_state(LOAD_CREDENTIALS_FINISHED_WITH_UNKNOWN_ERRORS);
+ set_load_credentials_state(
+ signin::LoadCredentialsState::
+ LOAD_CREDENTIALS_FINISHED_WITH_DB_CANNOT_BE_OPENED);
}
// Make sure that we have an entry for |loading_primary_account_id_| in the
@@ -563,11 +569,14 @@ void MutableProfileOAuth2TokenServiceDelegate::OnWebDataServiceRequestDone(
// while this profile is connected to an account.
if (!loading_primary_account_id_.empty() &&
refresh_tokens_.count(loading_primary_account_id_) == 0) {
- if (load_credentials_state() == LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS) {
+ if (load_credentials_state() ==
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS) {
set_load_credentials_state(
- LOAD_CREDENTIALS_FINISHED_WITH_NO_TOKEN_FOR_PRIMARY_ACCOUNT);
+ signin::LoadCredentialsState::
+ LOAD_CREDENTIALS_FINISHED_WITH_NO_TOKEN_FOR_PRIMARY_ACCOUNT);
}
- AddAccountStatus(loading_primary_account_id_, kInvalidRefreshToken,
+ AddAccountStatus(loading_primary_account_id_,
+ GaiaConstants::kInvalidRefreshToken,
GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
GoogleServiceAuthError::InvalidGaiaCredentialsReason::
CREDENTIALS_MISSING));
@@ -583,7 +592,7 @@ void MutableProfileOAuth2TokenServiceDelegate::OnWebDataServiceRequestDone(
}
#endif
- loading_primary_account_id_.clear();
+ loading_primary_account_id_ = CoreAccountId();
FinishLoadingCredentials();
}
@@ -616,20 +625,20 @@ void MutableProfileOAuth2TokenServiceDelegate::LoadAllCredentialsIntoMemory(
}
} else {
DCHECK(!refresh_token.empty());
- std::string account_id = RemoveAccountIdPrefix(prefixed_account_id);
+ CoreAccountId account_id = RemoveAccountIdPrefix(prefixed_account_id);
switch (migration_state) {
case AccountTrackerService::MIGRATION_IN_PROGRESS: {
// Migrate to gaia-ids.
AccountInfo account_info =
- account_tracker_service_->FindAccountInfoByEmail(account_id);
- // |account_info.gaia| could be empty if |account_id| is already
- // gaia id. This could happen if the chrome was closed in the middle
- // of migration.
- if (!account_info.gaia.empty()) {
+ account_tracker_service_->FindAccountInfoByEmail(account_id.id);
+ // |account_info| can be empty if |account_id| was already migrated.
+ // This could happen if the chrome was closed in the middle of the
+ // account id migration.
+ if (!account_info.IsEmpty()) {
ClearPersistedCredentials(account_id);
- PersistCredentials(account_info.gaia, refresh_token);
- account_id = account_info.gaia;
+ account_id = account_info.account_id;
+ PersistCredentials(account_id, refresh_token);
}
// Skip duplicate accounts, this could happen if migration was
@@ -642,24 +651,24 @@ void MutableProfileOAuth2TokenServiceDelegate::LoadAllCredentialsIntoMemory(
// If the account_id is an email address, then canonicalize it. This
// is to support legacy account_ids, and will not be needed after
// switching to gaia-ids.
- if (account_id.find('@') != std::string::npos) {
+ if (account_id.id.find('@') != std::string::npos) {
// If the canonical account id is not the same as the loaded
// account id, make sure not to overwrite a refresh token from
// a canonical version. If no canonical version was loaded, then
// re-persist this refresh token with the canonical account id.
- std::string canon_account_id =
- gaia::CanonicalizeEmail(account_id);
+ CoreAccountId canon_account_id =
+ CoreAccountId(gaia::CanonicalizeEmail(account_id.id));
if (canon_account_id != account_id) {
ClearPersistedCredentials(account_id);
- if (db_tokens.count(ApplyAccountIdPrefix(canon_account_id)) ==
- 0)
+ if (db_tokens.count(
+ ApplyAccountIdPrefix(canon_account_id.id)) == 0)
PersistCredentials(canon_account_id, refresh_token);
}
account_id = canon_account_id;
}
break;
case AccountTrackerService::MIGRATION_DONE:
- DCHECK_EQ(std::string::npos, account_id.find('@'));
+ DCHECK_EQ(std::string::npos, account_id.id.find('@'));
break;
case AccountTrackerService::NUM_MIGRATION_STATES:
NOTREACHED();
@@ -694,7 +703,7 @@ void MutableProfileOAuth2TokenServiceDelegate::LoadAllCredentialsIntoMemory(
if (load_account && revoke_all_tokens_on_load_) {
if (account_id == loading_primary_account_id_) {
RevokeCredentialsOnServer(refresh_token);
- refresh_token = kInvalidRefreshToken;
+ refresh_token = GaiaConstants::kInvalidRefreshToken;
PersistCredentials(account_id, refresh_token);
} else {
load_account = false;
@@ -731,15 +740,13 @@ void MutableProfileOAuth2TokenServiceDelegate::LoadAllCredentialsIntoMemory(
}
void MutableProfileOAuth2TokenServiceDelegate::UpdateCredentials(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& refresh_token) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!account_id.empty());
DCHECK(!refresh_token.empty());
ValidateAccountId(account_id);
- signin_metrics::LogSigninAddAccount();
-
const std::string& existing_token = GetRefreshToken(account_id);
if (existing_token != refresh_token) {
ScopedBatchChange batch(this);
@@ -751,13 +758,14 @@ void MutableProfileOAuth2TokenServiceDelegate::UpdateCredentials(
}
void MutableProfileOAuth2TokenServiceDelegate::UpdateCredentialsInMemory(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& refresh_token) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!account_id.empty());
DCHECK(!refresh_token.empty());
- bool is_refresh_token_invalidated = refresh_token == kInvalidRefreshToken;
+ bool is_refresh_token_invalidated =
+ refresh_token == GaiaConstants::kInvalidRefreshToken;
GoogleServiceAuthError error =
is_refresh_token_invalidated
? GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
@@ -797,13 +805,13 @@ void MutableProfileOAuth2TokenServiceDelegate::UpdateCredentialsInMemory(
}
void MutableProfileOAuth2TokenServiceDelegate::PersistCredentials(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& refresh_token) {
DCHECK(!account_id.empty());
DCHECK(!refresh_token.empty());
if (token_web_data_) {
VLOG(1) << "MutablePO2TS::PersistCredentials for account_id=" << account_id;
- token_web_data_->SetTokenForService(ApplyAccountIdPrefix(account_id),
+ token_web_data_->SetTokenForService(ApplyAccountIdPrefix(account_id.id),
refresh_token);
}
}
@@ -816,13 +824,15 @@ void MutableProfileOAuth2TokenServiceDelegate::RevokeAllCredentials() {
VLOG(1) << "MutablePO2TS::RevokeAllCredentials";
ScopedBatchChange batch(this);
- if (load_credentials_state() == LOAD_CREDENTIALS_IN_PROGRESS) {
+ if (load_credentials_state() ==
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS) {
VLOG(1) << "MutablePO2TS::RevokeAllCredentials before tokens are loaded.";
// If |RevokeAllCredentials| is called while credentials are being loaded,
// then the load must be cancelled and the load credentials state updated.
DCHECK_NE(0, web_data_service_request_);
CancelWebTokenFetch();
- set_load_credentials_state(LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
+ set_load_credentials_state(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
FinishLoadingCredentials();
}
@@ -841,17 +851,17 @@ void MutableProfileOAuth2TokenServiceDelegate::RevokeAllCredentials() {
}
void MutableProfileOAuth2TokenServiceDelegate::RevokeCredentials(
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
RevokeCredentialsImpl(account_id, /*revoke_on_server=*/true);
}
void MutableProfileOAuth2TokenServiceDelegate::ClearPersistedCredentials(
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
DCHECK(!account_id.empty());
if (token_web_data_) {
VLOG(1) << "MutablePO2TS::ClearPersistedCredentials for account_id="
<< account_id;
- token_web_data_->RemoveTokenForService(ApplyAccountIdPrefix(account_id));
+ token_web_data_->RemoveTokenForService(ApplyAccountIdPrefix(account_id.id));
}
}
@@ -859,7 +869,7 @@ void MutableProfileOAuth2TokenServiceDelegate::RevokeCredentialsOnServer(
const std::string& refresh_token) {
DCHECK(!refresh_token.empty());
- if (refresh_token == kInvalidRefreshToken)
+ if (refresh_token == GaiaConstants::kInvalidRefreshToken)
return;
// Keep track or all server revoke requests. This way they can be deleted
@@ -877,8 +887,8 @@ void MutableProfileOAuth2TokenServiceDelegate::CancelWebTokenFetch() {
}
void MutableProfileOAuth2TokenServiceDelegate::ExtractCredentials(
- OAuth2TokenService* to_service,
- const std::string& account_id) {
+ ProfileOAuth2TokenService* to_service,
+ const CoreAccountId& account_id) {
static_cast<ProfileOAuth2TokenService*>(to_service)
->UpdateCredentials(account_id, GetRefreshToken(account_id),
signin_metrics::SourceForRefreshTokenOperation::
@@ -891,7 +901,7 @@ void MutableProfileOAuth2TokenServiceDelegate::Shutdown() {
server_revokes_.clear();
CancelWebTokenFetch();
refresh_tokens_.clear();
- OAuth2TokenServiceDelegate::Shutdown();
+ ProfileOAuth2TokenServiceDelegate::Shutdown();
}
void MutableProfileOAuth2TokenServiceDelegate::OnConnectionChanged(
@@ -913,7 +923,7 @@ bool MutableProfileOAuth2TokenServiceDelegate::FixRequestErrorIfPossible() {
}
void MutableProfileOAuth2TokenServiceDelegate::AddAccountStatus(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& refresh_token,
const GoogleServiceAuthError& error) {
DCHECK_EQ(0u, refresh_tokens_.count(account_id));
@@ -926,7 +936,7 @@ void MutableProfileOAuth2TokenServiceDelegate::FinishLoadingCredentials() {
}
void MutableProfileOAuth2TokenServiceDelegate::RevokeCredentialsImpl(
- const std::string& account_id,
+ const CoreAccountId& account_id,
bool revoke_on_server) {
ValidateAccountId(account_id);
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/chromium/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate.h b/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.h
index 906e25a5c9e..9c398812676 100644
--- a/chromium/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate.h
+++ b/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_MUTABLE_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_MUTABLE_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_MUTABLE_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_MUTABLE_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_
#include <memory>
#include <vector>
@@ -12,21 +12,21 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/threading/thread_checker.h"
-#include "components/signin/core/browser/account_consistency_method.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/webdata/token_web_data.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
+#include "components/signin/public/base/account_consistency_method.h"
#include "components/webdata/common/web_data_service_base.h"
#include "components/webdata/common/web_data_service_consumer.h"
-#include "google_apis/gaia/oauth2_token_service_delegate.h"
#include "net/base/backoff_entry.h"
#include "services/network/public/cpp/network_connection_tracker.h"
class PrefRegistrySimple;
class SigninClient;
+class TokenWebData;
class MutableProfileOAuth2TokenServiceDelegate
- : public OAuth2TokenServiceDelegate,
+ : public ProfileOAuth2TokenServiceDelegate,
public WebDataServiceConsumer,
public network::NetworkConnectionTracker::NetworkConnectionObserver {
public:
@@ -45,44 +45,44 @@ class MutableProfileOAuth2TokenServiceDelegate
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
- // Overridden from OAuth2TokenServiceDelegate.
- OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
- const std::string& account_id,
+ // Overridden from ProfileOAuth2TokenServiceDelegate.
+ std::unique_ptr<OAuth2AccessTokenFetcher> CreateAccessTokenFetcher(
+ const CoreAccountId& account_id,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
OAuth2AccessTokenConsumer* consumer) override;
// Updates the internal cache of the result from the most-recently-completed
// auth request (used for reporting errors to the user).
- void UpdateAuthError(const std::string& account_id,
+ void UpdateAuthError(const CoreAccountId& account_id,
const GoogleServiceAuthError& error) override;
std::string GetTokenForMultilogin(
- const std::string& account_id) const override;
- bool RefreshTokenIsAvailable(const std::string& account_id) const override;
+ const CoreAccountId& account_id) const override;
+ bool RefreshTokenIsAvailable(const CoreAccountId& account_id) const override;
GoogleServiceAuthError GetAuthError(
- const std::string& account_id) const override;
- std::vector<std::string> GetAccounts() override;
+ const CoreAccountId& account_id) const override;
+ std::vector<CoreAccountId> GetAccounts() const override;
scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory()
const override;
- void LoadCredentials(const std::string& primary_account_id) override;
- void UpdateCredentials(const std::string& account_id,
+ void LoadCredentials(const CoreAccountId& primary_account_id) override;
+ void UpdateCredentials(const CoreAccountId& account_id,
const std::string& refresh_token) override;
void RevokeAllCredentials() override;
- void RevokeCredentials(const std::string& account_id) override;
- void ExtractCredentials(OAuth2TokenService* to_service,
- const std::string& account_id) override;
+ void RevokeCredentials(const CoreAccountId& account_id) override;
+ void ExtractCredentials(ProfileOAuth2TokenService* to_service,
+ const CoreAccountId& account_id) override;
void Shutdown() override;
// Overridden from NetworkConnectionTracker::NetworkConnectionObserver.
void OnConnectionChanged(network::mojom::ConnectionType type) override;
- // Overridden from OAuth2TokenServiceDelegate.
+ // Overridden from ProfileOAuth2TokenServiceDelegate.
const net::BackoffEntry* BackoffEntry() const override;
bool FixRequestErrorIfPossible() override;
// Returns the account's refresh token used for testing purposes.
- std::string GetRefreshTokenForTest(const std::string& account_id) const;
+ std::string GetRefreshTokenForTest(const CoreAccountId& account_id) const;
private:
friend class MutableProfileOAuth2TokenServiceDelegateTest;
@@ -147,20 +147,21 @@ class MutableProfileOAuth2TokenServiceDelegate
const std::map<std::string, std::string>& db_tokens);
// Updates the in-memory representation of the credentials.
- void UpdateCredentialsInMemory(const std::string& account_id,
+ void UpdateCredentialsInMemory(const CoreAccountId& account_id,
const std::string& refresh_token);
// Sets refresh token in error.
- void InvalidateTokenForMultilogin(const std::string& failed_account) override;
+ void InvalidateTokenForMultilogin(
+ const CoreAccountId& failed_account) override;
// Persists credentials for |account_id|. Enables overriding for
// testing purposes, or other cases, when accessing the DB is not desired.
- void PersistCredentials(const std::string& account_id,
+ void PersistCredentials(const CoreAccountId& account_id,
const std::string& refresh_token);
// Clears credentials persisted for |account_id|. Enables overriding for
// testing purposes, or other cases, when accessing the DB is not desired.
- void ClearPersistedCredentials(const std::string& account_id);
+ void ClearPersistedCredentials(const CoreAccountId& account_id);
// Revokes the refresh token on the server.
void RevokeCredentialsOnServer(const std::string& refresh_token);
@@ -168,11 +169,11 @@ class MutableProfileOAuth2TokenServiceDelegate
// Cancels any outstanding fetch for tokens from the web database.
void CancelWebTokenFetch();
- std::string GetRefreshToken(const std::string& account_id) const;
+ std::string GetRefreshToken(const CoreAccountId& account_id) const;
// Creates a new AccountStatus and adds it to the AccountStatusMap.
// The account must not be already in the map.
- void AddAccountStatus(const std::string& account_id,
+ void AddAccountStatus(const CoreAccountId& account_id,
const std::string& refresh_token,
const GoogleServiceAuthError& error);
@@ -183,12 +184,12 @@ class MutableProfileOAuth2TokenServiceDelegate
// Deletes the credential locally and notifies observers through
// OnRefreshTokenRevoked(). If |revoke_on_server| is true, the token is also
// revoked on the server.
- void RevokeCredentialsImpl(const std::string& account_id,
+ void RevokeCredentialsImpl(const CoreAccountId& account_id,
bool revoke_on_server);
// Maps the |account_id| of accounts known to ProfileOAuth2TokenService
// to information about the account.
- typedef std::map<std::string, AccountStatus> AccountStatusMap;
+ typedef std::map<CoreAccountId, AccountStatus> AccountStatusMap;
// In memory refresh token store mapping account_id to refresh_token.
AccountStatusMap refresh_tokens_;
@@ -197,7 +198,7 @@ class MutableProfileOAuth2TokenServiceDelegate
// The primary account id of this service's profile during the loading of
// credentials. This member is empty otherwise.
- std::string loading_primary_account_id_;
+ CoreAccountId loading_primary_account_id_;
std::vector<std::unique_ptr<RevokeServerRefreshToken>> server_revokes_;
@@ -233,4 +234,4 @@ class MutableProfileOAuth2TokenServiceDelegate
DISALLOW_COPY_AND_ASSIGN(MutableProfileOAuth2TokenServiceDelegate);
};
-#endif // CHROME_BROWSER_SIGNIN_MUTABLE_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_MUTABLE_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_
diff --git a/chromium/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate_unittest.cc b/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc
index 7a42f2e4c1d..a25bc19bb95 100644
--- a/chromium/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/mutable_profile_oauth2_token_service_delegate.h"
+#include "components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.h"
#include <map>
#include <string>
@@ -20,26 +20,26 @@
#include "build/build_config.h"
#include "build/buildflag.h"
#include "components/os_crypt/os_crypt_mocker.h"
-#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/scoped_user_pref_update.h"
-#include "components/signin/core/browser/account_consistency_method.h"
-#include "components/signin/core/browser/account_info.h"
-#include "components/signin/core/browser/device_id_helper.h"
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_buildflags.h"
-#include "components/signin/core/browser/signin_manager_base.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "components/signin/core/browser/test_signin_client.h"
-#include "components/signin/core/browser/webdata/token_web_data.h"
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.h"
+#include "components/signin/internal/identity_manager/primary_account_manager.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/base/device_id_helper.h"
+#include "components/signin/public/base/signin_buildflags.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/base/test_signin_client.h"
+#include "components/signin/public/identity_manager/account_info.h"
+#include "components/signin/public/webdata/token_web_data.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "components/webdata/common/web_data_service_base.h"
#include "components/webdata/common/web_database_service.h"
-#include "google_apis/gaia/fake_oauth2_token_service_delegate.h"
#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_access_token_consumer.h"
-#include "google_apis/gaia/oauth2_token_service_test_util.h"
+#include "google_apis/gaia/oauth2_access_token_fetcher.h"
+#include "google_apis/gaia/oauth2_access_token_manager_test_util.h"
#include "net/http/http_status_code.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/test/test_network_connection_tracker.h"
@@ -81,8 +81,7 @@ AccountInfo CreateTestAccountInfo(const std::string& name,
class MutableProfileOAuth2TokenServiceDelegateTest
: public testing::Test,
public OAuth2AccessTokenConsumer,
- public OAuth2TokenService::Observer,
- public OAuth2TokenService::DiagnosticsObserver,
+ public OAuth2TokenServiceObserver,
public WebDataServiceConsumer {
public:
MutableProfileOAuth2TokenServiceDelegateTest()
@@ -105,7 +104,7 @@ class MutableProfileOAuth2TokenServiceDelegateTest
MutableProfileOAuth2TokenServiceDelegate::RegisterProfilePrefs(
pref_service_.registry());
AccountTrackerService::RegisterPrefs(pref_service_.registry());
- SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
+ PrimaryAccountManager::RegisterProfilePrefs(pref_service_.registry());
client_.reset(new TestSigninClient(&pref_service_));
client_->GetTestURLLoaderFactory()->AddResponse(
GaiaUrls::GetInstance()->oauth2_revoke_url().spec(), "");
@@ -187,30 +186,30 @@ class MutableProfileOAuth2TokenServiceDelegateTest
access_token_failure_ = error;
}
- // OAuth2TokenService::Observer implementation.
- void OnRefreshTokenAvailable(const std::string& account_id) override {
+ // OAuth2TokenServiceObserver implementation.
+ void OnRefreshTokenAvailable(const CoreAccountId& account_id) override {
++token_available_count_;
}
- void OnRefreshTokenRevoked(const std::string& account_id) override {
+ void OnRefreshTokenRevoked(const CoreAccountId& account_id) override {
++token_revoked_count_;
}
void OnRefreshTokensLoaded() override { ++tokens_loaded_count_; }
void OnEndBatchChanges() override { ++end_batch_changes_; }
- void OnAuthErrorChanged(const std::string& account_id,
+ void OnAuthErrorChanged(const CoreAccountId& account_id,
const GoogleServiceAuthError& auth_error) override {
++auth_error_changed_count_;
}
- // OAuth2TokenService::DiagnosticsObserver implementation
+ // ProfileOAuth2TokenService callbacks.
void OnRefreshTokenAvailableFromSource(const CoreAccountId& account_id,
bool is_refresh_token_valid,
- const std::string& source) override {
+ const std::string& source) {
source_for_refresh_token_available_ = source;
}
void OnRefreshTokenRevokedFromSource(const CoreAccountId& account_id,
- const std::string& source) override {
+ const std::string& source) {
source_for_refresh_token_revoked_ = source;
}
@@ -256,7 +255,7 @@ class MutableProfileOAuth2TokenServiceDelegateTest
std::unique_ptr<TestSigninClient> client_;
std::unique_ptr<MutableProfileOAuth2TokenServiceDelegate>
oauth2_service_delegate_;
- TestingOAuth2TokenServiceConsumer consumer_;
+ TestingOAuth2AccessTokenManagerConsumer consumer_;
sync_preferences::TestingPrefServiceSyncable pref_service_;
AccountTrackerService account_tracker_service_;
scoped_refptr<TokenWebData> token_web_data_;
@@ -276,7 +275,7 @@ class MutableProfileOAuth2TokenServiceDelegateTest
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, PersistenceDBUpgrade) {
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kMirror);
- std::string main_account_id("account_id");
+ CoreAccountId main_account_id("account_id");
std::string main_refresh_token("old_refresh_token");
// Populate DB with legacy tokens.
@@ -344,9 +343,9 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, PersistenceDBUpgrade) {
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
PersistenceRevokeCredentials) {
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDisabled);
- std::string account_id_1 = "account_id_1";
+ CoreAccountId account_id_1("account_id_1");
std::string refresh_token_1 = "refresh_token_1";
- std::string account_id_2 = "account_id_2";
+ CoreAccountId account_id_2("account_id_2");
std::string refresh_token_2 = "refresh_token_2";
EXPECT_FALSE(oauth2_service_delegate_->RefreshTokenIsAvailable(account_id_1));
@@ -380,30 +379,33 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
// Ensure DB is clean.
oauth2_service_delegate_->RevokeAllCredentials();
- EXPECT_EQ(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_NOT_STARTED,
+ EXPECT_EQ(signin::LoadCredentialsState::LOAD_CREDENTIALS_NOT_STARTED,
oauth2_service_delegate_->load_credentials_state());
oauth2_service_delegate_->LoadCredentials("");
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
- oauth2_service_delegate_->load_credentials_state());
+ EXPECT_EQ(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ oauth2_service_delegate_->load_credentials_state());
}
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
PersistenceLoadCredentials) {
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kMirror);
+ const CoreAccountId account_id("account_id");
+ const CoreAccountId account_id2("account_id_2");
// Ensure DB is clean.
oauth2_service_delegate_->RevokeAllCredentials();
ResetObserverCounts();
// Perform a load from an empty DB.
- EXPECT_EQ(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_NOT_STARTED,
+ EXPECT_EQ(signin::LoadCredentialsState::LOAD_CREDENTIALS_NOT_STARTED,
oauth2_service_delegate_->load_credentials_state());
oauth2_service_delegate_->LoadCredentials("account_id");
- EXPECT_EQ(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_IN_PROGRESS,
+ EXPECT_EQ(signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS,
oauth2_service_delegate_->load_credentials_state());
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(OAuth2TokenServiceDelegate::
+ EXPECT_EQ(signin::LoadCredentialsState::
LOAD_CREDENTIALS_FINISHED_WITH_NO_TOKEN_FOR_PRIMARY_ACCOUNT,
oauth2_service_delegate_->load_credentials_state());
EXPECT_EQ(GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
@@ -427,24 +429,25 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
// is in the refresh_token map.
EXPECT_EQ(1U, oauth2_service_delegate_->refresh_tokens_.size());
EXPECT_EQ(
- MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken,
- oauth2_service_delegate_->refresh_tokens_["account_id"].refresh_token);
+ GaiaConstants::kInvalidRefreshToken,
+ oauth2_service_delegate_->refresh_tokens_[account_id].refresh_token);
// Setup a DB with tokens that don't require upgrade and clear memory.
- oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token");
- oauth2_service_delegate_->UpdateCredentials("account_id2", "refresh_token2");
+ oauth2_service_delegate_->UpdateCredentials(account_id, "refresh_token");
+ oauth2_service_delegate_->UpdateCredentials(account_id2, "refresh_token2");
oauth2_service_delegate_->refresh_tokens_.clear();
EXPECT_EQ(2, end_batch_changes_);
EXPECT_EQ(2, auth_error_changed_count_);
ResetObserverCounts();
- oauth2_service_delegate_->LoadCredentials("account_id");
- EXPECT_EQ(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_IN_PROGRESS,
+ oauth2_service_delegate_->LoadCredentials(account_id);
+ EXPECT_EQ(signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS,
oauth2_service_delegate_->load_credentials_state());
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
- oauth2_service_delegate_->load_credentials_state());
+ EXPECT_EQ(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ oauth2_service_delegate_->load_credentials_state());
EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
- oauth2_service_delegate_->GetAuthError("account_id"));
+ oauth2_service_delegate_->GetAuthError(account_id));
EXPECT_EQ(2, token_available_count_);
EXPECT_EQ(0, token_revoked_count_);
EXPECT_EQ(1, tokens_loaded_count_);
@@ -452,8 +455,8 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
EXPECT_EQ(2, auth_error_changed_count_);
ResetObserverCounts();
- EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable("account_id"));
- EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable("account_id2"));
+ EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(account_id));
+ EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(account_id2));
oauth2_service_delegate_->RevokeAllCredentials();
EXPECT_EQ(0, token_available_count_);
@@ -469,19 +472,22 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
PersistenceLoadCredentialsEmptyPrimaryAccountId_DiceEnabled) {
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDice);
+ const CoreAccountId account_id("account_id");
+ const CoreAccountId account_id2("account_id_2");
// Ensure DB is clean.
oauth2_service_delegate_->RevokeAllCredentials();
ResetObserverCounts();
// Perform a load from an empty DB.
- EXPECT_EQ(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_NOT_STARTED,
+ EXPECT_EQ(signin::LoadCredentialsState::LOAD_CREDENTIALS_NOT_STARTED,
oauth2_service_delegate_->load_credentials_state());
oauth2_service_delegate_->LoadCredentials("");
- EXPECT_EQ(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_IN_PROGRESS,
+ EXPECT_EQ(signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS,
oauth2_service_delegate_->load_credentials_state());
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
- oauth2_service_delegate_->load_credentials_state());
+ EXPECT_EQ(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ oauth2_service_delegate_->load_credentials_state());
EXPECT_EQ(1, end_batch_changes_);
EXPECT_EQ(0, auth_error_changed_count_);
ExpectOneTokensLoadedNotification();
@@ -491,19 +497,20 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
EXPECT_TRUE(oauth2_service_delegate_->refresh_tokens_.empty());
// Setup a DB with tokens that don't require upgrade and clear memory.
- oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token");
- oauth2_service_delegate_->UpdateCredentials("account_id2", "refresh_token2");
+ oauth2_service_delegate_->UpdateCredentials(account_id, "refresh_token");
+ oauth2_service_delegate_->UpdateCredentials(account_id2, "refresh_token2");
oauth2_service_delegate_->refresh_tokens_.clear();
EXPECT_EQ(2, end_batch_changes_);
EXPECT_EQ(2, auth_error_changed_count_);
ResetObserverCounts();
oauth2_service_delegate_->LoadCredentials("");
- EXPECT_EQ(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_IN_PROGRESS,
+ EXPECT_EQ(signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS,
oauth2_service_delegate_->load_credentials_state());
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
- oauth2_service_delegate_->load_credentials_state());
+ EXPECT_EQ(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ oauth2_service_delegate_->load_credentials_state());
EXPECT_EQ(2, token_available_count_);
EXPECT_EQ(0, token_revoked_count_);
EXPECT_EQ(1, tokens_loaded_count_);
@@ -511,8 +518,8 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
EXPECT_EQ(2, auth_error_changed_count_);
ResetObserverCounts();
- EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable("account_id"));
- EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable("account_id2"));
+ EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(account_id));
+ EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(account_id2));
oauth2_service_delegate_->RevokeAllCredentials();
EXPECT_EQ(0, token_available_count_);
@@ -557,8 +564,9 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
primary_account.account_id));
EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(
secondary_account.account_id));
- EXPECT_EQ(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
- oauth2_service_delegate_->load_credentials_state());
+ EXPECT_EQ(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ oauth2_service_delegate_->load_credentials_state());
EXPECT_FALSE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
}
@@ -598,8 +606,9 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
primary_account.account_id));
EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(
secondary_account.account_id));
- EXPECT_EQ(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
- oauth2_service_delegate_->load_credentials_state());
+ EXPECT_EQ(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ oauth2_service_delegate_->load_credentials_state());
EXPECT_TRUE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
}
@@ -637,8 +646,9 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
EXPECT_EQ(1, auth_error_changed_count_);
EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(
primary_account.account_id));
- EXPECT_EQ(OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
- oauth2_service_delegate_->load_credentials_state());
+ EXPECT_EQ(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ oauth2_service_delegate_->load_credentials_state());
EXPECT_TRUE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
}
@@ -676,14 +686,14 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(
primary_account.account_id));
EXPECT_EQ(
- MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken,
+ GaiaConstants::kInvalidRefreshToken,
oauth2_service_delegate_->refresh_tokens_[primary_account.account_id]
.refresh_token);
EXPECT_EQ(
GoogleServiceAuthError::InvalidGaiaCredentialsReason::CREDENTIALS_MISSING,
oauth2_service_delegate_->GetAuthError(primary_account.account_id)
.GetInvalidGaiaCredentialsReason());
- EXPECT_EQ(OAuth2TokenServiceDelegate::
+ EXPECT_EQ(signin::LoadCredentialsState::
LOAD_CREDENTIALS_FINISHED_WITH_NO_TOKEN_FOR_PRIMARY_ACCOUNT,
oauth2_service_delegate_->load_credentials_state());
@@ -721,16 +731,18 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
// Tests that calling UpdateCredentials revokes the old token, without sending
// the notification.
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, RevokeOnUpdate) {
+ const CoreAccountId account_id("account_id");
+
// Add a token.
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDisabled);
ASSERT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
- oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token");
+ oauth2_service_delegate_->UpdateCredentials(account_id, "refresh_token");
EXPECT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
ExpectOneTokenAvailableNotification();
// Updating the token does not revoke the old one.
// Regression test for http://crbug.com/865189
- oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token2");
+ oauth2_service_delegate_->UpdateCredentials(account_id, "refresh_token2");
EXPECT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
ExpectOneTokenAvailableNotification();
@@ -739,7 +751,7 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, RevokeOnUpdate) {
EXPECT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
// Set the same token again.
- oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token2");
+ oauth2_service_delegate_->UpdateCredentials(account_id, "refresh_token2");
EXPECT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
ExpectNoNotifications();
@@ -754,11 +766,13 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, RevokeOnUpdate) {
}
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, DelayedRevoke) {
+ const CoreAccountId account_id("account_id");
+
client_->SetNetworkCallsDelayed(true);
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDisabled);
- oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token");
+ oauth2_service_delegate_->UpdateCredentials(account_id, "refresh_token");
EXPECT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
- oauth2_service_delegate_->RevokeCredentials("account_id");
+ oauth2_service_delegate_->RevokeCredentials(account_id);
// The revoke does not start until network calls are unblocked.
EXPECT_EQ(1u, oauth2_service_delegate_->server_revokes_.size());
@@ -772,11 +786,13 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, DelayedRevoke) {
}
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, ShutdownDuringRevoke) {
+ const CoreAccountId account_id("account_id");
+
// Shutdown cancels the revocation.
client_->SetNetworkCallsDelayed(true);
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDisabled);
- oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token");
- oauth2_service_delegate_->RevokeCredentials("account_id");
+ oauth2_service_delegate_->UpdateCredentials(account_id, "refresh_token");
+ oauth2_service_delegate_->RevokeCredentials(account_id);
EXPECT_EQ(1u, oauth2_service_delegate_->server_revokes_.size());
// Shutdown.
@@ -791,14 +807,15 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, ShutdownDuringRevoke) {
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, RevokeRetries) {
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDisabled);
const std::string url = GaiaUrls::GetInstance()->oauth2_revoke_url().spec();
+ const CoreAccountId account_id("account_id");
// Revokes will remain in "pending" state.
client_->GetTestURLLoaderFactory()->ClearResponses();
- oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token");
+ oauth2_service_delegate_->UpdateCredentials(account_id, "refresh_token");
EXPECT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
EXPECT_FALSE(client_->GetTestURLLoaderFactory()->IsPending(url));
- oauth2_service_delegate_->RevokeCredentials("account_id");
+ oauth2_service_delegate_->RevokeCredentials(account_id);
EXPECT_EQ(1u, oauth2_service_delegate_->server_revokes_.size());
EXPECT_TRUE(client_->GetTestURLLoaderFactory()->IsPending(url));
// Fail and retry.
@@ -818,8 +835,8 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, RevokeRetries) {
EXPECT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
// No retry after success.
- oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token");
- oauth2_service_delegate_->RevokeCredentials("account_id");
+ oauth2_service_delegate_->UpdateCredentials(account_id, "refresh_token");
+ oauth2_service_delegate_->RevokeCredentials(account_id);
EXPECT_EQ(1u, oauth2_service_delegate_->server_revokes_.size());
EXPECT_TRUE(client_->GetTestURLLoaderFactory()->IsPending(url));
client_->GetTestURLLoaderFactory()->SimulateResponseForPendingRequest(
@@ -829,12 +846,12 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, RevokeRetries) {
}
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, UpdateInvalidToken) {
+ const CoreAccountId account_id("account_id");
// Add the invalid token.
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDisabled);
ASSERT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
oauth2_service_delegate_->UpdateCredentials(
- "account_id",
- MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken);
+ account_id, GaiaConstants::kInvalidRefreshToken);
EXPECT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
EXPECT_EQ(1, auth_error_changed_count_);
ExpectOneTokenAvailableNotification();
@@ -844,32 +861,32 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, UpdateInvalidToken) {
GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
GoogleServiceAuthError::InvalidGaiaCredentialsReason::
CREDENTIALS_REJECTED_BY_CLIENT)),
- oauth2_service_delegate_->GetAuthError("account_id"));
+ oauth2_service_delegate_->GetAuthError(account_id));
// Update the token: authentication error is fixed, no actual server
// revocation.
- oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token");
+ oauth2_service_delegate_->UpdateCredentials(account_id, "refresh_token");
EXPECT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
EXPECT_EQ(1, auth_error_changed_count_);
ExpectOneTokenAvailableNotification();
EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
- oauth2_service_delegate_->GetAuthError("account_id"));
+ oauth2_service_delegate_->GetAuthError(account_id));
}
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
InvalidateTokensForMultilogin) {
- class TokenServiceErrorObserver : public OAuth2TokenService::Observer {
+ class TokenServiceErrorObserver : public OAuth2TokenServiceObserver {
public:
MOCK_METHOD2(OnAuthErrorChanged,
- void(const std::string&, const GoogleServiceAuthError&));
+ void(const CoreAccountId&, const GoogleServiceAuthError&));
};
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDice);
TokenServiceErrorObserver observer;
oauth2_service_delegate_->AddObserver(&observer);
- const std::string account_id1 = "account_id1";
- const std::string account_id2 = "account_id2";
+ const CoreAccountId account_id1("account_id1");
+ const CoreAccountId account_id2("account_id2");
// This will be fired from UpdateCredentials.
EXPECT_CALL(
@@ -901,28 +918,28 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, LoadInvalidToken) {
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDice);
std::map<std::string, std::string> tokens;
- tokens["AccountId-account_id"] =
- MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken;
+ const CoreAccountId account_id("account_id");
+ tokens["AccountId-account_id"] = GaiaConstants::kInvalidRefreshToken;
oauth2_service_delegate_->LoadAllCredentialsIntoMemory(tokens);
EXPECT_EQ(1u, oauth2_service_delegate_->GetAccounts().size());
- EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable("account_id"));
- EXPECT_STREQ(MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken,
- oauth2_service_delegate_->GetRefreshToken("account_id").c_str());
+ EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(account_id));
+ EXPECT_STREQ(GaiaConstants::kInvalidRefreshToken,
+ oauth2_service_delegate_->GetRefreshToken(account_id).c_str());
// The account is in authentication error.
EXPECT_EQ(GoogleServiceAuthError(
GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
GoogleServiceAuthError::InvalidGaiaCredentialsReason::
CREDENTIALS_REJECTED_BY_CLIENT)),
- oauth2_service_delegate_->GetAuthError("account_id"));
+ oauth2_service_delegate_->GetAuthError(account_id));
}
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, GetTokenForMultilogin) {
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDice);
- const std::string account_id1 = "account_id1";
- const std::string account_id2 = "account_id2";
+ const CoreAccountId account_id1("account_id1");
+ const CoreAccountId account_id2("account_id2");
oauth2_service_delegate_->UpdateCredentials(account_id1, "refresh_token1");
oauth2_service_delegate_->UpdateCredentials(account_id2, "refresh_token2");
@@ -939,20 +956,22 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, GetTokenForMultilogin) {
}
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, PersistenceNotifications) {
+ const CoreAccountId account_id("account_id");
+
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDisabled);
- oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token");
+ oauth2_service_delegate_->UpdateCredentials(account_id, "refresh_token");
ExpectOneTokenAvailableNotification();
- oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token");
+ oauth2_service_delegate_->UpdateCredentials(account_id, "refresh_token");
ExpectNoNotifications();
- oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token2");
+ oauth2_service_delegate_->UpdateCredentials(account_id, "refresh_token2");
ExpectOneTokenAvailableNotification();
- oauth2_service_delegate_->RevokeCredentials("account_id");
+ oauth2_service_delegate_->RevokeCredentials(account_id);
ExpectOneTokenRevokedNotification();
- oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token2");
+ oauth2_service_delegate_->UpdateCredentials(account_id, "refresh_token2");
ExpectOneTokenAvailableNotification();
oauth2_service_delegate_->RevokeAllCredentials();
@@ -960,30 +979,37 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, PersistenceNotifications) {
}
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, GetAccounts) {
+ const CoreAccountId account_id1("account_id1");
+ const CoreAccountId account_id2("account_id2");
+
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDisabled);
EXPECT_TRUE(oauth2_service_delegate_->GetAccounts().empty());
- oauth2_service_delegate_->UpdateCredentials("account_id1", "refresh_token1");
- oauth2_service_delegate_->UpdateCredentials("account_id2", "refresh_token2");
- std::vector<std::string> accounts = oauth2_service_delegate_->GetAccounts();
+
+ oauth2_service_delegate_->UpdateCredentials(account_id1, "refresh_token1");
+ oauth2_service_delegate_->UpdateCredentials(account_id2, "refresh_token2");
+ std::vector<CoreAccountId> accounts = oauth2_service_delegate_->GetAccounts();
EXPECT_EQ(2u, accounts.size());
- EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id1"));
- EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id2"));
- oauth2_service_delegate_->RevokeCredentials("account_id2");
+ EXPECT_EQ(1, count(accounts.begin(), accounts.end(), account_id1));
+ EXPECT_EQ(1, count(accounts.begin(), accounts.end(), account_id2));
+ oauth2_service_delegate_->RevokeCredentials(account_id2);
accounts = oauth2_service_delegate_->GetAccounts();
EXPECT_EQ(1u, oauth2_service_delegate_->GetAccounts().size());
- EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id1"));
+ EXPECT_EQ(1, count(accounts.begin(), accounts.end(), account_id1));
}
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, FetchPersistentError) {
+ const CoreAccountId email(kEmail);
+
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDisabled);
- oauth2_service_delegate_->UpdateCredentials(kEmail, "refreshToken");
+ oauth2_service_delegate_->UpdateCredentials(email, "refreshToken");
EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
- oauth2_service_delegate_->GetAuthError(kEmail));
+ oauth2_service_delegate_->GetAuthError(email));
- GoogleServiceAuthError authfail(GoogleServiceAuthError::ACCOUNT_DELETED);
- oauth2_service_delegate_->UpdateAuthError(kEmail, authfail);
+ GoogleServiceAuthError authfail(
+ GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
+ oauth2_service_delegate_->UpdateAuthError(email, authfail);
EXPECT_NE(GoogleServiceAuthError::AuthErrorNone(),
- oauth2_service_delegate_->GetAuthError(kEmail));
+ oauth2_service_delegate_->GetAuthError(email));
// Create a "success" fetch we don't expect to get called.
AddSuccessfulOAuhTokenResponse();
@@ -992,9 +1018,9 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, FetchPersistentError) {
EXPECT_EQ(0, access_token_failure_count_);
std::vector<std::string> scope_list;
scope_list.push_back("scope");
- std::unique_ptr<OAuth2AccessTokenFetcher> fetcher(
+ std::unique_ptr<OAuth2AccessTokenFetcher> fetcher =
oauth2_service_delegate_->CreateAccessTokenFetcher(
- kEmail, oauth2_service_delegate_->GetURLLoaderFactory(), this));
+ email, oauth2_service_delegate_->GetURLLoaderFactory(), this);
fetcher->Start("foo", "bar", scope_list);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, access_token_success_count_);
@@ -1002,15 +1028,17 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, FetchPersistentError) {
}
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, RetryBackoff) {
+ const CoreAccountId email(kEmail);
+
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDisabled);
- oauth2_service_delegate_->UpdateCredentials(kEmail, "refreshToken");
+ oauth2_service_delegate_->UpdateCredentials(email, "refreshToken");
EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
- oauth2_service_delegate_->GetAuthError(kEmail));
+ oauth2_service_delegate_->GetAuthError(email));
GoogleServiceAuthError authfail(GoogleServiceAuthError::SERVICE_UNAVAILABLE);
- oauth2_service_delegate_->UpdateAuthError(kEmail, authfail);
+ oauth2_service_delegate_->UpdateAuthError(email, authfail);
EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
- oauth2_service_delegate_->GetAuthError(kEmail));
+ oauth2_service_delegate_->GetAuthError(email));
// Create a "success" fetch we don't expect to get called just yet.
AddSuccessfulOAuhTokenResponse();
@@ -1020,9 +1048,9 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, RetryBackoff) {
EXPECT_EQ(0, access_token_failure_count_);
std::vector<std::string> scope_list;
scope_list.push_back("scope");
- std::unique_ptr<OAuth2AccessTokenFetcher> fetcher1(
+ std::unique_ptr<OAuth2AccessTokenFetcher> fetcher1 =
oauth2_service_delegate_->CreateAccessTokenFetcher(
- kEmail, oauth2_service_delegate_->GetURLLoaderFactory(), this));
+ email, oauth2_service_delegate_->GetURLLoaderFactory(), this);
fetcher1->Start("foo", "bar", scope_list);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, access_token_success_count_);
@@ -1034,9 +1062,9 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, RetryBackoff) {
// Pretend that backoff has expired and try again.
oauth2_service_delegate_->backoff_entry_.SetCustomReleaseTime(
base::TimeTicks());
- std::unique_ptr<OAuth2AccessTokenFetcher> fetcher2(
+ std::unique_ptr<OAuth2AccessTokenFetcher> fetcher2 =
oauth2_service_delegate_->CreateAccessTokenFetcher(
- kEmail, oauth2_service_delegate_->GetURLLoaderFactory(), this));
+ email, oauth2_service_delegate_->GetURLLoaderFactory(), this);
fetcher2->Start("foo", "bar", scope_list);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, access_token_success_count_);
@@ -1062,9 +1090,9 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, ResetBackoff) {
EXPECT_EQ(0, access_token_failure_count_);
std::vector<std::string> scope_list;
scope_list.push_back("scope");
- std::unique_ptr<OAuth2AccessTokenFetcher> fetcher1(
+ std::unique_ptr<OAuth2AccessTokenFetcher> fetcher1 =
oauth2_service_delegate_->CreateAccessTokenFetcher(
- kEmail, oauth2_service_delegate_->GetURLLoaderFactory(), this));
+ kEmail, oauth2_service_delegate_->GetURLLoaderFactory(), this);
fetcher1->Start("foo", "bar", scope_list);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, access_token_success_count_);
@@ -1073,9 +1101,9 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, ResetBackoff) {
// Notify of network change and ensure that request now runs.
oauth2_service_delegate_->OnConnectionChanged(
network::mojom::ConnectionType::CONNECTION_WIFI);
- std::unique_ptr<OAuth2AccessTokenFetcher> fetcher2(
+ std::unique_ptr<OAuth2AccessTokenFetcher> fetcher2 =
oauth2_service_delegate_->CreateAccessTokenFetcher(
- kEmail, oauth2_service_delegate_->GetURLLoaderFactory(), this));
+ kEmail, oauth2_service_delegate_->GetURLLoaderFactory(), this);
fetcher2->Start("foo", "bar", scope_list);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, access_token_success_count_);
@@ -1122,14 +1150,17 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, ShutdownService) {
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kMirror);
EXPECT_TRUE(oauth2_service_delegate_->GetAccounts().empty());
- oauth2_service_delegate_->UpdateCredentials("account_id1", "refresh_token1");
- oauth2_service_delegate_->UpdateCredentials("account_id2", "refresh_token2");
- std::vector<std::string> accounts = oauth2_service_delegate_->GetAccounts();
+ const CoreAccountId account_id1("account_id1");
+ const CoreAccountId account_id2("account_id2");
+
+ oauth2_service_delegate_->UpdateCredentials(account_id1, "refresh_token1");
+ oauth2_service_delegate_->UpdateCredentials(account_id2, "refresh_token2");
+ std::vector<CoreAccountId> accounts = oauth2_service_delegate_->GetAccounts();
EXPECT_EQ(2u, accounts.size());
- EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id1"));
- EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id2"));
- oauth2_service_delegate_->LoadCredentials("account_id1");
- oauth2_service_delegate_->UpdateCredentials("account_id1", "refresh_token3");
+ EXPECT_EQ(1, count(accounts.begin(), accounts.end(), account_id1));
+ EXPECT_EQ(1, count(accounts.begin(), accounts.end(), account_id2));
+ oauth2_service_delegate_->LoadCredentials(account_id1);
+ oauth2_service_delegate_->UpdateCredentials(account_id1, "refresh_token3");
oauth2_service_delegate_->Shutdown();
EXPECT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
EXPECT_TRUE(oauth2_service_delegate_->refresh_tokens_.empty());
@@ -1164,7 +1195,8 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, GaiaIdMigration) {
EXPECT_EQ(1, token_available_count_);
EXPECT_EQ(1, end_batch_changes_);
- std::vector<std::string> accounts = oauth2_service_delegate_->GetAccounts();
+ std::vector<CoreAccountId> accounts =
+ oauth2_service_delegate_->GetAccounts();
EXPECT_EQ(1u, accounts.size());
EXPECT_FALSE(oauth2_service_delegate_->RefreshTokenIsAvailable(email));
@@ -1226,7 +1258,8 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
EXPECT_EQ(2, token_available_count_);
EXPECT_EQ(1, end_batch_changes_);
- std::vector<std::string> accounts = oauth2_service_delegate_->GetAccounts();
+ std::vector<CoreAccountId> accounts =
+ oauth2_service_delegate_->GetAccounts();
EXPECT_EQ(2u, accounts.size());
EXPECT_FALSE(oauth2_service_delegate_->RefreshTokenIsAvailable(email1));
@@ -1304,13 +1337,13 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
// Checks that OnAuthErrorChanged() is called during UpdateCredentials(), and
// that RefreshTokenIsAvailable() can be used at this time.
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, OnAuthErrorChanged) {
- class TokenServiceErrorObserver : public OAuth2TokenService::Observer {
+ class TokenServiceErrorObserver : public OAuth2TokenServiceObserver {
public:
explicit TokenServiceErrorObserver(
MutableProfileOAuth2TokenServiceDelegate* delegate)
: delegate_(delegate) {}
- void OnAuthErrorChanged(const std::string& account_id,
+ void OnAuthErrorChanged(const CoreAccountId& account_id,
const GoogleServiceAuthError& auth_error) override {
error_changed_ = true;
EXPECT_EQ("account_id", account_id);
@@ -1331,8 +1364,7 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, OnAuthErrorChanged) {
// Start with the SigninErrorController in error state, so that it calls
// OnErrorChanged() from AddProvider().
oauth2_service_delegate_->UpdateCredentials(
- "error_account_id",
- MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken);
+ "error_account_id", GaiaConstants::kInvalidRefreshToken);
TokenServiceErrorObserver token_service_observer(
oauth2_service_delegate_.get());
@@ -1363,8 +1395,7 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, GetAuthError) {
oauth2_service_delegate_->GetAuthError("foo"));
// Add account with invalid token.
oauth2_service_delegate_->UpdateCredentials(
- "account_id_2",
- MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken);
+ "account_id_2", GaiaConstants::kInvalidRefreshToken);
EXPECT_EQ(GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
GoogleServiceAuthError::InvalidGaiaCredentialsReason::
CREDENTIALS_REJECTED_BY_CLIENT),
@@ -1376,13 +1407,13 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, GetAuthError) {
// Regression test for https://crbug.com/824791.
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
InvalidTokenObserverCallsOrdering) {
- class TokenServiceErrorObserver : public OAuth2TokenService::Observer {
+ class TokenServiceErrorObserver : public OAuth2TokenServiceObserver {
public:
explicit TokenServiceErrorObserver(
MutableProfileOAuth2TokenServiceDelegate* delegate)
: delegate_(delegate) {}
- void OnAuthErrorChanged(const std::string& account_id,
+ void OnAuthErrorChanged(const CoreAccountId& account_id,
const GoogleServiceAuthError& auth_error) override {
error_changed_ = true;
EXPECT_FALSE(token_available_)
@@ -1391,14 +1422,14 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
CheckTokenState(account_id);
}
- void OnRefreshTokenAvailable(const std::string& account_id) override {
+ void OnRefreshTokenAvailable(const CoreAccountId& account_id) override {
token_available_ = true;
EXPECT_TRUE(error_changed_)
<< "OnAuthErrorChanged() should be called first";
CheckTokenState(account_id);
}
- void CheckTokenState(const std::string& account_id) {
+ void CheckTokenState(const CoreAccountId& account_id) {
EXPECT_EQ("account_id", account_id);
EXPECT_TRUE(delegate_->RefreshTokenIsAvailable("account_id"));
EXPECT_EQ(GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
@@ -1419,8 +1450,7 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
oauth2_service_delegate_.get());
oauth2_service_delegate_->AddObserver(&token_service_observer);
oauth2_service_delegate_->UpdateCredentials(
- "account_id",
- MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken);
+ "account_id", GaiaConstants::kInvalidRefreshToken);
EXPECT_TRUE(token_service_observer.token_available_);
EXPECT_TRUE(token_service_observer.error_changed_);
oauth2_service_delegate_->RemoveObserver(&token_service_observer);
@@ -1451,7 +1481,7 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, ClearTokensOnStartup) {
EXPECT_FALSE(
oauth2_service_delegate_->RefreshTokenIsAvailable(secondary_account));
EXPECT_STREQ(
- MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken,
+ GaiaConstants::kInvalidRefreshToken,
oauth2_service_delegate_->GetRefreshToken(primary_account).c_str());
EXPECT_EQ(GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
GoogleServiceAuthError::InvalidGaiaCredentialsReason::
@@ -1474,7 +1504,7 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, ClearTokensOnStartup) {
EXPECT_FALSE(
oauth2_service_delegate_->RefreshTokenIsAvailable(secondary_account));
EXPECT_STREQ(
- MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken,
+ GaiaConstants::kInvalidRefreshToken,
oauth2_service_delegate_->GetRefreshToken(primary_account).c_str());
EXPECT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
}
@@ -1490,7 +1520,14 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
ProfileOAuth2TokenService token_service(
&pref_service_,
CreateOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDisabled));
- token_service.AddDiagnosticsObserver(this);
+ token_service.SetRefreshTokenAvailableFromSourceCallback(
+ base::BindRepeating(&MutableProfileOAuth2TokenServiceDelegateTest::
+ OnRefreshTokenAvailableFromSource,
+ base::Unretained(this)));
+ token_service.SetRefreshTokenRevokedFromSourceCallback(
+ base::BindRepeating(&MutableProfileOAuth2TokenServiceDelegateTest::
+ OnRefreshTokenRevokedFromSource,
+ base::Unretained(this)));
{
base::HistogramTester h_tester;
@@ -1534,9 +1571,9 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
"Signin.RefreshTokenUpdated.ToValidToken.Source",
Source::kDiceResponseHandler_Signin, 1);
- token_service.UpdateCredentials(
- "account_id_2", OAuth2TokenServiceDelegate::kInvalidRefreshToken,
- Source::kDiceResponseHandler_Signin);
+ token_service.UpdateCredentials("account_id_2",
+ GaiaConstants::kInvalidRefreshToken,
+ Source::kDiceResponseHandler_Signin);
EXPECT_EQ("DiceResponseHandler::Signin",
source_for_refresh_token_available_);
h_tester.ExpectUniqueSample(
@@ -1551,7 +1588,6 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
base::RunLoop().RunUntilIdle();
}
- token_service.RemoveDiagnosticsObserver(this);
token_service.Shutdown();
}
@@ -1562,9 +1598,9 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, ExtractCredentials) {
// Create another token service
sync_preferences::TestingPrefServiceSyncable prefs;
ProfileOAuth2TokenService::RegisterProfilePrefs(prefs.registry());
- std::unique_ptr<FakeOAuth2TokenServiceDelegate> delegate =
- std::make_unique<FakeOAuth2TokenServiceDelegate>();
- FakeOAuth2TokenServiceDelegate* other_delegate = delegate.get();
+ std::unique_ptr<FakeProfileOAuth2TokenServiceDelegate> delegate =
+ std::make_unique<FakeProfileOAuth2TokenServiceDelegate>();
+ FakeProfileOAuth2TokenServiceDelegate* other_delegate = delegate.get();
ProfileOAuth2TokenService other_token_service(&prefs, std::move(delegate));
other_token_service.LoadCredentials(std::string());
diff --git a/chromium/components/signin/core/browser/oauth2_token_service_delegate_android.cc b/chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android.cc
index 386c6dc93e7..d5aad257269 100644
--- a/chromium/components/signin/core/browser/oauth2_token_service_delegate_android.cc
+++ b/chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/oauth2_token_service_delegate_android.h"
+#include "components/signin/internal/identity_manager/oauth2_token_service_delegate_android.h"
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
@@ -14,11 +14,11 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
-#include "components/signin/core/browser/account_consistency_method.h"
-#include "components/signin/core/browser/account_info.h"
+#include "components/signin/core/browser/android/jni_headers/OAuth2TokenService_jni.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/identity_manager/account_info.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/oauth2_access_token_fetcher.h"
-#include "jni/OAuth2TokenService_jni.h"
using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF8;
@@ -149,11 +149,11 @@ OAuth2TokenServiceDelegateAndroid::OAuth2TokenServiceDelegateAndroid(
if (account_tracker_service_->GetMigrationState() ==
AccountTrackerService::MIGRATION_IN_PROGRESS) {
- std::vector<std::string> accounts = GetAccounts();
+ std::vector<CoreAccountId> accounts = GetAccounts();
std::vector<CoreAccountId> accounts_id;
for (auto account_name : accounts) {
AccountInfo account_info =
- account_tracker_service_->FindAccountInfoByEmail(account_name);
+ account_tracker_service_->FindAccountInfoByEmail(account_name.id);
DCHECK(!account_info.gaia.empty());
accounts_id.push_back(account_info.gaia);
}
@@ -172,7 +172,7 @@ ScopedJavaLocalRef<jobject> OAuth2TokenServiceDelegateAndroid::GetJavaObject() {
}
bool OAuth2TokenServiceDelegateAndroid::RefreshTokenIsAvailable(
- const std::string& account_id) const {
+ const CoreAccountId& account_id) const {
DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::RefreshTokenIsAvailable"
<< " account= " << account_id;
std::string account_name = MapAccountIdToAccountName(account_id);
@@ -192,14 +192,14 @@ bool OAuth2TokenServiceDelegateAndroid::RefreshTokenIsAvailable(
}
GoogleServiceAuthError OAuth2TokenServiceDelegateAndroid::GetAuthError(
- const std::string& account_id) const {
+ const CoreAccountId& account_id) const {
auto it = errors_.find(account_id);
return (it == errors_.end()) ? GoogleServiceAuthError::AuthErrorNone()
: it->second;
}
void OAuth2TokenServiceDelegateAndroid::UpdateAuthError(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const GoogleServiceAuthError& error) {
DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::UpdateAuthError"
<< " account=" << account_id << " error=" << error.ToString();
@@ -220,7 +220,8 @@ void OAuth2TokenServiceDelegateAndroid::UpdateAuthError(
FireAuthErrorChanged(account_id, error);
}
-std::vector<std::string> OAuth2TokenServiceDelegateAndroid::GetAccounts() {
+std::vector<CoreAccountId> OAuth2TokenServiceDelegateAndroid::GetAccounts()
+ const {
std::vector<std::string> accounts;
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobjectArray> j_accounts =
@@ -228,7 +229,7 @@ std::vector<std::string> OAuth2TokenServiceDelegateAndroid::GetAccounts() {
// TODO(fgorski): We may decide to filter out some of the accounts.
base::android::AppendJavaStringArrayToStringVector(env, j_accounts,
&accounts);
- return accounts;
+ return std::vector<CoreAccountId>(accounts.begin(), accounts.end());
}
std::vector<std::string>
@@ -256,7 +257,7 @@ OAuth2TokenServiceDelegateAndroid::GetSystemAccounts() {
std::vector<CoreAccountId>
OAuth2TokenServiceDelegateAndroid::GetValidAccounts() {
std::vector<CoreAccountId> ids;
- for (const std::string& id : GetAccounts()) {
+ for (const CoreAccountId& id : GetAccounts()) {
if (ValidateAccountId(id))
ids.emplace_back(id);
}
@@ -272,9 +273,9 @@ void OAuth2TokenServiceDelegateAndroid::SetAccounts(
Java_OAuth2TokenService_setAccounts(env, java_accounts);
}
-OAuth2AccessTokenFetcher*
+std::unique_ptr<OAuth2AccessTokenFetcher>
OAuth2TokenServiceDelegateAndroid::CreateAccessTokenFetcher(
- const std::string& account_id,
+ const CoreAccountId& account_id,
scoped_refptr<network::SharedURLLoaderFactory> url_factory,
OAuth2AccessTokenConsumer* consumer) {
DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::CreateAccessTokenFetcher"
@@ -283,13 +284,13 @@ OAuth2TokenServiceDelegateAndroid::CreateAccessTokenFetcher(
std::string account_name = MapAccountIdToAccountName(account_id);
DCHECK(!account_name.empty())
<< "Cannot find account name for account id " << account_id;
- return new AndroidAccessTokenFetcher(consumer, account_name);
+ return std::make_unique<AndroidAccessTokenFetcher>(consumer, account_name);
}
-void OAuth2TokenServiceDelegateAndroid::InvalidateAccessToken(
- const std::string& account_id,
+void OAuth2TokenServiceDelegateAndroid::OnAccessTokenInvalidated(
+ const CoreAccountId& account_id,
const std::string& client_id,
- const OAuth2TokenService::ScopeSet& scopes,
+ const OAuth2AccessTokenManager::ScopeSet& scopes,
const std::string& access_token) {
ValidateAccountId(account_id);
JNIEnv* env = AttachCurrentThread();
@@ -351,11 +352,12 @@ void OAuth2TokenServiceDelegateAndroid::UpdateAccountList(
std::vector<AccountInfo> accounts_info =
account_tracker_service_->GetAccounts();
for (const AccountInfo& info : accounts_info) {
- if (!base::ContainsValue(curr_ids, info.account_id))
+ if (!base::Contains(curr_ids, info.account_id))
account_tracker_service_->RemoveAccount(info.account_id);
}
- // No need to wait for SigninManager to finish migration if not signed in.
+ // No need to wait for PrimaryAccountManager to finish migration if not signed
+ // in.
if (account_tracker_service_->GetMigrationState() ==
AccountTrackerService::MIGRATION_IN_PROGRESS &&
signed_in_account_id.empty()) {
@@ -376,13 +378,13 @@ bool OAuth2TokenServiceDelegateAndroid::UpdateAccountList(
std::vector<CoreAccountId>* refreshed_ids,
std::vector<CoreAccountId>* revoked_ids) {
bool keep_accounts = base::FeatureList::IsEnabled(signin::kMiceFeature) ||
- base::ContainsValue(curr_ids, signed_in_id);
+ base::Contains(curr_ids, signed_in_id);
if (keep_accounts) {
// Revoke token for ids that have been removed from the device.
for (const CoreAccountId& prev_id : prev_ids) {
if (prev_id == signed_in_id)
continue;
- if (!base::ContainsValue(curr_ids, prev_id)) {
+ if (!base::Contains(curr_ids, prev_id)) {
DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::UpdateAccountList:"
<< "revoked=" << prev_id;
revoked_ids->push_back(prev_id);
@@ -404,7 +406,7 @@ bool OAuth2TokenServiceDelegateAndroid::UpdateAccountList(
}
} else {
// Revoke all ids.
- if (base::ContainsValue(prev_ids, signed_in_id)) {
+ if (base::Contains(prev_ids, signed_in_id)) {
DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::UpdateAccountList:"
<< "revoked=" << signed_in_id;
revoked_ids->push_back(signed_in_id);
@@ -420,74 +422,34 @@ bool OAuth2TokenServiceDelegateAndroid::UpdateAccountList(
return keep_accounts;
}
-void OAuth2TokenServiceDelegateAndroid::FireRefreshTokenAvailable(
- const std::string& account_id) {
- DCHECK(!account_id.empty());
- DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::FireRefreshTokenAvailable id="
- << account_id;
- std::string account_name = MapAccountIdToAccountName(account_id);
- DCHECK(!account_name.empty())
- << "Cannot find account name for account id " << account_id;
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jstring> j_account_name =
- ConvertUTF8ToJavaString(env, account_name);
- Java_OAuth2TokenService_notifyRefreshTokenAvailable(env, java_ref_,
- j_account_name);
- OAuth2TokenServiceDelegate::FireRefreshTokenAvailable(account_id);
-}
-
-void OAuth2TokenServiceDelegateAndroid::FireRefreshTokenRevoked(
- const std::string& account_id) {
- DCHECK(!account_id.empty());
- DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::FireRefreshTokenRevoked id="
- << account_id;
- std::string account_name = MapAccountIdToAccountName(account_id);
- if (!account_name.empty()) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jstring> j_account_name =
- ConvertUTF8ToJavaString(env, account_name);
- Java_OAuth2TokenService_notifyRefreshTokenRevoked(env, java_ref_,
- j_account_name);
- } else {
- // Current prognosis is that we have an unmigrated account which is due for
- // deletion. Record a histogram to debug this.
- UMA_HISTOGRAM_ENUMERATION("OAuth2Login.AccountRevoked.MigrationState",
- account_tracker_service_->GetMigrationState(),
- AccountTrackerService::NUM_MIGRATION_STATES);
- bool is_email_id = account_id.find('@') != std::string::npos;
- UMA_HISTOGRAM_BOOLEAN("OAuth2Login.AccountRevoked.IsEmailId", is_email_id);
- }
- OAuth2TokenServiceDelegate::FireRefreshTokenRevoked(account_id);
-}
-
void OAuth2TokenServiceDelegateAndroid::FireRefreshTokensLoaded() {
DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::FireRefreshTokensLoaded";
-
- DCHECK_EQ(LOAD_CREDENTIALS_IN_PROGRESS, load_credentials_state());
- set_load_credentials_state(LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
-
- JNIEnv* env = AttachCurrentThread();
- Java_OAuth2TokenService_notifyRefreshTokensLoaded(env, java_ref_);
- OAuth2TokenServiceDelegate::FireRefreshTokensLoaded();
+ DCHECK_EQ(signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS,
+ load_credentials_state());
+ set_load_credentials_state(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
+ ProfileOAuth2TokenServiceDelegate::FireRefreshTokensLoaded();
}
void OAuth2TokenServiceDelegateAndroid::RevokeAllCredentials() {
DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::RevokeAllCredentials";
ScopedBatchChange batch(this);
- std::vector<std::string> accounts_to_revoke = GetAccounts();
+ std::vector<CoreAccountId> accounts_to_revoke = GetAccounts();
// Clear accounts in the token service before calling
// |FireRefreshTokenRevoked|.
SetAccounts(std::vector<CoreAccountId>());
- for (const std::string& account : accounts_to_revoke)
+ for (const CoreAccountId& account : accounts_to_revoke)
FireRefreshTokenRevoked(account);
}
void OAuth2TokenServiceDelegateAndroid::LoadCredentials(
- const std::string& primary_account_id) {
- DCHECK_EQ(LOAD_CREDENTIALS_NOT_STARTED, load_credentials_state());
- set_load_credentials_state(LOAD_CREDENTIALS_IN_PROGRESS);
+ const CoreAccountId& primary_account_id) {
+ DCHECK_EQ(signin::LoadCredentialsState::LOAD_CREDENTIALS_NOT_STARTED,
+ load_credentials_state());
+ set_load_credentials_state(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS);
if (primary_account_id.empty() &&
!base::FeatureList::IsEnabled(signin::kMiceFeature)) {
FireRefreshTokensLoaded();
@@ -502,7 +464,7 @@ void OAuth2TokenServiceDelegateAndroid::LoadCredentials(
}
void OAuth2TokenServiceDelegateAndroid::ReloadAccountsFromSystem(
- const std::string& primary_account_id) {
+ const CoreAccountId& primary_account_id) {
// UpdateAccountList() effectively synchronizes the accounts in the Token
// Service with those present at the system level.
UpdateAccountList(primary_account_id, GetValidAccounts(),
diff --git a/chromium/components/signin/core/browser/oauth2_token_service_delegate_android.h b/chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android.h
index d3603245d49..2d1eedc2f8c 100644
--- a/chromium/components/signin/core/browser/oauth2_token_service_delegate_android.h
+++ b/chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH2_TOKEN_SERVICE_DELEGATE_ANDROID_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH2_TOKEN_SERVICE_DELEGATE_ANDROID_H_
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_OAUTH2_TOKEN_SERVICE_DELEGATE_ANDROID_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_OAUTH2_TOKEN_SERVICE_DELEGATE_ANDROID_H_
#include <map>
#include <memory>
@@ -15,20 +15,20 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/time/time.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
#include "google_apis/gaia/google_service_auth_error.h"
-#include "google_apis/gaia/oauth2_token_service_delegate.h"
-// A specialization of OAuth2TokenServiceDelegate that will be returned by
-// OAuth2TokenServiceDelegateFactory for OS_ANDROID. This instance uses
+// A specialization of ProfileOAuth2TokenServiceDelegate that will be returned
+// by OAuth2TokenServiceDelegateFactory for OS_ANDROID. This instance uses
// native Android features to lookup OAuth2 tokens.
//
-// See |OAuth2TokenServiceDelegate| for usage details.
+// See |ProfileOAuth2TokenServiceDelegate| for usage details.
//
-// Note: requests should be started from the UI thread. To start a
-// request from other thread, please use OAuth2TokenServiceRequest.
-class OAuth2TokenServiceDelegateAndroid : public OAuth2TokenServiceDelegate {
+// Note: requests should be started from the UI thread.
+class OAuth2TokenServiceDelegateAndroid
+ : public ProfileOAuth2TokenServiceDelegate {
public:
OAuth2TokenServiceDelegateAndroid(
AccountTrackerService* account_tracker_service);
@@ -47,13 +47,13 @@ class OAuth2TokenServiceDelegateAndroid : public OAuth2TokenServiceDelegate {
disable_interaction_with_system_accounts_ = true;
}
- // OAuth2TokenServiceDelegate overrides:
- bool RefreshTokenIsAvailable(const std::string& account_id) const override;
+ // ProfileOAuth2TokenServiceDelegate overrides:
+ bool RefreshTokenIsAvailable(const CoreAccountId& account_id) const override;
GoogleServiceAuthError GetAuthError(
- const std::string& account_id) const override;
- void UpdateAuthError(const std::string& account_id,
+ const CoreAccountId& account_id) const override;
+ void UpdateAuthError(const CoreAccountId& account_id,
const GoogleServiceAuthError& error) override;
- std::vector<std::string> GetAccounts() override;
+ std::vector<CoreAccountId> GetAccounts() const override;
void UpdateAccountList(
JNIEnv* env,
@@ -72,27 +72,25 @@ class OAuth2TokenServiceDelegateAndroid : public OAuth2TokenServiceDelegate {
// OA2TService aware accounts.
void RevokeAllCredentials() override;
- void LoadCredentials(const std::string& primary_account_id) override;
+ void LoadCredentials(const CoreAccountId& primary_account_id) override;
- void ReloadAccountsFromSystem(const std::string& primary_account_id) override;
+ void ReloadAccountsFromSystem(
+ const CoreAccountId& primary_account_id) override;
protected:
- OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
- const std::string& account_id,
+ std::unique_ptr<OAuth2AccessTokenFetcher> CreateAccessTokenFetcher(
+ const CoreAccountId& account_id,
scoped_refptr<network::SharedURLLoaderFactory> url_factory,
OAuth2AccessTokenConsumer* consumer) override;
- // Overridden from OAuth2TokenService to intercept token fetch requests and
- // redirect them to the Account Manager.
- void InvalidateAccessToken(const std::string& account_id,
- const std::string& client_id,
- const OAuth2TokenService::ScopeSet& scopes,
- const std::string& access_token) override;
-
- // Called to notify observers when a refresh token is available.
- void FireRefreshTokenAvailable(const std::string& account_id) override;
- // Called to notify observers when a refresh token has been revoked.
- void FireRefreshTokenRevoked(const std::string& account_id) override;
+ // Overridden from ProfileOAuth2TokenServiceDelegate to intercept token fetch
+ // requests and redirect them to the Account Manager.
+ void OnAccessTokenInvalidated(
+ const CoreAccountId& account_id,
+ const std::string& client_id,
+ const OAuth2AccessTokenManager::ScopeSet& scopes,
+ const std::string& access_token) override;
+
// Called to notify observers when refresh tokans have been loaded.
void FireRefreshTokensLoaded() override;
@@ -128,7 +126,7 @@ class OAuth2TokenServiceDelegateAndroid : public OAuth2TokenServiceDelegate {
base::android::ScopedJavaGlobalRef<jobject> java_ref_;
// Maps account_id to the last error for that account.
- std::map<std::string, GoogleServiceAuthError> errors_;
+ std::map<CoreAccountId, GoogleServiceAuthError> errors_;
AccountTrackerService* account_tracker_service_;
RefreshTokenLoadStatus fire_refresh_token_loaded_;
@@ -139,4 +137,4 @@ class OAuth2TokenServiceDelegateAndroid : public OAuth2TokenServiceDelegate {
DISALLOW_COPY_AND_ASSIGN(OAuth2TokenServiceDelegateAndroid);
};
-#endif // CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_DELEGATE_ANDROID_H_
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_OAUTH2_TOKEN_SERVICE_DELEGATE_ANDROID_H_
diff --git a/chromium/components/signin/core/browser/oauth2_token_service_delegate_android_unittest.cc b/chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android_unittest.cc
index 6fe207ad174..731a71c9955 100644
--- a/chromium/components/signin/core/browser/oauth2_token_service_delegate_android_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/oauth2_token_service_delegate_android.h"
+#include "components/signin/internal/identity_manager/oauth2_token_service_delegate_android.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -27,10 +27,10 @@ class OAuth2TokenServiceDelegateAndroidForTest
MOCK_METHOD1(SetAccounts, void(const std::vector<CoreAccountId>&));
};
-class TestObserver : public OAuth2TokenService::Observer {
+class TestObserver : public OAuth2TokenServiceObserver {
public:
- MOCK_METHOD1(OnRefreshTokenAvailable, void(const std::string&));
- MOCK_METHOD1(OnRefreshTokenRevoked, void(const std::string&));
+ MOCK_METHOD1(OnRefreshTokenAvailable, void(const CoreAccountId&));
+ MOCK_METHOD1(OnRefreshTokenRevoked, void(const CoreAccountId&));
MOCK_METHOD0(OnRefreshTokensLoaded, void());
};
} // namespace
@@ -120,7 +120,7 @@ TEST_F(OAuth2TokenServiceDelegateAndroidTest,
.InSequence(seq)
.WillOnce(Return());
// Stored account from |GetAccounts| must fire a revoked event
- EXPECT_CALL(observer_, OnRefreshTokenRevoked(account1_.account_id.id))
+ EXPECT_CALL(observer_, OnRefreshTokenRevoked(account1_.account_id))
.InSequence(seq)
.WillOnce(Return());
@@ -137,7 +137,7 @@ TEST_F(OAuth2TokenServiceDelegateAndroidTest,
SetAccounts(std::vector<CoreAccountId>({account1_.account_id})))
.InSequence(seq)
.WillOnce(Return());
- EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id.id))
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id))
.InSequence(seq)
.WillOnce(Return());
@@ -154,7 +154,7 @@ TEST_F(OAuth2TokenServiceDelegateAndroidTest,
SetAccounts(std::vector<CoreAccountId>({account1_.account_id})))
.InSequence(seq)
.WillOnce(Return());
- EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id.id))
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id))
.InSequence(seq)
.WillOnce(Return());
@@ -172,10 +172,10 @@ TEST_F(OAuth2TokenServiceDelegateAndroidTest,
.InSequence(seq)
.WillOnce(Return());
// Previously stored account is removed, new account is available
- EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id.id))
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id))
.InSequence(seq)
.WillOnce(Return());
- EXPECT_CALL(observer_, OnRefreshTokenRevoked(account2_.account_id.id))
+ EXPECT_CALL(observer_, OnRefreshTokenRevoked(account2_.account_id))
.InSequence(seq)
.WillOnce(Return());
@@ -191,7 +191,7 @@ TEST_F(OAuth2TokenServiceDelegateAndroidTest,
EXPECT_CALL(*delegate_, SetAccounts(kEmptyVector))
.InSequence(seq)
.WillOnce(Return());
- EXPECT_CALL(observer_, OnRefreshTokenRevoked(account1_.account_id.id))
+ EXPECT_CALL(observer_, OnRefreshTokenRevoked(account1_.account_id))
.InSequence(seq)
.WillOnce(Return());
@@ -218,7 +218,7 @@ TEST_F(OAuth2TokenServiceDelegateAndroidTest,
EXPECT_CALL(*delegate_, SetAccounts(kEmptyVector))
.InSequence(seq)
.WillOnce(Return());
- EXPECT_CALL(observer_, OnRefreshTokenRevoked(account1_.account_id.id))
+ EXPECT_CALL(observer_, OnRefreshTokenRevoked(account1_.account_id))
.InSequence(seq)
.WillOnce(Return());
@@ -236,10 +236,10 @@ TEST_F(OAuth2TokenServiceDelegateAndroidTest,
.InSequence(seq)
.WillOnce(Return());
// OnRefreshTokenAvailable fired, signed in account should go first.
- EXPECT_CALL(observer_, OnRefreshTokenAvailable(account2_.account_id.id))
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account2_.account_id))
.InSequence(seq)
.WillOnce(Return());
- EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id.id))
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id))
.InSequence(seq)
.WillOnce(Return());
@@ -257,10 +257,10 @@ TEST_F(OAuth2TokenServiceDelegateAndroidTest,
.InSequence(seq)
.WillOnce(Return());
// OnRefreshTokenAvailable fired, signed in account should go first.
- EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id.id))
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id))
.InSequence(seq)
.WillOnce(Return());
- EXPECT_CALL(observer_, OnRefreshTokenAvailable(account2_.account_id.id))
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account2_.account_id))
.InSequence(seq)
.WillOnce(Return());
delegate_->UpdateAccountList(account1_.account_id, {account2_.account_id},
@@ -277,10 +277,10 @@ TEST_F(OAuth2TokenServiceDelegateAndroidTest,
.InSequence(seq)
.WillOnce(Return());
// OnRefreshTokenAvailable fired, signed in account should go first.
- EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id.id))
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id))
.InSequence(seq)
.WillOnce(Return());
- EXPECT_CALL(observer_, OnRefreshTokenRevoked(account2_.account_id.id))
+ EXPECT_CALL(observer_, OnRefreshTokenRevoked(account2_.account_id))
.InSequence(seq)
.WillOnce(Return());
diff --git a/chromium/components/signin/core/browser/oauth_multilogin_helper.cc b/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.cc
index ab38dc09254..e5a314674d9 100644
--- a/chromium/components/signin/core/browser/oauth_multilogin_helper.cc
+++ b/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/oauth_multilogin_helper.h"
+#include "components/signin/internal/identity_manager/oauth_multilogin_helper.h"
#include <algorithm>
#include <utility>
@@ -12,9 +12,9 @@
#include "base/callback.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
-#include "components/signin/core/browser/oauth_multilogin_token_fetcher.h"
-#include "components/signin/core/browser/set_accounts_in_cookie_result.h"
-#include "components/signin/core/browser/signin_client.h"
+#include "components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.h"
+#include "components/signin/public/base/signin_client.h"
+#include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth_multilogin_result.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
@@ -25,41 +25,51 @@ namespace {
constexpr int kMaxFetcherRetries = 3;
std::string FindTokenForAccount(
- const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>& token_id_pairs,
- const std::string& account_id) {
- for (auto it = token_id_pairs.cbegin(); it != token_id_pairs.cend(); ++it) {
- if (account_id == it->gaia_id_)
- return it->token_;
+ const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>&
+ gaia_id_token_pairs,
+ const std::string& gaia_id) {
+ for (const auto& gaia_id_token : gaia_id_token_pairs) {
+ if (gaia_id == gaia_id_token.gaia_id_)
+ return gaia_id_token.token_;
}
return std::string();
}
+CoreAccountId FindAccountIdForGaiaId(
+ const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair>& accounts,
+ const std::string& gaia_id) {
+ for (const auto& account : accounts) {
+ if (gaia_id == account.second)
+ return account.first;
+ }
+ return CoreAccountId();
+}
+
} // namespace
namespace signin {
OAuthMultiloginHelper::OAuthMultiloginHelper(
SigninClient* signin_client,
- OAuth2TokenService* token_service,
- const std::vector<std::string>& account_ids,
+ ProfileOAuth2TokenService* token_service,
+ const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair>& accounts,
const std::string& external_cc_result,
- base::OnceCallback<void(signin::SetAccountsInCookieResult)> callback)
+ base::OnceCallback<void(SetAccountsInCookieResult)> callback)
: signin_client_(signin_client),
token_service_(token_service),
- account_ids_(account_ids),
+ accounts_(accounts),
external_cc_result_(external_cc_result),
- callback_(std::move(callback)),
- weak_ptr_factory_(this) {
+ callback_(std::move(callback)) {
DCHECK(signin_client_);
DCHECK(token_service_);
- DCHECK(!account_ids_.empty());
+ DCHECK(!accounts_.empty());
DCHECK(callback_);
#ifndef NDEBUG
// Check that there is no duplicate accounts.
- std::set<std::string> accounts_no_duplicates(account_ids_.begin(),
- account_ids_.end());
- DCHECK_EQ(account_ids_.size(), accounts_no_duplicates.size());
+ std::set<GaiaCookieManagerService::AccountIdGaiaIdPair>
+ accounts_no_duplicates(accounts_.begin(), accounts_.end());
+ DCHECK_EQ(accounts_.size(), accounts_no_duplicates.size());
#endif
StartFetchingTokens();
@@ -69,9 +79,13 @@ OAuthMultiloginHelper::~OAuthMultiloginHelper() = default;
void OAuthMultiloginHelper::StartFetchingTokens() {
DCHECK(!token_fetcher_);
- DCHECK(token_id_pairs_.empty());
- token_fetcher_ = std::make_unique<signin::OAuthMultiloginTokenFetcher>(
- signin_client_, token_service_, account_ids_,
+ DCHECK(gaia_id_token_pairs_.empty());
+ std::vector<CoreAccountId> account_ids;
+ for (const auto& account : accounts_)
+ account_ids.push_back(account.first);
+
+ token_fetcher_ = std::make_unique<OAuthMultiloginTokenFetcher>(
+ signin_client_, token_service_, account_ids,
base::BindOnce(&OAuthMultiloginHelper::OnAccessTokensSuccess,
base::Unretained(this)),
base::BindOnce(&OAuthMultiloginHelper::OnAccessTokensFailure,
@@ -79,10 +93,17 @@ void OAuthMultiloginHelper::StartFetchingTokens() {
}
void OAuthMultiloginHelper::OnAccessTokensSuccess(
- const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>& token_id_pairs) {
- DCHECK(token_id_pairs_.empty());
- token_id_pairs_ = token_id_pairs;
- DCHECK_EQ(token_id_pairs_.size(), account_ids_.size());
+ const std::vector<OAuthMultiloginTokenFetcher::AccountIdTokenPair>&
+ account_token_pairs) {
+ DCHECK(gaia_id_token_pairs_.empty());
+ for (size_t index = 0; index < accounts_.size(); index++) {
+ // OAuthMultiloginTokenFetcher should return the tokens in the same order
+ // as the account_ids that was passed to it.
+ DCHECK_EQ(accounts_[index].first, account_token_pairs[index].account_id);
+ gaia_id_token_pairs_.emplace_back(accounts_[index].second,
+ account_token_pairs[index].token);
+ }
+ DCHECK_EQ(gaia_id_token_pairs_.size(), accounts_.size());
token_fetcher_.reset();
signin_client_->DelayNetworkCall(
@@ -93,43 +114,45 @@ void OAuthMultiloginHelper::OnAccessTokensSuccess(
void OAuthMultiloginHelper::OnAccessTokensFailure(
const GoogleServiceAuthError& error) {
token_fetcher_.reset();
- std::move(callback_).Run(
- error.IsTransientError()
- ? signin::SetAccountsInCookieResult::kTransientError
- : signin::SetAccountsInCookieResult::kPersistentError);
+ std::move(callback_).Run(error.IsTransientError()
+ ? SetAccountsInCookieResult::kTransientError
+ : SetAccountsInCookieResult::kPersistentError);
// Do not add anything below this line, because this may be deleted.
}
void OAuthMultiloginHelper::StartFetchingMultiLogin() {
- DCHECK_EQ(token_id_pairs_.size(), account_ids_.size());
+ DCHECK_EQ(gaia_id_token_pairs_.size(), accounts_.size());
gaia_auth_fetcher_ =
signin_client_->CreateGaiaAuthFetcher(this, gaia::GaiaSource::kChrome);
- gaia_auth_fetcher_->StartOAuthMultilogin(token_id_pairs_,
+ gaia_auth_fetcher_->StartOAuthMultilogin(gaia_id_token_pairs_,
external_cc_result_);
}
void OAuthMultiloginHelper::OnOAuthMultiloginFinished(
const OAuthMultiloginResult& result) {
if (result.status() == OAuthMultiloginResponseStatus::kOk) {
+ std::vector<std::string> account_ids;
+ for (const auto& account : accounts_)
+ account_ids.push_back(account.first.id);
VLOG(1) << "Multilogin successful accounts="
- << base::JoinString(account_ids_, " ");
+ << base::JoinString(account_ids, " ");
StartSettingCookies(result);
return;
}
// If Gaia responded with kInvalidTokens, we have to mark tokens as invalid.
if (result.status() == OAuthMultiloginResponseStatus::kInvalidTokens) {
- for (const std::string& failed_account_id : result.failed_accounts()) {
+ for (const std::string& failed_gaia_id : result.failed_gaia_ids()) {
std::string failed_token =
- FindTokenForAccount(token_id_pairs_, failed_account_id);
+ FindTokenForAccount(gaia_id_token_pairs_, failed_gaia_id);
if (failed_token.empty()) {
LOG(ERROR)
<< "Unexpected failed token for account not present in request: "
- << failed_account_id;
+ << failed_gaia_id;
continue;
}
- token_service_->InvalidateTokenForMultilogin(failed_account_id,
- failed_token);
+ token_service_->InvalidateTokenForMultilogin(
+ FindAccountIdForGaiaId(accounts_, failed_gaia_id), failed_token);
}
}
@@ -138,13 +161,13 @@ void OAuthMultiloginHelper::OnOAuthMultiloginFinished(
result.status() == OAuthMultiloginResponseStatus::kRetry;
if (is_transient_error && ++fetcher_retries_ < kMaxFetcherRetries) {
- token_id_pairs_.clear();
+ gaia_id_token_pairs_.clear();
StartFetchingTokens();
return;
}
- std::move(callback_).Run(
- is_transient_error ? signin::SetAccountsInCookieResult::kTransientError
- : signin::SetAccountsInCookieResult::kPersistentError);
+ std::move(callback_).Run(is_transient_error
+ ? SetAccountsInCookieResult::kTransientError
+ : SetAccountsInCookieResult::kPersistentError);
// Do not add anything below this line, because this may be deleted.
}
@@ -195,7 +218,7 @@ void OAuthMultiloginHelper::OnCookieSet(
}
UMA_HISTOGRAM_BOOLEAN("Signin.SetCookieSuccess", success);
if (cookies_to_set_.empty())
- std::move(callback_).Run(signin::SetAccountsInCookieResult::kSuccess);
+ std::move(callback_).Run(SetAccountsInCookieResult::kSuccess);
// Do not add anything below this line, because this may be deleted.
}
diff --git a/chromium/components/signin/core/browser/oauth_multilogin_helper.h b/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.h
index 69064a9f0b0..e91721eaff8 100644
--- a/chromium/components/signin/core/browser/oauth_multilogin_helper.h
+++ b/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH_MULTILOGIN_HELPER_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH_MULTILOGIN_HELPER_H_
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_OAUTH_MULTILOGIN_HELPER_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_OAUTH_MULTILOGIN_HELPER_H_
#include <memory>
#include <set>
@@ -13,18 +13,20 @@
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h"
+#include "components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.h"
+#include "google_apis/gaia/core_account_id.h"
#include "google_apis/gaia/gaia_auth_consumer.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
class GaiaAuthFetcher;
class GoogleServiceAuthError;
-class OAuth2TokenService;
+class ProfileOAuth2TokenService;
class SigninClient;
namespace signin {
-class OAuthMultiloginTokenFetcher;
enum class SetAccountsInCookieResult;
// This is a helper class that drives the OAuth multilogin process.
@@ -37,10 +39,11 @@ class OAuthMultiloginHelper : public GaiaAuthConsumer {
public:
OAuthMultiloginHelper(
SigninClient* signin_client,
- OAuth2TokenService* token_service,
- const std::vector<std::string>& account_ids,
+ ProfileOAuth2TokenService* token_service,
+ const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair>&
+ accounts,
const std::string& external_cc_result,
- base::OnceCallback<void(signin::SetAccountsInCookieResult)> callback);
+ base::OnceCallback<void(SetAccountsInCookieResult)> callback);
~OAuthMultiloginHelper() override;
@@ -50,8 +53,8 @@ class OAuthMultiloginHelper : public GaiaAuthConsumer {
// Callbacks for OAuthMultiloginTokenFetcher.
void OnAccessTokensSuccess(
- const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>&
- token_id_pairs);
+ const std::vector<OAuthMultiloginTokenFetcher::AccountIdTokenPair>&
+ account_token_pairs);
void OnAccessTokensFailure(const GoogleServiceAuthError& error);
// Actual call to the multilogin endpoint.
@@ -69,18 +72,18 @@ class OAuthMultiloginHelper : public GaiaAuthConsumer {
net::CanonicalCookie::CookieInclusionStatus status);
SigninClient* signin_client_;
- OAuth2TokenService* token_service_;
+ ProfileOAuth2TokenService* token_service_;
int fetcher_retries_ = 0;
// Account ids to set in the cookie.
- const std::vector<std::string> account_ids_;
+ const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair> accounts_;
// See GaiaCookieManagerService::ExternalCcResultFetcher for details.
const std::string external_cc_result_;
// Access tokens, in the same order as the account ids.
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> token_id_pairs_;
+ std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> gaia_id_token_pairs_;
- base::OnceCallback<void(signin::SetAccountsInCookieResult)> callback_;
+ base::OnceCallback<void(SetAccountsInCookieResult)> callback_;
std::unique_ptr<GaiaAuthFetcher> gaia_auth_fetcher_;
std::unique_ptr<OAuthMultiloginTokenFetcher> token_fetcher_;
@@ -88,11 +91,11 @@ class OAuthMultiloginHelper : public GaiaAuthConsumer {
// cookie jar.
std::set<std::pair<std::string, std::string>> cookies_to_set_;
- base::WeakPtrFactory<OAuthMultiloginHelper> weak_ptr_factory_;
+ base::WeakPtrFactory<OAuthMultiloginHelper> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(OAuthMultiloginHelper);
};
} // namespace signin
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH_MULTILOGIN_HELPER_H_
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_OAUTH_MULTILOGIN_HELPER_H_
diff --git a/chromium/components/signin/core/browser/oauth_multilogin_helper_unittest.cc b/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc
index 8c19a4b7009..9ad5f88d61e 100644
--- a/chromium/components/signin/core/browser/oauth_multilogin_helper_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc
@@ -2,15 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/oauth_multilogin_helper.h"
+#include "components/signin/internal/identity_manager/oauth_multilogin_helper.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/test/scoped_task_environment.h"
-#include "components/signin/core/browser/set_accounts_in_cookie_result.h"
-#include "components/signin/core/browser/test_signin_client.h"
-#include "google_apis/gaia/fake_oauth2_token_service.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h"
+#include "components/signin/public/base/test_signin_client.h"
+#include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h"
#include "google_apis/gaia/gaia_urls.h"
#include "services/network/test/test_cookie_manager.h"
#include "services/network/test/test_url_loader_factory.h"
@@ -21,8 +22,10 @@ namespace signin {
namespace {
-const char kAccountId[] = "account_id_1";
-const char kAccountId2[] = "account_id_2";
+const CoreAccountId kAccountId("account_id_1");
+const CoreAccountId kAccountId2("account_id_2");
+const char kGaiaId[] = "gaia_id_1";
+const char kGaiaId2[] = "gaia_id_2";
const char kAccessToken[] = "access_token_1";
const char kAccessToken2[] = "access_token_2";
@@ -119,8 +122,8 @@ const char kMultiloginInvalidTokenResponse[] =
{
"status": "INVALID_TOKENS",
"failed_accounts": [
- { "obfuscated_id": "account_id_1", "status": "RECOVERABLE" },
- { "obfuscated_id": "account_id_2", "status": "OK" }
+ { "obfuscated_id": "gaia_id_1", "status": "RECOVERABLE" },
+ { "obfuscated_id": "gaia_id_2", "status": "OK" }
]
}
)";
@@ -149,17 +152,21 @@ class MockCookieManager
SetCanonicalCookieCallback callback));
};
-class MockTokenService : public FakeOAuth2TokenService {
+class MockTokenService : public FakeProfileOAuth2TokenService {
public:
+ MockTokenService(PrefService* prefs) : FakeProfileOAuth2TokenService(prefs) {}
+
MOCK_METHOD2(InvalidateTokenForMultilogin,
- void(const std::string& account_id, const std::string& token));
+ void(const CoreAccountId& account_id, const std::string& token));
};
} // namespace
class OAuthMultiloginHelperTest : public testing::Test {
public:
- OAuthMultiloginHelperTest() : test_signin_client_(/*prefs=*/nullptr) {
+ OAuthMultiloginHelperTest()
+ : test_signin_client_(&pref_service_),
+ mock_token_service_(&pref_service_) {
std::unique_ptr<MockCookieManager> cookie_manager =
std::make_unique<MockCookieManager>();
mock_cookie_manager_ = cookie_manager.get();
@@ -169,17 +176,19 @@ class OAuthMultiloginHelperTest : public testing::Test {
~OAuthMultiloginHelperTest() override = default;
std::unique_ptr<OAuthMultiloginHelper> CreateHelper(
- const std::vector<std::string> account_ids) {
+ const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair>
+ accounts) {
return std::make_unique<OAuthMultiloginHelper>(
- &test_signin_client_, token_service(), account_ids, std::string(),
+ &test_signin_client_, token_service(), accounts, std::string(),
base::BindOnce(&OAuthMultiloginHelperTest::OnOAuthMultiloginFinished,
base::Unretained(this)));
}
std::unique_ptr<OAuthMultiloginHelper> CreateHelperWithExternalCcResult(
- const std::vector<std::string> account_ids) {
+ const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair>
+ accounts) {
return std::make_unique<OAuthMultiloginHelper>(
- &test_signin_client_, token_service(), account_ids, kExternalCcResult,
+ &test_signin_client_, token_service(), accounts, kExternalCcResult,
base::BindOnce(&OAuthMultiloginHelperTest::OnOAuthMultiloginFinished,
base::Unretained(this)));
}
@@ -202,7 +211,7 @@ class OAuthMultiloginHelperTest : public testing::Test {
MockTokenService* token_service() { return &mock_token_service_; }
protected:
- void OnOAuthMultiloginFinished(signin::SetAccountsInCookieResult result) {
+ void OnOAuthMultiloginFinished(SetAccountsInCookieResult result) {
DCHECK(!callback_called_);
callback_called_ = true;
result_ = result;
@@ -211,8 +220,9 @@ class OAuthMultiloginHelperTest : public testing::Test {
base::test::ScopedTaskEnvironment scoped_task_environment_;
bool callback_called_ = false;
- signin::SetAccountsInCookieResult result_;
+ SetAccountsInCookieResult result_;
+ TestingPrefServiceSimple pref_service_;
MockCookieManager* mock_cookie_manager_; // Owned by test_signin_client_
TestSigninClient test_signin_client_;
MockTokenService mock_token_service_;
@@ -220,8 +230,9 @@ class OAuthMultiloginHelperTest : public testing::Test {
// Everything succeeds.
TEST_F(OAuthMultiloginHelperTest, Success) {
- token_service()->AddAccount(kAccountId);
- std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId});
+ token_service()->UpdateCredentials(kAccountId, "refresh_token");
+ std::unique_ptr<OAuthMultiloginHelper> helper =
+ CreateHelper({{kAccountId, kGaiaId}});
// Configure mock cookie manager:
// - check that the cookie is the expected one
@@ -243,13 +254,14 @@ TEST_F(OAuthMultiloginHelperTest, Success) {
url_loader()->AddResponse(multilogin_url(), kMultiloginSuccessResponse);
EXPECT_FALSE(url_loader()->IsPending(multilogin_url()));
EXPECT_TRUE(callback_called_);
- EXPECT_EQ(signin::SetAccountsInCookieResult::kSuccess, result_);
+ EXPECT_EQ(SetAccountsInCookieResult::kSuccess, result_);
}
// Multiple cookies in the multilogin response.
TEST_F(OAuthMultiloginHelperTest, MultipleCookies) {
- token_service()->AddAccount(kAccountId);
- std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId});
+ token_service()->UpdateCredentials(kAccountId, "refresh_token");
+ std::unique_ptr<OAuthMultiloginHelper> helper =
+ CreateHelper({{kAccountId, kGaiaId}});
// Configure mock cookie manager:
// - check that the cookie is the expected one
@@ -277,14 +289,14 @@ TEST_F(OAuthMultiloginHelperTest, MultipleCookies) {
kMultiloginSuccessResponseTwoCookies);
EXPECT_FALSE(url_loader()->IsPending(multilogin_url()));
EXPECT_TRUE(callback_called_);
- EXPECT_EQ(signin::SetAccountsInCookieResult::kSuccess, result_);
+ EXPECT_EQ(SetAccountsInCookieResult::kSuccess, result_);
}
// Multiple cookies in the multilogin response.
TEST_F(OAuthMultiloginHelperTest, SuccessWithExternalCcResult) {
- token_service()->AddAccount(kAccountId);
+ token_service()->UpdateCredentials(kAccountId, "refresh_token");
std::unique_ptr<OAuthMultiloginHelper> helper =
- CreateHelperWithExternalCcResult({kAccountId});
+ CreateHelperWithExternalCcResult({{kAccountId, kGaiaId}});
// Configure mock cookie manager:
// - check that the cookie is the expected one
@@ -314,25 +326,27 @@ TEST_F(OAuthMultiloginHelperTest, SuccessWithExternalCcResult) {
EXPECT_FALSE(
url_loader()->IsPending(multilogin_url_with_external_cc_result()));
EXPECT_TRUE(callback_called_);
- EXPECT_EQ(signin::SetAccountsInCookieResult::kSuccess, result_);
+ EXPECT_EQ(SetAccountsInCookieResult::kSuccess, result_);
}
// Failure to get the access token.
TEST_F(OAuthMultiloginHelperTest, OneAccountAccessTokenFailure) {
- token_service()->AddAccount(kAccountId);
- std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId});
+ token_service()->UpdateCredentials(kAccountId, "refresh_token");
+ std::unique_ptr<OAuthMultiloginHelper> helper =
+ CreateHelper({{kAccountId, kGaiaId}});
token_service()->IssueErrorForAllPendingRequestsForAccount(
kAccountId,
GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
EXPECT_TRUE(callback_called_);
- EXPECT_EQ(signin::SetAccountsInCookieResult::kPersistentError, result_);
+ EXPECT_EQ(SetAccountsInCookieResult::kPersistentError, result_);
}
// Retry on transient errors in the multilogin call.
TEST_F(OAuthMultiloginHelperTest, OneAccountTransientMultiloginError) {
- token_service()->AddAccount(kAccountId);
- std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId});
+ token_service()->UpdateCredentials(kAccountId, "refresh_token");
+ std::unique_ptr<OAuthMultiloginHelper> helper =
+ CreateHelper({{kAccountId, kGaiaId}});
// Configure mock cookie manager:
// - check that the cookie is the expected one
@@ -361,14 +375,15 @@ TEST_F(OAuthMultiloginHelperTest, OneAccountTransientMultiloginError) {
url_loader()->AddResponse(multilogin_url(), kMultiloginSuccessResponse);
EXPECT_FALSE(url_loader()->IsPending(multilogin_url()));
EXPECT_TRUE(callback_called_);
- EXPECT_EQ(signin::SetAccountsInCookieResult::kSuccess, result_);
+ EXPECT_EQ(SetAccountsInCookieResult::kSuccess, result_);
}
// Stop retrying after too many transient errors in the multilogin call.
TEST_F(OAuthMultiloginHelperTest,
OneAccountTransientMultiloginErrorMaxRetries) {
- token_service()->AddAccount(kAccountId);
- std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId});
+ token_service()->UpdateCredentials(kAccountId, "refresh_token");
+ std::unique_ptr<OAuthMultiloginHelper> helper =
+ CreateHelper({{kAccountId, kGaiaId}});
// Issue access token.
OAuth2AccessTokenConsumer::TokenResponse success_response;
@@ -385,13 +400,14 @@ TEST_F(OAuthMultiloginHelperTest,
// Failure after exceeding the maximum number of retries.
EXPECT_TRUE(callback_called_);
- EXPECT_EQ(signin::SetAccountsInCookieResult::kTransientError, result_);
+ EXPECT_EQ(SetAccountsInCookieResult::kTransientError, result_);
}
// Persistent error in the multilogin call.
TEST_F(OAuthMultiloginHelperTest, OneAccountPersistentMultiloginError) {
- token_service()->AddAccount(kAccountId);
- std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId});
+ token_service()->UpdateCredentials(kAccountId, "refresh_token");
+ std::unique_ptr<OAuthMultiloginHelper> helper =
+ CreateHelper({{kAccountId, kGaiaId}});
// Issue access token.
OAuth2AccessTokenConsumer::TokenResponse success_response;
@@ -404,15 +420,15 @@ TEST_F(OAuthMultiloginHelperTest, OneAccountPersistentMultiloginError) {
url_loader()->AddResponse(multilogin_url(), "blah"); // Unexpected response.
EXPECT_FALSE(url_loader()->IsPending(multilogin_url()));
EXPECT_TRUE(callback_called_);
- EXPECT_EQ(signin::SetAccountsInCookieResult::kPersistentError, result_);
+ EXPECT_EQ(SetAccountsInCookieResult::kPersistentError, result_);
}
// Retry on "invalid token" in the multilogin response.
TEST_F(OAuthMultiloginHelperTest, InvalidTokenError) {
- token_service()->AddAccount(kAccountId);
- token_service()->AddAccount(kAccountId2);
+ token_service()->UpdateCredentials(kAccountId, "refresh_token");
+ token_service()->UpdateCredentials(kAccountId2, "refresh_token");
std::unique_ptr<OAuthMultiloginHelper> helper =
- CreateHelper({kAccountId, kAccountId2});
+ CreateHelper({{kAccountId, kGaiaId}, {kAccountId2, kGaiaId2}});
// Configure mock cookie manager:
// - check that the cookie is the expected one
@@ -452,15 +468,15 @@ TEST_F(OAuthMultiloginHelperTest, InvalidTokenError) {
url_loader()->AddResponse(multilogin_url(), kMultiloginSuccessResponse);
EXPECT_FALSE(url_loader()->IsPending(multilogin_url()));
EXPECT_TRUE(callback_called_);
- EXPECT_EQ(signin::SetAccountsInCookieResult::kSuccess, result_);
+ EXPECT_EQ(SetAccountsInCookieResult::kSuccess, result_);
}
// Retry on "invalid token" in the multilogin response.
TEST_F(OAuthMultiloginHelperTest, InvalidTokenErrorMaxRetries) {
- token_service()->AddAccount(kAccountId);
- token_service()->AddAccount(kAccountId2);
+ token_service()->UpdateCredentials(kAccountId, "refresh_token");
+ token_service()->UpdateCredentials(kAccountId2, "refresh_token");
std::unique_ptr<OAuthMultiloginHelper> helper =
- CreateHelper({kAccountId, kAccountId2});
+ CreateHelper({{kAccountId, kGaiaId}, {kAccountId2, kGaiaId2}});
// The failed access token should be invalidated.
EXPECT_CALL(*token_service(),
@@ -489,7 +505,7 @@ TEST_F(OAuthMultiloginHelperTest, InvalidTokenErrorMaxRetries) {
// The maximum number of retries is reached, fail.
EXPECT_FALSE(url_loader()->IsPending(multilogin_url()));
EXPECT_TRUE(callback_called_);
- EXPECT_EQ(signin::SetAccountsInCookieResult::kTransientError, result_);
+ EXPECT_EQ(SetAccountsInCookieResult::kTransientError, result_);
}
} // namespace signin
diff --git a/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher.cc b/chromium/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.cc
index d01a50aa468..7ee1cecab12 100644
--- a/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher.cc
+++ b/chromium/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/oauth_multilogin_token_fetcher.h"
+#include "components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.h"
#include <algorithm>
#include <set>
@@ -12,7 +12,8 @@
#include "base/callback.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
-#include "components/signin/core/browser/signin_client.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/public/base/signin_client.h"
namespace {
@@ -27,17 +28,16 @@ namespace signin {
OAuthMultiloginTokenFetcher::OAuthMultiloginTokenFetcher(
SigninClient* signin_client,
- OAuth2TokenService* token_service,
- const std::vector<std::string>& account_ids,
+ ProfileOAuth2TokenService* token_service,
+ const std::vector<CoreAccountId>& account_ids,
SuccessCallback success_callback,
FailureCallback failure_callback)
- : OAuth2TokenService::Consumer("oauth_multilogin_token_fetcher"),
+ : OAuth2AccessTokenManager::Consumer("oauth_multilogin_token_fetcher"),
signin_client_(signin_client),
token_service_(token_service),
account_ids_(account_ids),
success_callback_(std::move(success_callback)),
- failure_callback_(std::move(failure_callback)),
- weak_ptr_factory_(this) {
+ failure_callback_(std::move(failure_callback)) {
DCHECK(signin_client_);
DCHECK(token_service_);
DCHECK(!account_ids_.empty());
@@ -46,28 +46,28 @@ OAuthMultiloginTokenFetcher::OAuthMultiloginTokenFetcher(
#ifndef NDEBUG
// Check that there is no duplicate accounts.
- std::set<std::string> accounts_no_duplicates(account_ids_.begin(),
- account_ids_.end());
+ std::set<CoreAccountId> accounts_no_duplicates(account_ids_.begin(),
+ account_ids_.end());
DCHECK_EQ(account_ids_.size(), accounts_no_duplicates.size());
#endif
- for (const std::string& account_id : account_ids_)
+ for (const CoreAccountId& account_id : account_ids_)
StartFetchingToken(account_id);
}
OAuthMultiloginTokenFetcher::~OAuthMultiloginTokenFetcher() = default;
void OAuthMultiloginTokenFetcher::StartFetchingToken(
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
DCHECK(!account_id.empty());
token_requests_.push_back(
token_service_->StartRequestForMultilogin(account_id, this));
}
void OAuthMultiloginTokenFetcher::OnGetTokenSuccess(
- const OAuth2TokenService::Request* request,
+ const OAuth2AccessTokenManager::Request* request,
const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
- std::string account_id = request->GetAccountId();
+ CoreAccountId account_id = request->GetAccountId();
DCHECK(account_ids_.cend() !=
std::find(account_ids_.cbegin(), account_ids_.cend(), account_id));
@@ -82,24 +82,22 @@ void OAuthMultiloginTokenFetcher::OnGetTokenSuccess(
DCHECK(inserted.second); // If this fires, we have a duplicate account.
if (access_tokens_.size() == account_ids_.size()) {
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> token_id_pairs;
+ std::vector<AccountIdTokenPair> account_token_pairs;
for (const auto& id : account_ids_) {
const auto& it = access_tokens_.find(id);
DCHECK(!it->second.empty());
- // TODO(https://crbug.com/956503): Don't assume that the account ID is the
- // Gaia ID.
- token_id_pairs.emplace_back(id, it->second);
+ account_token_pairs.emplace_back(id, it->second);
}
RecordGetAccessTokenFinished(GoogleServiceAuthError::AuthErrorNone());
- std::move(success_callback_).Run(token_id_pairs);
+ std::move(success_callback_).Run(account_token_pairs);
// Do not add anything below this line, as this may be deleted.
}
}
void OAuthMultiloginTokenFetcher::OnGetTokenFailure(
- const OAuth2TokenService::Request* request,
+ const OAuth2AccessTokenManager::Request* request,
const GoogleServiceAuthError& error) {
- std::string account_id = request->GetAccountId();
+ CoreAccountId account_id = request->GetAccountId();
VLOG(1) << "Failed to retrieve accesstoken account=" << account_id
<< " error=" << error.ToString();
if (error.IsTransientError() &&
@@ -123,7 +121,7 @@ void OAuthMultiloginTokenFetcher::OnGetTokenFailure(
}
void OAuthMultiloginTokenFetcher::EraseRequest(
- const OAuth2TokenService::Request* request) {
+ const OAuth2AccessTokenManager::Request* request) {
for (auto it = token_requests_.begin(); it != token_requests_.end(); ++it) {
if (it->get() == request) {
token_requests_.erase(it);
diff --git a/chromium/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.h b/chromium/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.h
new file mode 100644
index 00000000000..8f5a5d62e8d
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.h
@@ -0,0 +1,84 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_OAUTH_MULTILOGIN_TOKEN_FETCHER_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_OAUTH_MULTILOGIN_TOKEN_FETCHER_H_
+
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/bind_helpers.h"
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "google_apis/gaia/oauth2_access_token_manager.h"
+
+class SigninClient;
+class ProfileOAuth2TokenService;
+
+namespace signin {
+
+// Fetches multilogin access tokens in parallel for multiple accounts.
+// It is safe to delete this object from within the callbacks.
+class OAuthMultiloginTokenFetcher : public OAuth2AccessTokenManager::Consumer {
+ public:
+ struct AccountIdTokenPair {
+ CoreAccountId account_id;
+ std::string token;
+
+ AccountIdTokenPair(const CoreAccountId& account_id,
+ const std::string& token)
+ : account_id(account_id), token(token) {}
+ };
+ using SuccessCallback =
+ base::OnceCallback<void(const std::vector<AccountIdTokenPair>&)>;
+ using FailureCallback =
+ base::OnceCallback<void(const GoogleServiceAuthError&)>;
+
+ OAuthMultiloginTokenFetcher(SigninClient* signin_client,
+ ProfileOAuth2TokenService* token_service,
+ const std::vector<CoreAccountId>& account_ids,
+ SuccessCallback success_callback,
+ FailureCallback failure_callback);
+
+ ~OAuthMultiloginTokenFetcher() override;
+
+ private:
+ void StartFetchingToken(const CoreAccountId& account_id);
+
+ // Overridden from OAuth2AccessTokenManager::Consumer.
+ void OnGetTokenSuccess(
+ const OAuth2AccessTokenManager::Request* request,
+ const OAuth2AccessTokenConsumer::TokenResponse& token_response) override;
+ void OnGetTokenFailure(const OAuth2AccessTokenManager::Request* request,
+ const GoogleServiceAuthError& error) override;
+
+ // Helper function to remove a request from token_requests_.
+ void EraseRequest(const OAuth2AccessTokenManager::Request* request);
+
+ SigninClient* signin_client_;
+ ProfileOAuth2TokenService* token_service_;
+ const std::vector<CoreAccountId> account_ids_;
+
+ SuccessCallback success_callback_;
+ FailureCallback failure_callback_;
+
+ std::vector<std::unique_ptr<OAuth2AccessTokenManager::Request>>
+ token_requests_;
+ std::map<CoreAccountId, std::string> access_tokens_;
+ std::set<CoreAccountId> retried_requests_; // Requests are retried once.
+
+ base::WeakPtrFactory<OAuthMultiloginTokenFetcher> weak_ptr_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(OAuthMultiloginTokenFetcher);
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_OAUTH_MULTILOGIN_TOKEN_FETCHER_H_
diff --git a/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher_unittest.cc b/chromium/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher_unittest.cc
index a40df52a3d6..ebeb12b0a3a 100644
--- a/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/oauth_multilogin_token_fetcher.h"
+#include "components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.h"
#include <map>
#include <memory>
@@ -11,8 +11,9 @@
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/test/scoped_task_environment.h"
-#include "components/signin/core/browser/test_signin_client.h"
-#include "google_apis/gaia/fake_oauth2_token_service.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h"
+#include "components/signin/public/base/test_signin_client.h"
#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/gaia_urls.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -21,7 +22,7 @@ namespace signin {
namespace {
-const char kAccountId[] = "account_id";
+const CoreAccountId kAccountId("account_id");
const char kAccessToken[] = "access_token";
// Status of the token fetch.
@@ -31,12 +32,13 @@ enum class FetchStatus { kSuccess, kFailure, kPending };
class OAuthMultiloginTokenFetcherTest : public testing::Test {
public:
- OAuthMultiloginTokenFetcherTest() : test_signin_client_(/*prefs=*/nullptr) {}
+ OAuthMultiloginTokenFetcherTest()
+ : test_signin_client_(&pref_service_), token_service_(&pref_service_) {}
~OAuthMultiloginTokenFetcherTest() override = default;
std::unique_ptr<OAuthMultiloginTokenFetcher> CreateFetcher(
- const std::vector<std::string> account_ids) {
+ const std::vector<CoreAccountId> account_ids) {
return std::make_unique<OAuthMultiloginTokenFetcher>(
&test_signin_client_, &token_service_, account_ids,
base::BindOnce(&OAuthMultiloginTokenFetcherTest::OnSuccess,
@@ -55,12 +57,13 @@ class OAuthMultiloginTokenFetcherTest : public testing::Test {
protected:
// Success callback for OAuthMultiloginTokenFetcher.
- void OnSuccess(const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>&
- token_id_pairs) {
+ void OnSuccess(
+ const std::vector<OAuthMultiloginTokenFetcher::AccountIdTokenPair>&
+ account_id_token_pairs) {
DCHECK(!success_callback_called_);
- DCHECK(token_id_pairs_.empty());
+ DCHECK(account_id_token_pairs_.empty());
success_callback_called_ = true;
- token_id_pairs_ = token_id_pairs;
+ account_id_token_pairs_ = account_id_token_pairs;
}
// Failure callback for OAuthMultiloginTokenFetcher.
@@ -75,14 +78,16 @@ class OAuthMultiloginTokenFetcherTest : public testing::Test {
bool success_callback_called_ = false;
bool failure_callback_called_ = false;
GoogleServiceAuthError error_;
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> token_id_pairs_;
+ std::vector<OAuthMultiloginTokenFetcher::AccountIdTokenPair>
+ account_id_token_pairs_;
+ TestingPrefServiceSimple pref_service_;
TestSigninClient test_signin_client_;
- FakeOAuth2TokenService token_service_;
+ FakeProfileOAuth2TokenService token_service_;
};
TEST_F(OAuthMultiloginTokenFetcherTest, OneAccountSuccess) {
- token_service_.AddAccount(kAccountId);
+ token_service_.UpdateCredentials(kAccountId, "refresh_token");
std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher =
CreateFetcher({kAccountId});
EXPECT_EQ(FetchStatus::kPending, GetFetchStatus());
@@ -91,13 +96,13 @@ TEST_F(OAuthMultiloginTokenFetcherTest, OneAccountSuccess) {
token_service_.IssueAllTokensForAccount(kAccountId, success_response);
EXPECT_EQ(FetchStatus::kSuccess, GetFetchStatus());
// Check result.
- EXPECT_EQ(1u, token_id_pairs_.size());
- EXPECT_EQ(kAccountId, token_id_pairs_[0].gaia_id_);
- EXPECT_EQ(kAccessToken, token_id_pairs_[0].token_);
+ EXPECT_EQ(1u, account_id_token_pairs_.size());
+ EXPECT_EQ(kAccountId, account_id_token_pairs_[0].account_id);
+ EXPECT_EQ(kAccessToken, account_id_token_pairs_[0].token);
}
TEST_F(OAuthMultiloginTokenFetcherTest, OneAccountPersistentError) {
- token_service_.AddAccount(kAccountId);
+ token_service_.UpdateCredentials(kAccountId, "refresh_token");
std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher =
CreateFetcher({kAccountId});
EXPECT_EQ(FetchStatus::kPending, GetFetchStatus());
@@ -109,7 +114,7 @@ TEST_F(OAuthMultiloginTokenFetcherTest, OneAccountPersistentError) {
}
TEST_F(OAuthMultiloginTokenFetcherTest, OneAccountTransientError) {
- token_service_.AddAccount(kAccountId);
+ token_service_.UpdateCredentials(kAccountId, "refresh_token");
std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher =
CreateFetcher({kAccountId});
// Connection failure will be retried.
@@ -123,13 +128,13 @@ TEST_F(OAuthMultiloginTokenFetcherTest, OneAccountTransientError) {
token_service_.IssueAllTokensForAccount(kAccountId, success_response);
EXPECT_EQ(FetchStatus::kSuccess, GetFetchStatus());
// Check result.
- EXPECT_EQ(1u, token_id_pairs_.size());
- EXPECT_EQ(kAccountId, token_id_pairs_[0].gaia_id_);
- EXPECT_EQ(kAccessToken, token_id_pairs_[0].token_);
+ EXPECT_EQ(1u, account_id_token_pairs_.size());
+ EXPECT_EQ(kAccountId, account_id_token_pairs_[0].account_id);
+ EXPECT_EQ(kAccessToken, account_id_token_pairs_[0].token);
}
TEST_F(OAuthMultiloginTokenFetcherTest, OneAccountTransientErrorMaxRetries) {
- token_service_.AddAccount(kAccountId);
+ token_service_.UpdateCredentials(kAccountId, "refresh_token");
std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher =
CreateFetcher({kAccountId});
// Repeated connection failures.
@@ -147,76 +152,85 @@ TEST_F(OAuthMultiloginTokenFetcherTest, OneAccountTransientErrorMaxRetries) {
// The flow succeeds even if requests are received out of order.
TEST_F(OAuthMultiloginTokenFetcherTest, MultipleAccountsSuccess) {
- token_service_.AddAccount("account_1");
- token_service_.AddAccount("account_2");
- token_service_.AddAccount("account_3");
+ const CoreAccountId account_1("account_1");
+ const CoreAccountId account_2("account_2");
+ const CoreAccountId account_3("account_3");
+ token_service_.UpdateCredentials(account_1, "refresh_token");
+ token_service_.UpdateCredentials(account_2, "refresh_token");
+ token_service_.UpdateCredentials(account_3, "refresh_token");
std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher =
- CreateFetcher({"account_1", "account_2", "account_3"});
+ CreateFetcher({account_1, account_2, account_3});
OAuth2AccessTokenConsumer::TokenResponse success_response;
success_response.access_token = "token_3";
- token_service_.IssueAllTokensForAccount("account_3", success_response);
+ token_service_.IssueAllTokensForAccount(account_3, success_response);
success_response.access_token = "token_1";
- token_service_.IssueAllTokensForAccount("account_1", success_response);
+ token_service_.IssueAllTokensForAccount(account_1, success_response);
EXPECT_EQ(FetchStatus::kPending, GetFetchStatus());
success_response.access_token = "token_2";
- token_service_.IssueAllTokensForAccount("account_2", success_response);
+ token_service_.IssueAllTokensForAccount(account_2, success_response);
EXPECT_EQ(FetchStatus::kSuccess, GetFetchStatus());
// Check result.
- EXPECT_EQ(3u, token_id_pairs_.size());
- EXPECT_EQ("account_1", token_id_pairs_[0].gaia_id_);
- EXPECT_EQ("account_2", token_id_pairs_[1].gaia_id_);
- EXPECT_EQ("account_3", token_id_pairs_[2].gaia_id_);
- EXPECT_EQ("token_1", token_id_pairs_[0].token_);
- EXPECT_EQ("token_2", token_id_pairs_[1].token_);
- EXPECT_EQ("token_3", token_id_pairs_[2].token_);
+ EXPECT_EQ(3u, account_id_token_pairs_.size());
+ EXPECT_EQ(account_1, account_id_token_pairs_[0].account_id);
+ EXPECT_EQ(account_2, account_id_token_pairs_[1].account_id);
+ EXPECT_EQ(account_3, account_id_token_pairs_[2].account_id);
+ EXPECT_EQ("token_1", account_id_token_pairs_[0].token);
+ EXPECT_EQ("token_2", account_id_token_pairs_[1].token);
+ EXPECT_EQ("token_3", account_id_token_pairs_[2].token);
}
TEST_F(OAuthMultiloginTokenFetcherTest, MultipleAccountsTransientError) {
- token_service_.AddAccount("account_1");
- token_service_.AddAccount("account_2");
- token_service_.AddAccount("account_3");
+ const CoreAccountId account_1("account_1");
+ const CoreAccountId account_2("account_2");
+ const CoreAccountId account_3("account_3");
+ token_service_.UpdateCredentials(account_1, "refresh_token");
+ token_service_.UpdateCredentials(account_2, "refresh_token");
+ token_service_.UpdateCredentials(account_3, "refresh_token");
std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher =
- CreateFetcher({"account_1", "account_2", "account_3"});
+ CreateFetcher({account_1, account_2, account_3});
// Connection failures will be retried.
token_service_.IssueErrorForAllPendingRequestsForAccount(
- "account_1",
+ account_1,
GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
token_service_.IssueErrorForAllPendingRequestsForAccount(
- "account_2",
+ account_2,
GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
token_service_.IssueErrorForAllPendingRequestsForAccount(
- "account_3",
+ account_3,
GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
// Success on retry.
OAuth2AccessTokenConsumer::TokenResponse success_response;
success_response.access_token = kAccessToken;
success_response.access_token = "token_1";
- token_service_.IssueAllTokensForAccount("account_1", success_response);
+ token_service_.IssueAllTokensForAccount(account_1, success_response);
success_response.access_token = "token_2";
- token_service_.IssueAllTokensForAccount("account_2", success_response);
+ token_service_.IssueAllTokensForAccount(account_2, success_response);
EXPECT_EQ(FetchStatus::kPending, GetFetchStatus());
success_response.access_token = "token_3";
- token_service_.IssueAllTokensForAccount("account_3", success_response);
+ token_service_.IssueAllTokensForAccount(account_3, success_response);
EXPECT_EQ(FetchStatus::kSuccess, GetFetchStatus());
// Check result.
- EXPECT_EQ(3u, token_id_pairs_.size());
- EXPECT_EQ("account_1", token_id_pairs_[0].gaia_id_);
- EXPECT_EQ("account_2", token_id_pairs_[1].gaia_id_);
- EXPECT_EQ("account_3", token_id_pairs_[2].gaia_id_);
- EXPECT_EQ("token_1", token_id_pairs_[0].token_);
- EXPECT_EQ("token_2", token_id_pairs_[1].token_);
- EXPECT_EQ("token_3", token_id_pairs_[2].token_);
+ EXPECT_EQ(3u, account_id_token_pairs_.size());
+ EXPECT_EQ(account_1, account_id_token_pairs_[0].account_id);
+ EXPECT_EQ(account_2, account_id_token_pairs_[1].account_id);
+ EXPECT_EQ(account_3, account_id_token_pairs_[2].account_id);
+ EXPECT_EQ("token_1", account_id_token_pairs_[0].token);
+ EXPECT_EQ("token_2", account_id_token_pairs_[1].token);
+ EXPECT_EQ("token_3", account_id_token_pairs_[2].token);
}
TEST_F(OAuthMultiloginTokenFetcherTest, MultipleAccountsPersistentError) {
- token_service_.AddAccount("account_1");
- token_service_.AddAccount("account_2");
- token_service_.AddAccount("account_3");
+ const CoreAccountId account_1("account_1");
+ const CoreAccountId account_2("account_2");
+ const CoreAccountId account_3("account_3");
+ token_service_.UpdateCredentials(account_1, "refresh_token");
+ token_service_.UpdateCredentials(account_2, "refresh_token");
+ token_service_.UpdateCredentials(account_3, "refresh_token");
std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher =
- CreateFetcher({"account_1", "account_2", "account_3"});
+ CreateFetcher({account_1, account_2, account_3});
EXPECT_EQ(FetchStatus::kPending, GetFetchStatus());
token_service_.IssueErrorForAllPendingRequestsForAccount(
- "account_2",
+ account_2,
GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
// Fail as soon as one of the accounts is in error.
EXPECT_EQ(FetchStatus::kFailure, GetFetchStatus());
diff --git a/chromium/components/signin/core/browser/signin_manager_base.cc b/chromium/components/signin/internal/identity_manager/primary_account_manager.cc
index 37ee80721d5..91105525fcc 100644
--- a/chromium/components/signin/core/browser/signin_manager_base.cc
+++ b/chromium/components/signin/internal/identity_manager/primary_account_manager.cc
@@ -2,52 +2,51 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/signin_manager_base.h"
+#include "components/signin/internal/identity_manager/primary_account_manager.h"
+#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include "base/command_line.h"
-#include "base/memory/ref_counted.h"
+#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/account_info.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/gaia_cookie_manager_service.h"
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_client.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "components/signin/core/browser/signin_switches.h"
-#include "google_apis/gaia/gaia_auth_util.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/gaia_urls.h"
-
-SigninManagerBase::SigninManagerBase(
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/primary_account_policy_manager.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/public/base/signin_client.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/base/signin_switches.h"
+#include "components/signin/public/identity_manager/account_info.h"
+
+PrimaryAccountManager::PrimaryAccountManager(
SigninClient* client,
ProfileOAuth2TokenService* token_service,
AccountTrackerService* account_tracker_service,
- GaiaCookieManagerService* cookie_manager_service,
- signin::AccountConsistencyMethod account_consistency)
+ signin::AccountConsistencyMethod account_consistency,
+ std::unique_ptr<PrimaryAccountPolicyManager> policy_manager)
: client_(client),
token_service_(token_service),
account_tracker_service_(account_tracker_service),
initialized_(false),
+#if !defined(OS_CHROMEOS)
account_consistency_(account_consistency),
- weak_pointer_factory_(this) {
+#endif
+ policy_manager_(std::move(policy_manager)) {
DCHECK(client_);
DCHECK(account_tracker_service_);
}
-SigninManagerBase::~SigninManagerBase() {
- DCHECK(!observer_);
+PrimaryAccountManager::~PrimaryAccountManager() {
+ token_service_->RemoveObserver(this);
}
// static
-void SigninManagerBase::RegisterProfilePrefs(PrefRegistrySimple* registry) {
+void PrimaryAccountManager::RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterStringPref(prefs::kGoogleServicesHostedDomain,
std::string());
registry->RegisterStringPref(prefs::kGoogleServicesLastAccountId,
@@ -60,8 +59,6 @@ void SigninManagerBase::RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(prefs::kAutologinEnabled, true);
registry->RegisterListPref(prefs::kReverseAutologinRejectedEmailList);
registry->RegisterBooleanPref(prefs::kSigninAllowed, true);
- registry->RegisterInt64Pref(prefs::kSignedInTime,
- base::Time().ToInternalValue());
registry->RegisterBooleanPref(prefs::kSignedInWithCredentialProvider, false);
// Deprecated prefs: will be removed in a future release.
@@ -69,12 +66,12 @@ void SigninManagerBase::RegisterProfilePrefs(PrefRegistrySimple* registry) {
}
// static
-void SigninManagerBase::RegisterPrefs(PrefRegistrySimple* registry) {
+void PrimaryAccountManager::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterStringPref(prefs::kGoogleServicesUsernamePattern,
std::string());
}
-void SigninManagerBase::Initialize(PrefService* local_state) {
+void PrimaryAccountManager::Initialize(PrefService* local_state) {
// Should never call Initialize() twice.
DCHECK(!IsInitialized());
initialized_ = true;
@@ -89,7 +86,7 @@ void SigninManagerBase::Initialize(PrefService* local_state) {
client_->GetPrefs()->ClearPref(prefs::kGoogleServicesUserAccountId);
}
- std::string account_id =
+ std::string pref_account_id =
client_->GetPrefs()->GetString(prefs::kGoogleServicesAccountId);
// Handle backward compatibility: if kGoogleServicesAccountId is empty, but
@@ -97,7 +94,7 @@ void SigninManagerBase::Initialize(PrefService* local_state) {
// be updated. kGoogleServicesUserAccountId should not be empty, and contains
// the gaia_id. Use both properties to prime the account tracker before
// proceeding.
- if (account_id.empty()) {
+ if (pref_account_id.empty()) {
std::string pref_account_username =
client_->GetPrefs()->GetString(prefs::kGoogleServicesUsername);
if (!pref_account_username.empty()) {
@@ -123,13 +120,15 @@ void SigninManagerBase::Initialize(PrefService* local_state) {
// is correct. After the migration, the returned value will be empty,
// which means the user is essentially signed out.
// TODO(rogerta): may want to show a toast or something.
- account_id = account_tracker_service_->SeedAccountInfo(
- pref_gaia_id, pref_account_username);
+ pref_account_id =
+ account_tracker_service_
+ ->SeedAccountInfo(pref_gaia_id, pref_account_username)
+ .id;
// Set account id before removing obsolete user name in case crash in the
// middle.
client_->GetPrefs()->SetString(prefs::kGoogleServicesAccountId,
- account_id);
+ pref_account_id);
// Now remove obsolete preferences.
client_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
@@ -140,51 +139,54 @@ void SigninManagerBase::Initialize(PrefService* local_state) {
// kGoogleServicesAccountId.
}
- if (!account_id.empty()) {
+ if (!pref_account_id.empty()) {
if (account_tracker_service_->GetMigrationState() ==
AccountTrackerService::MIGRATION_IN_PROGRESS) {
AccountInfo account_info =
- account_tracker_service_->FindAccountInfoByEmail(account_id);
+ account_tracker_service_->FindAccountInfoByEmail(pref_account_id);
// |account_info.gaia| could be empty if |account_id| is already gaia id.
if (!account_info.gaia.empty()) {
- account_id = account_info.gaia;
+ pref_account_id = account_info.gaia;
client_->GetPrefs()->SetString(prefs::kGoogleServicesAccountId,
- account_id);
+ pref_account_id);
}
}
- SetAuthenticatedAccountId(account_id);
+ SetAuthenticatedAccountId(CoreAccountId(pref_account_id));
+ }
+ if (policy_manager_) {
+ policy_manager_->InitializePolicy(local_state, this);
}
- FinalizeInitBeforeLoadingRefreshTokens(local_state);
- token_service()->LoadCredentials(GetAuthenticatedAccountId());
+ // It is important to only load credentials after starting to observe the
+ // token service.
+ token_service_->AddObserver(this);
+ token_service_->LoadCredentials(GetAuthenticatedAccountId());
}
-void SigninManagerBase::FinalizeInitBeforeLoadingRefreshTokens(
- PrefService* local_state) {}
-
-bool SigninManagerBase::IsInitialized() const {
+bool PrimaryAccountManager::IsInitialized() const {
return initialized_;
}
-AccountInfo SigninManagerBase::GetAuthenticatedAccountInfo() const {
+AccountInfo PrimaryAccountManager::GetAuthenticatedAccountInfo() const {
return account_tracker_service_->GetAccountInfo(GetAuthenticatedAccountId());
}
-const std::string& SigninManagerBase::GetAuthenticatedAccountId() const {
+const CoreAccountId& PrimaryAccountManager::GetAuthenticatedAccountId() const {
return authenticated_account_id_;
}
-void SigninManagerBase::SetAuthenticatedAccountInfo(const std::string& gaia_id,
- const std::string& email) {
+void PrimaryAccountManager::SetAuthenticatedAccountInfo(
+ const std::string& gaia_id,
+ const std::string& email) {
DCHECK(!gaia_id.empty());
DCHECK(!email.empty());
- std::string account_id =
+ CoreAccountId account_id =
account_tracker_service_->SeedAccountInfo(gaia_id, email);
SetAuthenticatedAccountId(account_id);
}
-void SigninManagerBase::SetAuthenticatedAccountId(
- const std::string& account_id) {
+void PrimaryAccountManager::SetAuthenticatedAccountId(
+ const CoreAccountId& account_id) {
DCHECK(!account_id.empty());
if (!authenticated_account_id_.empty()) {
DCHECK_EQ(account_id, authenticated_account_id_)
@@ -196,10 +198,11 @@ void SigninManagerBase::SetAuthenticatedAccountId(
std::string pref_account_id =
client_->GetPrefs()->GetString(prefs::kGoogleServicesAccountId);
- DCHECK(pref_account_id.empty() || pref_account_id == account_id)
+ DCHECK(pref_account_id.empty() || pref_account_id == account_id.id)
<< "account_id=" << account_id << " pref_account_id=" << pref_account_id;
authenticated_account_id_ = account_id;
- client_->GetPrefs()->SetString(prefs::kGoogleServicesAccountId, account_id);
+ client_->GetPrefs()->SetString(prefs::kGoogleServicesAccountId,
+ account_id.id);
// This preference is set so that code on I/O thread has access to the
// Gaia id of the signed in user.
@@ -216,7 +219,7 @@ void SigninManagerBase::SetAuthenticatedAccountId(
// user is signed in the corresponding preferences should match. Doing it here
// as opposed to on signin allows us to catch the upgrade scenario.
client_->GetPrefs()->SetString(prefs::kGoogleServicesLastAccountId,
- account_id);
+ account_id.id);
client_->GetPrefs()->SetString(prefs::kGoogleServicesLastUsername,
info.email);
@@ -224,34 +227,67 @@ void SigninManagerBase::SetAuthenticatedAccountId(
// if Chrome crashes before the next commit interval.
client_->GetPrefs()->CommitPendingWrite();
- if (observer_) {
- observer_->AuthenticatedAccountSet(info);
+ if (on_authenticated_account_set_callback_) {
+ on_authenticated_account_set_callback_.Run(info);
}
}
-void SigninManagerBase::ClearAuthenticatedAccountId() {
- authenticated_account_id_.clear();
- if (observer_) {
- observer_->AuthenticatedAccountCleared();
+void PrimaryAccountManager::ClearAuthenticatedAccountId() {
+ authenticated_account_id_ = CoreAccountId();
+ if (on_authenticated_account_cleared_callback_) {
+ on_authenticated_account_cleared_callback_.Run();
}
}
-bool SigninManagerBase::IsAuthenticated() const {
+bool PrimaryAccountManager::IsAuthenticated() const {
return !authenticated_account_id_.empty();
}
-void SigninManagerBase::SetObserver(Observer* observer) {
- DCHECK(!observer_) << "SetObserver shouldn't be called multiple times.";
- observer_ = observer;
+void PrimaryAccountManager::SetGoogleSigninSucceededCallback(
+ AccountSigninCallback callback) {
+ DCHECK(!on_google_signin_succeeded_callback_)
+ << "GoogleSigninSucceededCallback shouldn't be set multiple times.";
+ on_google_signin_succeeded_callback_ = callback;
+}
+
+#if !defined(OS_CHROMEOS)
+void PrimaryAccountManager::SetGoogleSignedOutCallback(
+ AccountSigninCallback callback) {
+ DCHECK(!on_google_signed_out_callback_)
+ << "GoogleSignedOutCallback shouldn't be set multiple times.";
+ on_google_signed_out_callback_ = callback;
+}
+#endif // !defined(OS_CHROMEOS)
+
+void PrimaryAccountManager::SetAuthenticatedAccountSetCallback(
+ AccountSigninCallback callback) {
+ DCHECK(!on_authenticated_account_set_callback_)
+ << "AuthenticatedAccountSetCallback shouldn't be set multiple times.";
+ on_authenticated_account_set_callback_ = callback;
+}
+
+void PrimaryAccountManager::SetAuthenticatedAccountClearedCallback(
+ AccountClearedCallback callback) {
+ DCHECK(!on_authenticated_account_cleared_callback_)
+ << "AuthenticatedAccountClearedCallback shouldn't be set multiple times.";
+ on_authenticated_account_cleared_callback_ = callback;
}
-void SigninManagerBase::ClearObserver() {
- DCHECK(observer_);
- observer_ = nullptr;
+void PrimaryAccountManager::SignIn(const std::string& username) {
+ AccountInfo info = account_tracker_service_->FindAccountInfoByEmail(username);
+ DCHECK(!info.gaia.empty());
+ DCHECK(!info.email.empty());
+
+ bool reauth_in_progress = IsAuthenticated();
+
+ SetAuthenticatedAccountInfo(info.gaia, info.email);
+
+ if (!reauth_in_progress && on_google_signin_succeeded_callback_)
+ on_google_signin_succeeded_callback_.Run(GetAuthenticatedAccountInfo());
}
#if !defined(OS_CHROMEOS)
-void SigninManagerBase::SignOut(
+void PrimaryAccountManager::SignOut(
signin_metrics::ProfileSignout signout_source_metric,
signin_metrics::SignoutDelete signout_delete_metric) {
RemoveAccountsOption remove_option =
@@ -261,38 +297,43 @@ void SigninManagerBase::SignOut(
StartSignOut(signout_source_metric, signout_delete_metric, remove_option);
}
-void SigninManagerBase::SignOutAndRemoveAllAccounts(
+void PrimaryAccountManager::SignOutAndRemoveAllAccounts(
signin_metrics::ProfileSignout signout_source_metric,
signin_metrics::SignoutDelete signout_delete_metric) {
StartSignOut(signout_source_metric, signout_delete_metric,
RemoveAccountsOption::kRemoveAllAccounts);
}
-void SigninManagerBase::SignOutAndKeepAllAccounts(
+void PrimaryAccountManager::SignOutAndKeepAllAccounts(
signin_metrics::ProfileSignout signout_source_metric,
signin_metrics::SignoutDelete signout_delete_metric) {
StartSignOut(signout_source_metric, signout_delete_metric,
RemoveAccountsOption::kKeepAllAccounts);
}
-void SigninManagerBase::StartSignOut(
+void PrimaryAccountManager::StartSignOut(
signin_metrics::ProfileSignout signout_source_metric,
signin_metrics::SignoutDelete signout_delete_metric,
RemoveAccountsOption remove_option) {
- signin_client()->PreSignOut(
- base::BindOnce(&SigninManagerBase::OnSignoutDecisionReached,
+ VLOG(1) << "StartSignOut: " << static_cast<int>(signout_source_metric) << ", "
+ << static_cast<int>(signout_delete_metric) << ", "
+ << static_cast<int>(remove_option);
+ client_->PreSignOut(
+ base::BindOnce(&PrimaryAccountManager::OnSignoutDecisionReached,
base::Unretained(this), signout_source_metric,
signout_delete_metric, remove_option),
signout_source_metric);
}
-void SigninManagerBase::OnSignoutDecisionReached(
+void PrimaryAccountManager::OnSignoutDecisionReached(
signin_metrics::ProfileSignout signout_source_metric,
signin_metrics::SignoutDelete signout_delete_metric,
RemoveAccountsOption remove_option,
SigninClient::SignoutDecision signout_decision) {
DCHECK(IsInitialized());
+ VLOG(1) << "OnSignoutDecisionReached: "
+ << (signout_decision == SigninClient::SignoutDecision::ALLOW_SIGNOUT);
signin_metrics::LogSignout(signout_source_metric, signout_delete_metric);
if (!IsAuthenticated()) {
return;
@@ -301,28 +342,17 @@ void SigninManagerBase::OnSignoutDecisionReached(
// TODO(crbug.com/887756): Consider moving this higher up, or document why
// the above blocks are exempt from the |signout_decision| early return.
if (signout_decision == SigninClient::SignoutDecision::DISALLOW_SIGNOUT) {
- DVLOG(1) << "Ignoring attempt to sign out while signout disallowed";
+ VLOG(1) << "Ignoring attempt to sign out while signout disallowed";
return;
}
AccountInfo account_info = GetAuthenticatedAccountInfo();
- const std::string account_id = GetAuthenticatedAccountId();
+ const CoreAccountId account_id = GetAuthenticatedAccountId();
const std::string username = account_info.email;
- const base::Time signin_time =
- base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromMicroseconds(
- signin_client()->GetPrefs()->GetInt64(prefs::kSignedInTime)));
ClearAuthenticatedAccountId();
- signin_client()->GetPrefs()->ClearPref(prefs::kGoogleServicesHostedDomain);
- signin_client()->GetPrefs()->ClearPref(prefs::kGoogleServicesAccountId);
- signin_client()->GetPrefs()->ClearPref(prefs::kGoogleServicesUserAccountId);
- signin_client()->GetPrefs()->ClearPref(prefs::kSignedInTime);
-
- // Determine the duration the user was logged in and log that to UMA.
- if (!signin_time.is_null()) {
- base::TimeDelta signed_in_duration = base::Time::Now() - signin_time;
- UMA_HISTOGRAM_COUNTS_1M("Signin.SignedInDurationBeforeSignout",
- signed_in_duration.InMinutes());
- }
+ client_->GetPrefs()->ClearPref(prefs::kGoogleServicesHostedDomain);
+ client_->GetPrefs()->ClearPref(prefs::kGoogleServicesAccountId);
+ client_->GetPrefs()->ClearPref(prefs::kGoogleServicesUserAccountId);
// Revoke all tokens before sending signed_out notification, because there
// may be components that don't listen for token service events when the
@@ -330,15 +360,15 @@ void SigninManagerBase::OnSignoutDecisionReached(
switch (remove_option) {
case RemoveAccountsOption::kRemoveAllAccounts:
VLOG(0) << "Revoking all refresh tokens on server. Reason: sign out";
- token_service()->RevokeAllCredentials(
+ token_service_->RevokeAllCredentials(
signin_metrics::SourceForRefreshTokenOperation::
- kSigninManager_ClearPrimaryAccount);
+ kPrimaryAccountManager_ClearAccount);
break;
case RemoveAccountsOption::kRemoveAuthenticatedAccountIfInError:
- if (token_service()->RefreshTokenHasError(account_id))
- token_service()->RevokeCredentials(
+ if (token_service_->RefreshTokenHasError(account_id))
+ token_service_->RevokeCredentials(
account_id, signin_metrics::SourceForRefreshTokenOperation::
- kSigninManager_ClearPrimaryAccount);
+ kPrimaryAccountManager_ClearAccount);
break;
case RemoveAccountsOption::kKeepAllAccounts:
// Do nothing.
@@ -348,9 +378,33 @@ void SigninManagerBase::OnSignoutDecisionReached(
FireGoogleSignedOut(account_info);
}
-void SigninManagerBase::FireGoogleSignedOut(const AccountInfo& account_info) {
- if (observer_ != nullptr) {
- observer_->GoogleSignedOut(account_info);
+void PrimaryAccountManager::FireGoogleSignedOut(
+ const AccountInfo& account_info) {
+ if (on_google_signed_out_callback_) {
+ on_google_signed_out_callback_.Run(account_info);
+ }
+}
+
+void PrimaryAccountManager::OnRefreshTokensLoaded() {
+ token_service_->RemoveObserver(this);
+
+ if (account_tracker_service_->GetMigrationState() ==
+ AccountTrackerService::MIGRATION_IN_PROGRESS) {
+ account_tracker_service_->SetMigrationDone();
+ }
+
+ // Remove account information from the account tracker service if needed.
+ if (token_service_->HasLoadCredentialsFinishedWithNoErrors()) {
+ std::vector<AccountInfo> accounts_in_tracker_service =
+ account_tracker_service_->GetAccounts();
+ for (const auto& account : accounts_in_tracker_service) {
+ if (GetAuthenticatedAccountId() != account.account_id &&
+ !token_service_->RefreshTokenIsAvailable(account.account_id)) {
+ VLOG(0) << "Removed account from account tracker service: "
+ << account.account_id;
+ account_tracker_service_->RemoveAccount(account.account_id);
+ }
+ }
}
}
#endif // !defined(OS_CHROMEOS)
diff --git a/chromium/components/signin/core/browser/signin_manager_base.h b/chromium/components/signin/internal/identity_manager/primary_account_manager.h
index 9297ca097fe..7625fe002c3 100644
--- a/chromium/components/signin/core/browser/signin_manager_base.h
+++ b/chromium/components/signin/internal/identity_manager/primary_account_manager.h
@@ -2,100 +2,55 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// The signin manager encapsulates some functionality tracking
-// which user is signed in.
+// The PrimaryAccountManager encapsulates some functionality tracking
+// which account is the primary one.
//
-// **NOTE** on semantics of SigninManager:
+// **NOTE** on semantics of PrimaryAccountManager:
//
// Once a signin is successful, the username becomes "established" and will not
// be cleared until a SignOut operation is performed (persists across
-// restarts). Until that happens, the signin manager can still be used to
-// refresh credentials, but changing the username is not permitted.
+// restarts). Until that happens, the primary account manager can still be used
+// to refresh credentials, but changing the username is not permitted.
//
-// On Chrome OS, because of the existence of other components that handle login
-// and signin at a higher level, all that is needed from a SigninManager is
-// caching / handling of the "authenticated username" field, and TokenService
-// initialization, so that components that depend on these two things
-// (i.e on desktop) can continue using it / don't need to change. For this
-// reason, SigninManagerBase is all that exists on Chrome OS. For desktop,
-// see signin/signin_manager.h.
+// On ChromeOS signout is not possible, so that functionality is if-def'd out on
+// that platform.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_BASE_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_BASE_H_
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PRIMARY_ACCOUNT_MANAGER_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PRIMARY_ACCOUNT_MANAGER_H_
#include <memory>
#include <string>
+#include "base/callback.h"
#include "base/callback_list.h"
-#include "base/compiler_specific.h"
-#include "base/logging.h"
#include "base/macros.h"
-#include "base/observer_list.h"
-#include "components/prefs/pref_change_registrar.h"
-#include "components/prefs/pref_member.h"
-#include "components/signin/core/browser/account_consistency_method.h"
-#include "components/signin/core/browser/account_info.h"
-#include "components/signin/core/browser/signin_client.h"
-#include "google_apis/gaia/google_service_auth_error.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/base/signin_client.h"
+#include "google_apis/gaia/oauth2_token_service_observer.h"
+struct AccountInfo;
class AccountTrackerService;
-class GaiaCookieManagerService;
class PrefRegistrySimple;
class PrefService;
+class PrimaryAccountPolicyManager;
class ProfileOAuth2TokenService;
-class SigninClient;
-class SigninManagerBase {
- public:
- class Observer {
- public:
- // Called when a user signs into Google services such as sync.
- // This method is not called during a reauth.
- virtual void GoogleSigninSucceeded(const AccountInfo& account_info) {}
-
- // Called when the currently signed-in user for a user has been signed out.
- virtual void GoogleSignedOut(const AccountInfo& account_info) {}
-
- // Called during the signin as soon as
- // SigninManagerBase::authenticated_account_id_ is set.
- virtual void AuthenticatedAccountSet(const AccountInfo& account_info) {}
-
- // Called during the signout as soon as
- // SigninManagerBase::authenticated_account_id_ is cleared.
- virtual void AuthenticatedAccountCleared() {}
+namespace signin_metrics {
+enum ProfileSignout : int;
+enum class SignoutDelete;
+} // namespace signin_metrics
- protected:
- virtual ~Observer() {}
-
- private:
- // SigninManagers that fire notifications.
- friend class SigninManager;
- };
-
-// On non-ChromeOS platforms, SigninManagerBase should only be instantiated
-// via the derived SigninManager class, as the codewise assumes the
-// invariant that any SigninManagerBase object can be cast to a
-// SigninManager object when not on ChromeOS. Make the constructor private
-// and add SigninManager as a friend to support this.
-// TODO(883648): Eliminate the need to downcast SigninManagerBase to
-// SigninManager and then eliminate this as well.
-#if !defined(OS_CHROMEOS)
- private:
-#endif
- SigninManagerBase(SigninClient* client,
- ProfileOAuth2TokenService* token_service,
- AccountTrackerService* account_tracker_service,
- GaiaCookieManagerService* cookie_manager_service,
- signin::AccountConsistencyMethod account_consistency);
-#if !defined(OS_CHROMEOS)
+class PrimaryAccountManager : public OAuth2TokenServiceObserver {
public:
-#endif
+ typedef base::RepeatingCallback<void(const AccountInfo&)>
+ AccountSigninCallback;
+ typedef base::RepeatingCallback<void()> AccountClearedCallback;
#if !defined(OS_CHROMEOS)
// Used to remove accounts from the token service and the account tracker.
enum class RemoveAccountsOption {
// Do not remove accounts.
- kKeepAllAccounts,
+ kKeepAllAccounts = 0,
// Remove all the accounts.
kRemoveAllAccounts,
// Removes the authenticated account if it is in authentication error.
@@ -103,7 +58,13 @@ class SigninManagerBase {
};
#endif
- virtual ~SigninManagerBase();
+ PrimaryAccountManager(
+ SigninClient* client,
+ ProfileOAuth2TokenService* token_service,
+ AccountTrackerService* account_tracker_service,
+ signin::AccountConsistencyMethod account_consistency,
+ std::unique_ptr<PrimaryAccountPolicyManager> policy_manager);
+ ~PrimaryAccountManager() override;
// Registers per-profile prefs.
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
@@ -129,7 +90,7 @@ class SigninManagerBase {
// normalized email address of the connected account, use
// GetAuthenticatedAccountInfo().email. Example: to show the string "Signed
// in as XXX" in the hotdog menu.
- const std::string& GetAuthenticatedAccountId() const;
+ const CoreAccountId& GetAuthenticatedAccountId() const;
// Sets the authenticated user's Gaia ID and display email. Internally,
// this will seed the account information in AccountTrackerService and pick
@@ -140,12 +101,27 @@ class SigninManagerBase {
// Returns true if there is an authenticated user.
bool IsAuthenticated() const;
- // Methods to set or clear the observer of signin.
- // In practice these should only be used by IdentityManager.
- // NOTE: If SetObserver is called, ClearObserver should be called before
- // the destruction of SigninManagerBase.
- void SetObserver(Observer* observer);
- void ClearObserver();
+ // If set, this callback will be invoked whenever a user signs into Google
+ // services such as sync. This callback is not called during a reauth.
+ void SetGoogleSigninSucceededCallback(AccountSigninCallback callback);
+
+#if !defined(OS_CHROMEOS)
+ // If set, this callback will be invoked whenever the currently signed-in user
+ // for a user has been signed out.
+ void SetGoogleSignedOutCallback(AccountSigninCallback callback);
+#endif
+
+ // If set, this callback will be invoked during the signin as soon as
+ // PrimaryAccountManager::authenticated_account_id_ is set.
+ void SetAuthenticatedAccountSetCallback(AccountSigninCallback callback);
+
+ // If set, this callback will be invoked during the signout as soon as
+ // PrimaryAccountManager::authenticated_account_id_ is cleared.
+ void SetAuthenticatedAccountClearedCallback(AccountClearedCallback callback);
+
+ // Signs a user in. PrimaryAccountManager assumes that |username| can be used
+ // to look up the corresponding account_id and gaia_id for this email.
+ void SignIn(const std::string& username);
// Signout API surfaces (not supported on ChromeOS, where signout is not
// permitted).
@@ -175,19 +151,7 @@ class SigninManagerBase {
signin_metrics::SignoutDelete signout_delete_metric);
#endif
- protected:
- SigninClient* signin_client() const { return client_; }
-
- ProfileOAuth2TokenService* token_service() const { return token_service_; }
-
- AccountTrackerService* account_tracker_service() const {
- return account_tracker_service_;
- }
-
- // Invoked at the end of |Initialize| before the refresh token for the primary
- // account is loaded.
- virtual void FinalizeInitBeforeLoadingRefreshTokens(PrefService* local_state);
-
+ private:
// Sets the authenticated user's account id.
// If the user is already authenticated with the same account id, then this
// method is a no-op.
@@ -195,24 +159,14 @@ class SigninManagerBase {
// with a different account (this method will DCHECK in that case).
// |account_id| must not be empty. To log the user out, use
// ClearAuthenticatedAccountId() instead.
- void SetAuthenticatedAccountId(const std::string& account_id);
+ void SetAuthenticatedAccountId(const CoreAccountId& account_id);
// Clears the authenticated user's account id.
- // This method is not public because SigninManagerBase does not allow signing
- // out by default. Subclasses implementing a sign-out functionality need to
- // call this.
+ // This method is not public because PrimaryAccountManager does not allow
+ // signing out by default. Subclasses implementing a sign-out functionality
+ // need to call this.
void ClearAuthenticatedAccountId();
- // Observer to notify on signin events.
- // There is a DCHECK on destruction that this has been cleared.
- Observer* observer_ = nullptr;
-
- private:
- // Added only to allow SigninManager to call the SigninManagerBase
- // constructor while disallowing any ad-hoc subclassing of
- // SigninManagerBase.
- friend class SigninManager;
-
#if !defined(OS_CHROMEOS)
// Starts the sign out process.
void StartSignOut(signin_metrics::ProfileSignout signout_source_metric,
@@ -228,6 +182,9 @@ class SigninManagerBase {
// Send all observers |GoogleSignedOut| notifications.
void FireGoogleSignedOut(const AccountInfo& account_info);
+
+ // OAuth2TokenServiceObserver:
+ void OnRefreshTokensLoaded() override;
#endif
SigninClient* client_;
@@ -241,16 +198,26 @@ class SigninManagerBase {
bool initialized_;
// Account id after successful authentication.
- std::string authenticated_account_id_;
+ CoreAccountId authenticated_account_id_;
+
+ // Callbacks which will be invoked, if set, for signin-related events.
+ AccountSigninCallback on_google_signin_succeeded_callback_;
+#if !defined(OS_CHROMEOS)
+ AccountSigninCallback on_google_signed_out_callback_;
+#endif
+ AccountSigninCallback on_authenticated_account_set_callback_;
+ AccountClearedCallback on_authenticated_account_cleared_callback_;
// The list of callbacks notified on shutdown.
base::CallbackList<void()> on_shutdown_callback_list_;
+#if !defined(OS_CHROMEOS)
signin::AccountConsistencyMethod account_consistency_;
+#endif
- base::WeakPtrFactory<SigninManagerBase> weak_pointer_factory_;
+ std::unique_ptr<PrimaryAccountPolicyManager> policy_manager_;
- DISALLOW_COPY_AND_ASSIGN(SigninManagerBase);
+ DISALLOW_COPY_AND_ASSIGN(PrimaryAccountManager);
};
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_BASE_H_
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PRIMARY_ACCOUNT_MANAGER_H_
diff --git a/chromium/components/signin/core/browser/signin_manager_unittest.cc b/chromium/components/signin/internal/identity_manager/primary_account_manager_unittest.cc
index f6f77f798d4..8549cd814ff 100644
--- a/chromium/components/signin/core/browser/signin_manager_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/primary_account_manager_unittest.cc
@@ -2,87 +2,62 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/signin_manager.h"
+#include "components/signin/internal/identity_manager/primary_account_manager.h"
#include <memory>
+#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/compiler_specific.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
-#include "build/build_config.h"
#include "components/image_fetcher/core/fake_image_decoder.h"
-#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/prefs/testing_pref_service.h"
-#include "components/signin/core/browser/account_consistency_method.h"
-#include "components/signin/core/browser/account_fetcher_service.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/device_id_helper.h"
-#include "components/signin/core/browser/gaia_cookie_manager_service.h"
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "components/signin/core/browser/test_signin_client.h"
+#include "components/signin/internal/identity_manager/account_fetcher_service.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.h"
+#include "components/signin/internal/identity_manager/primary_account_policy_manager.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/base/test_signin_client.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "google_apis/gaia/fake_oauth2_token_service_delegate.h"
-#include "google_apis/gaia/gaia_urls.h"
-#include "net/cookies/cookie_monster.h"
-#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-namespace {
+#if !defined(OS_CHROMEOS)
+#include "components/signin/internal/identity_manager/primary_account_policy_manager_impl.h"
+#endif
-class TestSigninManagerObserver : public SigninManagerBase::Observer {
+class PrimaryAccountManagerTest : public testing::Test {
public:
- TestSigninManagerObserver() : num_successful_signins_(0), num_signouts_(0) {}
-
- ~TestSigninManagerObserver() override {}
-
- int num_successful_signins_;
- int num_signouts_;
-
- private:
- void GoogleSigninSucceeded(const AccountInfo& account_info) override {
- num_successful_signins_++;
- }
-
- void GoogleSignedOut(const AccountInfo& account_info) override {
- num_signouts_++;
- }
-};
-
-} // namespace
-
-class SigninManagerTest : public testing::Test {
- public:
- SigninManagerTest()
+ PrimaryAccountManagerTest()
: test_signin_client_(&user_prefs_),
- token_service_(&user_prefs_,
- std::make_unique<FakeOAuth2TokenServiceDelegate>()),
- cookie_manager_service_(&token_service_, &test_signin_client_),
- account_consistency_(signin::AccountConsistencyMethod::kDisabled) {
+ token_service_(
+ &user_prefs_,
+ std::make_unique<FakeProfileOAuth2TokenServiceDelegate>()),
+ account_consistency_(signin::AccountConsistencyMethod::kDisabled),
+ num_successful_signins_(0),
+ num_signouts_(0) {
AccountFetcherService::RegisterPrefs(user_prefs_.registry());
AccountTrackerService::RegisterPrefs(user_prefs_.registry());
ProfileOAuth2TokenService::RegisterProfilePrefs(user_prefs_.registry());
- SigninManagerBase::RegisterProfilePrefs(user_prefs_.registry());
- SigninManagerBase::RegisterPrefs(local_state_.registry());
+ PrimaryAccountManager::RegisterProfilePrefs(user_prefs_.registry());
+ PrimaryAccountManager::RegisterPrefs(local_state_.registry());
account_tracker_.Initialize(&user_prefs_, base::FilePath());
account_fetcher_.Initialize(
&test_signin_client_, &token_service_, &account_tracker_,
std::make_unique<image_fetcher::FakeImageDecoder>());
}
- ~SigninManagerTest() override {
+ ~PrimaryAccountManagerTest() override {
if (manager_) {
ShutDownManager();
}
token_service_.Shutdown();
test_signin_client_.Shutdown();
- cookie_manager_service_.Shutdown();
account_tracker_.Shutdown();
account_fetcher_.Shutdown();
}
@@ -94,28 +69,46 @@ class SigninManagerTest : public testing::Test {
PrefService* prefs() { return &user_prefs_; }
// Seed the account tracker with information from logged in user. Normally
- // this is done by UI code before calling SigninManager. Returns the string
- // to use as the account_id.
- std::string AddToAccountTracker(const std::string& gaia_id,
- const std::string& email) {
+ // this is done by UI code before calling PrimaryAccountManager.
+ // Returns the string to use as the account_id.
+ CoreAccountId AddToAccountTracker(const std::string& gaia_id,
+ const std::string& email) {
account_tracker_.SeedAccountInfo(gaia_id, email);
return account_tracker_.PickAccountIdForAccount(gaia_id, email);
}
- // Create a naked signin manager if integration with PKSs is not needed.
- void CreateSigninManager() {
+ void CreatePrimaryAccountManager() {
DCHECK(!manager_);
- manager_ = std::make_unique<SigninManager>(
+ // Supply the primary account manager with a policy manager to reflect
+ // production usage: null on ChromeOS, a PrimaryAccountPolicyManagerImpl on
+ // other platforms.
+ std::unique_ptr<PrimaryAccountPolicyManager> policy_manager;
+#if !defined(OS_CHROMEOS)
+ policy_manager =
+ std::make_unique<PrimaryAccountPolicyManagerImpl>(&test_signin_client_);
+ policy_manager_ =
+ static_cast<PrimaryAccountPolicyManagerImpl*>(policy_manager.get());
+#endif
+
+ manager_ = std::make_unique<PrimaryAccountManager>(
&test_signin_client_, &token_service_, &account_tracker_,
- &cookie_manager_service_, account_consistency_);
+ account_consistency_, std::move(policy_manager));
manager_->Initialize(&local_state_);
- manager_->SetObserver(&test_observer_);
+
+ // PrimaryAccountManagerTest will outlive the PrimaryAccountManager, so
+ // base::Unretained is safe.
+ manager_->SetGoogleSigninSucceededCallback(
+ base::BindRepeating(&PrimaryAccountManagerTest::GoogleSigninSucceeded,
+ base::Unretained(this)));
+#if !defined(OS_CHROMEOS)
+ manager_->SetGoogleSignedOutCallback(base::BindRepeating(
+ &PrimaryAccountManagerTest::GoogleSignedOut, base::Unretained(this)));
+#endif
}
// Shuts down |manager_|.
void ShutDownManager() {
DCHECK(manager_);
- manager_->ClearObserver();
manager_.reset();
}
@@ -128,27 +121,37 @@ class SigninManagerTest : public testing::Test {
manager_->GetAuthenticatedAccountId()));
// Should go into token service and stop.
- EXPECT_EQ(1, test_observer_.num_successful_signins_);
+ EXPECT_EQ(1, num_successful_signins_);
}
+ void GoogleSigninSucceeded(const AccountInfo& account_info) {
+ num_successful_signins_++;
+ }
+
+ void GoogleSignedOut(const AccountInfo& account_info) { num_signouts_++; }
+
base::test::ScopedTaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable user_prefs_;
TestingPrefServiceSimple local_state_;
TestSigninClient test_signin_client_;
ProfileOAuth2TokenService token_service_;
AccountTrackerService account_tracker_;
- GaiaCookieManagerService cookie_manager_service_;
AccountFetcherService account_fetcher_;
- std::unique_ptr<SigninManager> manager_;
- TestSigninManagerObserver test_observer_;
+#if !defined(OS_CHROMEOS)
+ PrimaryAccountPolicyManagerImpl* policy_manager_;
+#endif
+ std::unique_ptr<PrimaryAccountManager> manager_;
std::vector<std::string> oauth_tokens_fetched_;
std::vector<std::string> cookies_;
signin::AccountConsistencyMethod account_consistency_;
+ int num_successful_signins_;
+ int num_signouts_;
};
-TEST_F(SigninManagerTest, SignOut) {
- CreateSigninManager();
- std::string main_account_id =
+#if !defined(OS_CHROMEOS)
+TEST_F(PrimaryAccountManagerTest, SignOut) {
+ CreatePrimaryAccountManager();
+ CoreAccountId main_account_id =
AddToAccountTracker("account_id", "user@gmail.com");
manager_->SignIn("user@gmail.com");
manager_->SignOut(signin_metrics::SIGNOUT_TEST,
@@ -158,17 +161,17 @@ TEST_F(SigninManagerTest, SignOut) {
EXPECT_TRUE(manager_->GetAuthenticatedAccountId().empty());
// Should not be persisted anymore
ShutDownManager();
- CreateSigninManager();
+ CreatePrimaryAccountManager();
EXPECT_FALSE(manager_->IsAuthenticated());
EXPECT_TRUE(manager_->GetAuthenticatedAccountInfo().email.empty());
EXPECT_TRUE(manager_->GetAuthenticatedAccountId().empty());
}
-TEST_F(SigninManagerTest, SignOutRevoke) {
- CreateSigninManager();
- std::string main_account_id =
+TEST_F(PrimaryAccountManagerTest, SignOutRevoke) {
+ CreatePrimaryAccountManager();
+ CoreAccountId main_account_id =
AddToAccountTracker("main_id", "user@gmail.com");
- std::string other_account_id =
+ CoreAccountId other_account_id =
AddToAccountTracker("other_id", "other@gmail.com");
token_service_.UpdateCredentials(main_account_id, "token");
token_service_.UpdateCredentials(other_account_id, "token");
@@ -184,12 +187,12 @@ TEST_F(SigninManagerTest, SignOutRevoke) {
EXPECT_TRUE(token_service_.GetAccounts().empty());
}
-TEST_F(SigninManagerTest, SignOutDiceNoRevoke) {
+TEST_F(PrimaryAccountManagerTest, SignOutDiceNoRevoke) {
account_consistency_ = signin::AccountConsistencyMethod::kDice;
- CreateSigninManager();
- std::string main_account_id =
+ CreatePrimaryAccountManager();
+ CoreAccountId main_account_id =
AddToAccountTracker("main_id", "user@gmail.com");
- std::string other_account_id =
+ CoreAccountId other_account_id =
AddToAccountTracker("other_id", "other@gmail.com");
token_service_.UpdateCredentials(main_account_id, "token");
token_service_.UpdateCredentials(other_account_id, "token");
@@ -202,14 +205,14 @@ TEST_F(SigninManagerTest, SignOutDiceNoRevoke) {
// Tokens are not revoked.
EXPECT_FALSE(manager_->IsAuthenticated());
- std::vector<std::string> expected_tokens = {main_account_id,
- other_account_id};
+ std::vector<CoreAccountId> expected_tokens = {main_account_id,
+ other_account_id};
EXPECT_EQ(expected_tokens, token_service_.GetAccounts());
}
-TEST_F(SigninManagerTest, SignOutDiceWithError) {
+TEST_F(PrimaryAccountManagerTest, SignOutDiceWithError) {
account_consistency_ = signin::AccountConsistencyMethod::kDice;
- CreateSigninManager();
+ CreatePrimaryAccountManager();
std::string main_account_id =
AddToAccountTracker("main_id", "user@gmail.com");
std::string other_account_id =
@@ -233,12 +236,12 @@ TEST_F(SigninManagerTest, SignOutDiceWithError) {
// Only main token is revoked.
EXPECT_FALSE(manager_->IsAuthenticated());
- std::vector<std::string> expected_tokens = {other_account_id};
+ std::vector<CoreAccountId> expected_tokens = {other_account_id};
EXPECT_EQ(expected_tokens, token_service_.GetAccounts());
}
-TEST_F(SigninManagerTest, SignOutWhileProhibited) {
- CreateSigninManager();
+TEST_F(PrimaryAccountManagerTest, SignOutWhileProhibited) {
+ CreatePrimaryAccountManager();
EXPECT_FALSE(manager_->IsAuthenticated());
EXPECT_TRUE(manager_->GetAuthenticatedAccountInfo().email.empty());
EXPECT_TRUE(manager_->GetAuthenticatedAccountId().empty());
@@ -254,44 +257,21 @@ TEST_F(SigninManagerTest, SignOutWhileProhibited) {
EXPECT_FALSE(manager_->IsAuthenticated());
}
-TEST_F(SigninManagerTest, Prohibited) {
- local_state_.SetString(prefs::kGoogleServicesUsernamePattern,
- ".*@google.com");
- CreateSigninManager();
- EXPECT_TRUE(manager_->IsAllowedUsername("test@google.com"));
- EXPECT_TRUE(manager_->IsAllowedUsername("happy@google.com"));
- EXPECT_FALSE(manager_->IsAllowedUsername("test@invalid.com"));
- EXPECT_FALSE(manager_->IsAllowedUsername("test@notgoogle.com"));
- EXPECT_FALSE(manager_->IsAllowedUsername(std::string()));
-}
-
-TEST_F(SigninManagerTest, TestAlternateWildcard) {
- // Test to make sure we accept "*@google.com" as a pattern (treat it as if
- // the admin entered ".*@google.com").
- local_state_.SetString(prefs::kGoogleServicesUsernamePattern, "*@google.com");
- CreateSigninManager();
- EXPECT_TRUE(manager_->IsAllowedUsername("test@google.com"));
- EXPECT_TRUE(manager_->IsAllowedUsername("happy@google.com"));
- EXPECT_FALSE(manager_->IsAllowedUsername("test@invalid.com"));
- EXPECT_FALSE(manager_->IsAllowedUsername("test@notgoogle.com"));
- EXPECT_FALSE(manager_->IsAllowedUsername(std::string()));
-}
-
-TEST_F(SigninManagerTest, ProhibitedAtStartup) {
+TEST_F(PrimaryAccountManagerTest, ProhibitedAtStartup) {
std::string account_id = AddToAccountTracker("gaia_id", "user@gmail.com");
user_prefs_.SetString(prefs::kGoogleServicesAccountId, account_id);
local_state_.SetString(prefs::kGoogleServicesUsernamePattern,
".*@google.com");
- CreateSigninManager();
+ CreatePrimaryAccountManager();
// Currently signed in user is prohibited by policy, so should be signed out.
EXPECT_EQ("", manager_->GetAuthenticatedAccountInfo().email);
EXPECT_EQ("", manager_->GetAuthenticatedAccountId());
}
-TEST_F(SigninManagerTest, ProhibitedAfterStartup) {
+TEST_F(PrimaryAccountManagerTest, ProhibitedAfterStartup) {
std::string account_id = AddToAccountTracker("gaia_id", "user@gmail.com");
user_prefs_.SetString(prefs::kGoogleServicesAccountId, account_id);
- CreateSigninManager();
+ CreatePrimaryAccountManager();
EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedAccountInfo().email);
EXPECT_EQ(account_id, manager_->GetAuthenticatedAccountId());
// Update the profile - user should be signed out.
@@ -300,53 +280,57 @@ TEST_F(SigninManagerTest, ProhibitedAfterStartup) {
EXPECT_EQ("", manager_->GetAuthenticatedAccountInfo().email);
EXPECT_EQ("", manager_->GetAuthenticatedAccountId());
}
+#endif
-TEST_F(SigninManagerTest, ExternalSignIn) {
- CreateSigninManager();
+TEST_F(PrimaryAccountManagerTest, ExternalSignIn) {
+ CreatePrimaryAccountManager();
EXPECT_EQ("", manager_->GetAuthenticatedAccountInfo().email);
EXPECT_EQ("", manager_->GetAuthenticatedAccountId());
- EXPECT_EQ(0, test_observer_.num_successful_signins_);
+ EXPECT_EQ(0, num_successful_signins_);
std::string account_id = AddToAccountTracker("gaia_id", "user@gmail.com");
manager_->SignIn("user@gmail.com");
- EXPECT_EQ(1, test_observer_.num_successful_signins_);
+ EXPECT_EQ(1, num_successful_signins_);
EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedAccountInfo().email);
EXPECT_EQ(account_id, manager_->GetAuthenticatedAccountId());
}
-TEST_F(SigninManagerTest, ExternalSignIn_ReauthShouldNotSendNotification) {
- CreateSigninManager();
+TEST_F(PrimaryAccountManagerTest,
+ ExternalSignIn_ReauthShouldNotSendNotification) {
+ CreatePrimaryAccountManager();
EXPECT_EQ("", manager_->GetAuthenticatedAccountInfo().email);
EXPECT_EQ("", manager_->GetAuthenticatedAccountId());
- EXPECT_EQ(0, test_observer_.num_successful_signins_);
+ EXPECT_EQ(0, num_successful_signins_);
std::string account_id = AddToAccountTracker("gaia_id", "user@gmail.com");
manager_->SignIn("user@gmail.com");
- EXPECT_EQ(1, test_observer_.num_successful_signins_);
+ EXPECT_EQ(1, num_successful_signins_);
EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedAccountInfo().email);
EXPECT_EQ(account_id, manager_->GetAuthenticatedAccountId());
manager_->SignIn("user@gmail.com");
- EXPECT_EQ(1, test_observer_.num_successful_signins_);
+ EXPECT_EQ(1, num_successful_signins_);
EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedAccountInfo().email);
EXPECT_EQ(account_id, manager_->GetAuthenticatedAccountId());
}
-TEST_F(SigninManagerTest, SigninNotAllowed) {
+#if !defined(OS_CHROMEOS)
+TEST_F(PrimaryAccountManagerTest, SigninNotAllowed) {
std::string user("user@google.com");
std::string account_id = AddToAccountTracker("gaia_id", user);
user_prefs_.SetString(prefs::kGoogleServicesAccountId, account_id);
user_prefs_.SetBoolean(prefs::kSigninAllowed, false);
- CreateSigninManager();
+ CreatePrimaryAccountManager();
// Currently signing in is prohibited by policy, so should be signed out.
EXPECT_EQ("", manager_->GetAuthenticatedAccountInfo().email);
EXPECT_EQ("", manager_->GetAuthenticatedAccountId());
}
+#endif
-TEST_F(SigninManagerTest, UpgradeToNewPrefs) {
+TEST_F(PrimaryAccountManagerTest, UpgradeToNewPrefs) {
user_prefs_.SetString(prefs::kGoogleServicesUsername, "user@gmail.com");
user_prefs_.SetString(prefs::kGoogleServicesUserAccountId, "account_id");
- CreateSigninManager();
+ CreatePrimaryAccountManager();
EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedAccountInfo().email);
if (account_tracker()->GetMigrationState() ==
@@ -370,13 +354,13 @@ TEST_F(SigninManagerTest, UpgradeToNewPrefs) {
EXPECT_EQ("account_id", info.gaia);
}
-TEST_F(SigninManagerTest, CanonicalizesPrefs) {
+TEST_F(PrimaryAccountManagerTest, CanonicalizesPrefs) {
// This unit test is not needed after migrating to gaia id.
if (account_tracker()->GetMigrationState() ==
AccountTrackerService::MIGRATION_NOT_STARTED) {
user_prefs_.SetString(prefs::kGoogleServicesUsername, "user.C@gmail.com");
- CreateSigninManager();
+ CreatePrimaryAccountManager();
EXPECT_EQ("user.C@gmail.com",
manager_->GetAuthenticatedAccountInfo().email);
@@ -395,7 +379,7 @@ TEST_F(SigninManagerTest, CanonicalizesPrefs) {
}
}
-TEST_F(SigninManagerTest, GaiaIdMigration) {
+TEST_F(PrimaryAccountManagerTest, GaiaIdMigration) {
if (account_tracker()->GetMigrationState() !=
AccountTrackerService::MIGRATION_NOT_STARTED) {
std::string email = "user@gmail.com";
@@ -417,14 +401,14 @@ TEST_F(SigninManagerTest, GaiaIdMigration) {
client_prefs->SetString(prefs::kGoogleServicesAccountId, email);
- CreateSigninManager();
+ CreatePrimaryAccountManager();
EXPECT_EQ(gaia_id, manager_->GetAuthenticatedAccountId());
EXPECT_EQ(gaia_id, user_prefs_.GetString(prefs::kGoogleServicesAccountId));
}
}
-TEST_F(SigninManagerTest, VeryOldProfileGaiaIdMigration) {
+TEST_F(PrimaryAccountManagerTest, VeryOldProfileGaiaIdMigration) {
if (account_tracker()->GetMigrationState() !=
AccountTrackerService::MIGRATION_NOT_STARTED) {
std::string email = "user@gmail.com";
@@ -447,13 +431,13 @@ TEST_F(SigninManagerTest, VeryOldProfileGaiaIdMigration) {
client_prefs->ClearPref(prefs::kGoogleServicesAccountId);
client_prefs->SetString(prefs::kGoogleServicesUsername, email);
- CreateSigninManager();
+ CreatePrimaryAccountManager();
EXPECT_EQ(gaia_id, manager_->GetAuthenticatedAccountId());
EXPECT_EQ(gaia_id, user_prefs_.GetString(prefs::kGoogleServicesAccountId));
}
}
-TEST_F(SigninManagerTest, GaiaIdMigrationCrashInTheMiddle) {
+TEST_F(PrimaryAccountManagerTest, GaiaIdMigrationCrashInTheMiddle) {
if (account_tracker()->GetMigrationState() !=
AccountTrackerService::MIGRATION_NOT_STARTED) {
std::string email = "user@gmail.com";
@@ -475,7 +459,7 @@ TEST_F(SigninManagerTest, GaiaIdMigrationCrashInTheMiddle) {
client_prefs->SetString(prefs::kGoogleServicesAccountId, gaia_id);
- CreateSigninManager();
+ CreatePrimaryAccountManager();
EXPECT_EQ(gaia_id, manager_->GetAuthenticatedAccountId());
EXPECT_EQ(gaia_id, user_prefs_.GetString(prefs::kGoogleServicesAccountId));
diff --git a/chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.cc b/chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.cc
new file mode 100644
index 00000000000..f9d1eba03ec
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.cc
@@ -0,0 +1,90 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/internal/identity_manager/primary_account_mutator_impl.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "components/prefs/pref_service.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/primary_account_manager.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "google_apis/gaia/core_account_id.h"
+
+namespace signin {
+
+PrimaryAccountMutatorImpl::PrimaryAccountMutatorImpl(
+ AccountTrackerService* account_tracker,
+ PrimaryAccountManager* primary_account_manager,
+ PrefService* pref_service)
+ : account_tracker_(account_tracker),
+ primary_account_manager_(primary_account_manager),
+ pref_service_(pref_service) {
+ DCHECK(account_tracker_);
+ DCHECK(primary_account_manager_);
+ DCHECK(pref_service_);
+}
+
+PrimaryAccountMutatorImpl::~PrimaryAccountMutatorImpl() {}
+
+bool PrimaryAccountMutatorImpl::SetPrimaryAccount(
+ const CoreAccountId& account_id) {
+ AccountInfo account_info = account_tracker_->GetAccountInfo(account_id);
+
+#if !defined(OS_CHROMEOS)
+ if (!pref_service_->GetBoolean(prefs::kSigninAllowed))
+ return false;
+
+ if (primary_account_manager_->IsAuthenticated())
+ return false;
+
+ if (account_info.account_id != account_id || account_info.email.empty())
+ return false;
+
+ // TODO(crbug.com/889899): should check that the account email is allowed.
+#endif
+
+ primary_account_manager_->SignIn(account_info.email);
+ return true;
+}
+
+#if defined(OS_CHROMEOS)
+bool PrimaryAccountMutatorImpl::SetPrimaryAccountAndUpdateAccountInfo(
+ const std::string& gaia_id,
+ const std::string& email) {
+ CoreAccountId account_id = account_tracker_->SeedAccountInfo(gaia_id, email);
+ SetPrimaryAccount(account_id);
+ return true;
+}
+#endif
+
+#if !defined(OS_CHROMEOS)
+bool PrimaryAccountMutatorImpl::ClearPrimaryAccount(
+ ClearAccountsAction action,
+ signin_metrics::ProfileSignout source_metric,
+ signin_metrics::SignoutDelete delete_metric) {
+ if (!primary_account_manager_->IsAuthenticated())
+ return false;
+
+ switch (action) {
+ case PrimaryAccountMutator::ClearAccountsAction::kDefault:
+ primary_account_manager_->SignOut(source_metric, delete_metric);
+ break;
+ case PrimaryAccountMutator::ClearAccountsAction::kKeepAll:
+ primary_account_manager_->SignOutAndKeepAllAccounts(source_metric,
+ delete_metric);
+ break;
+ case PrimaryAccountMutator::ClearAccountsAction::kRemoveAll:
+ primary_account_manager_->SignOutAndRemoveAllAccounts(source_metric,
+ delete_metric);
+ break;
+ }
+
+ return true;
+}
+#endif
+
+} // namespace signin
diff --git a/chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.h b/chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.h
new file mode 100644
index 00000000000..f15e6c13f9b
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.h
@@ -0,0 +1,50 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PRIMARY_ACCOUNT_MUTATOR_IMPL_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PRIMARY_ACCOUNT_MUTATOR_IMPL_H_
+
+#include <string>
+
+#include "components/signin/public/identity_manager/primary_account_mutator.h"
+
+class AccountTrackerService;
+class PrefService;
+class PrimaryAccountManager;
+
+namespace signin {
+
+// Concrete implementation of PrimaryAccountMutator that is based on the
+// PrimaryAccountManager API.
+class PrimaryAccountMutatorImpl : public PrimaryAccountMutator {
+ public:
+ PrimaryAccountMutatorImpl(AccountTrackerService* account_tracker,
+ PrimaryAccountManager* primary_account_manager,
+ PrefService* pref_service);
+ ~PrimaryAccountMutatorImpl() override;
+
+ // PrimaryAccountMutator implementation.
+ bool SetPrimaryAccount(const CoreAccountId& account_id) override;
+#if defined(OS_CHROMEOS)
+ bool SetPrimaryAccountAndUpdateAccountInfo(const std::string& gaia_id,
+ const std::string& email) override;
+#endif
+#if !defined(OS_CHROMEOS)
+ bool ClearPrimaryAccount(
+ ClearAccountsAction action,
+ signin_metrics::ProfileSignout source_metric,
+ signin_metrics::SignoutDelete delete_metric) override;
+#endif
+
+ private:
+ // Pointers to the services used by the PrimaryAccountMutatorImpl. They
+ // *must* outlive this instance.
+ AccountTrackerService* account_tracker_ = nullptr;
+ PrimaryAccountManager* primary_account_manager_ = nullptr;
+ PrefService* pref_service_ = nullptr;
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PRIMARY_ACCOUNT_MUTATOR_IMPL_H_
diff --git a/chromium/components/signin/internal/identity_manager/primary_account_policy_manager.h b/chromium/components/signin/internal/identity_manager/primary_account_policy_manager.h
new file mode 100644
index 00000000000..d5e1537a39b
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/primary_account_policy_manager.h
@@ -0,0 +1,29 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PRIMARY_ACCOUNT_POLICY_MANAGER_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PRIMARY_ACCOUNT_POLICY_MANAGER_H_
+
+#include "base/macros.h"
+
+class PrefService;
+class PrimaryAccountManager;
+
+class PrimaryAccountPolicyManager {
+ public:
+ PrimaryAccountPolicyManager() = default;
+ virtual ~PrimaryAccountPolicyManager() = default;
+
+ // On platforms where PrimaryAccountManager is responsible for dealing with
+ // invalid username policy updates, we need to check this during
+ // initialization and sign the user out.
+ virtual void InitializePolicy(
+ PrefService* local_state,
+ PrimaryAccountManager* primary_account_manager) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PrimaryAccountPolicyManager);
+};
+
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PRIMARY_ACCOUNT_POLICY_MANAGER_H_
diff --git a/chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl.cc b/chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl.cc
new file mode 100644
index 00000000000..426aa6b4daf
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl.cc
@@ -0,0 +1,107 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/internal/identity_manager/primary_account_policy_manager_impl.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "components/signin/internal/identity_manager/primary_account_manager.h"
+#include "components/signin/public/base/signin_client.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/identity_manager/account_info.h"
+#include "components/signin/public/identity_manager/identity_utils.h"
+
+PrimaryAccountPolicyManagerImpl::PrimaryAccountPolicyManagerImpl(
+ SigninClient* client)
+ : client_(client) {}
+
+PrimaryAccountPolicyManagerImpl::~PrimaryAccountPolicyManagerImpl() {
+ local_state_pref_registrar_.RemoveAll();
+}
+
+void PrimaryAccountPolicyManagerImpl::InitializePolicy(
+ PrefService* local_state,
+ PrimaryAccountManager* primary_account_manager) {
+ // local_state can be null during unit tests.
+ if (local_state) {
+ local_state_pref_registrar_.Init(local_state);
+ local_state_pref_registrar_.Add(
+ prefs::kGoogleServicesUsernamePattern,
+ base::Bind(&PrimaryAccountPolicyManagerImpl::
+ OnGoogleServicesUsernamePatternChanged,
+ weak_pointer_factory_.GetWeakPtr(),
+ primary_account_manager));
+ }
+ signin_allowed_.Init(
+ prefs::kSigninAllowed, client_->GetPrefs(),
+ base::Bind(&PrimaryAccountPolicyManagerImpl::OnSigninAllowedPrefChanged,
+ base::Unretained(this), primary_account_manager));
+
+ AccountInfo account_info =
+ primary_account_manager->GetAuthenticatedAccountInfo();
+ if (!account_info.account_id.empty() &&
+ (!IsAllowedUsername(account_info.email) || !IsSigninAllowed())) {
+ // User is signed in, but the username is invalid or signin is no longer
+ // allowed, so the user must be sign out.
+ //
+ // This may happen in the following cases:
+ // a. The user has toggled off signin allowed in settings.
+ // b. The administrator changed the policy since the last signin.
+ //
+ // Note: The token service has not yet loaded its credentials, so accounts
+ // cannot be revoked here.
+ //
+ // On desktop, when PrimaryAccountManager is initializing, the profile was
+ // not yet marked with sign out allowed. Therefore sign out is not allowed
+ // and all calls to SignOut methods are no-op.
+ //
+ // TODO(msarda): SignOut methods do not guarantee that sign out can actually
+ // be done (this depends on whether sign out is allowed). Add a check here
+ // on desktop to make it clear that SignOut does not do anything.
+ primary_account_manager->SignOutAndKeepAllAccounts(
+ signin_metrics::SIGNIN_PREF_CHANGED_DURING_SIGNIN,
+ signin_metrics::SignoutDelete::IGNORE_METRIC);
+ }
+}
+
+void PrimaryAccountPolicyManagerImpl::OnGoogleServicesUsernamePatternChanged(
+ PrimaryAccountManager* primary_account_manager) {
+ if (primary_account_manager->IsAuthenticated() &&
+ !IsAllowedUsername(
+ primary_account_manager->GetAuthenticatedAccountInfo().email)) {
+ // Signed in user is invalid according to the current policy so sign
+ // the user out.
+ primary_account_manager->SignOut(
+ signin_metrics::GOOGLE_SERVICE_NAME_PATTERN_CHANGED,
+ signin_metrics::SignoutDelete::IGNORE_METRIC);
+ }
+}
+
+bool PrimaryAccountPolicyManagerImpl::IsSigninAllowed() const {
+ return signin_allowed_.GetValue();
+}
+
+void PrimaryAccountPolicyManagerImpl::OnSigninAllowedPrefChanged(
+ PrimaryAccountManager* primary_account_manager) {
+ if (!IsSigninAllowed() && primary_account_manager->IsAuthenticated()) {
+ VLOG(0) << "IsSigninAllowed() set to false, signing out the user";
+ primary_account_manager->SignOut(
+ signin_metrics::SIGNOUT_PREF_CHANGED,
+ signin_metrics::SignoutDelete::IGNORE_METRIC);
+ }
+}
+
+bool PrimaryAccountPolicyManagerImpl::IsAllowedUsername(
+ const std::string& username) const {
+ const PrefService* local_state = local_state_pref_registrar_.prefs();
+
+ // TODO(crbug.com/908121): We need to deal for now with the fact that many
+ // unit tests have a null |local_state| passed to InitializePolicy(), in which
+ // case all usernames are considered 'allowed'.
+ if (!local_state)
+ return true;
+
+ return signin::IsUsernameAllowedByPatternFromPrefs(local_state, username);
+}
diff --git a/chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl.h b/chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl.h
new file mode 100644
index 00000000000..43bce6d345b
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl.h
@@ -0,0 +1,62 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PRIMARY_ACCOUNT_POLICY_MANAGER_IMPL_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PRIMARY_ACCOUNT_POLICY_MANAGER_IMPL_H_
+
+#include <string>
+
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/prefs/pref_change_registrar.h"
+#include "components/prefs/pref_member.h"
+#include "components/signin/internal/identity_manager/primary_account_policy_manager.h"
+
+class PrefService;
+class PrimaryAccountManager;
+class SigninClient;
+
+class PrimaryAccountPolicyManagerImpl : public PrimaryAccountPolicyManager {
+ public:
+ explicit PrimaryAccountPolicyManagerImpl(SigninClient* client);
+ ~PrimaryAccountPolicyManagerImpl() override;
+
+ // PrimaryAccountPolicyManager:
+ void InitializePolicy(
+ PrefService* local_state,
+ PrimaryAccountManager* primary_account_manager) override;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(PrimaryAccountPolicyManagerImplTest, Prohibited);
+ FRIEND_TEST_ALL_PREFIXES(PrimaryAccountPolicyManagerImplTest,
+ TestAlternateWildcard);
+
+ // Returns true if a signin to Chrome is allowed (by policy or pref).
+ bool IsSigninAllowed() const;
+
+ void OnSigninAllowedPrefChanged(
+ PrimaryAccountManager* primary_account_manager);
+ void OnGoogleServicesUsernamePatternChanged(
+ PrimaryAccountManager* primary_account_manager);
+
+ // Returns true if the passed username is allowed by policy.
+ bool IsAllowedUsername(const std::string& username) const;
+
+ SigninClient* client_;
+
+ // Helper object to listen for changes to signin preferences stored in non-
+ // profile-specific local prefs (like kGoogleServicesUsernamePattern).
+ PrefChangeRegistrar local_state_pref_registrar_;
+
+ // Helper object to listen for changes to the signin allowed preference.
+ BooleanPrefMember signin_allowed_;
+
+ base::WeakPtrFactory<PrimaryAccountPolicyManagerImpl> weak_pointer_factory_{
+ this};
+
+ DISALLOW_COPY_AND_ASSIGN(PrimaryAccountPolicyManagerImpl);
+};
+
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PRIMARY_ACCOUNT_POLICY_MANAGER_IMPL_H_
diff --git a/chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl_unittest.cc b/chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl_unittest.cc
new file mode 100644
index 00000000000..282eab2ec0e
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl_unittest.cc
@@ -0,0 +1,75 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/internal/identity_manager/primary_account_policy_manager_impl.h"
+
+#include <memory>
+#include <string>
+
+#include "base/test/scoped_task_environment.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.h"
+#include "components/signin/internal/identity_manager/primary_account_manager.h"
+#include "components/signin/internal/identity_manager/primary_account_policy_manager_impl.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/base/test_signin_client.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class PrimaryAccountPolicyManagerImplTest : public testing::Test {
+ public:
+ PrimaryAccountPolicyManagerImplTest()
+ : test_signin_client_(&user_prefs_),
+ token_service_(
+ &user_prefs_,
+ std::make_unique<FakeProfileOAuth2TokenServiceDelegate>()),
+ primary_account_manager_(&test_signin_client_,
+ &token_service_,
+ &account_tracker_,
+ signin::AccountConsistencyMethod::kDisabled,
+ nullptr /*policy_manager*/),
+ policy_manager_(&test_signin_client_) {
+ PrimaryAccountManager::RegisterProfilePrefs(user_prefs_.registry());
+ PrimaryAccountManager::RegisterPrefs(local_state_.registry());
+
+ policy_manager_.InitializePolicy(&local_state_, &primary_account_manager_);
+ }
+
+ ~PrimaryAccountPolicyManagerImplTest() override {
+ test_signin_client_.Shutdown();
+ }
+
+ base::test::ScopedTaskEnvironment task_environment_;
+ sync_preferences::TestingPrefServiceSyncable user_prefs_;
+ TestingPrefServiceSimple local_state_;
+ TestSigninClient test_signin_client_;
+ ProfileOAuth2TokenService token_service_;
+ AccountTrackerService account_tracker_;
+ PrimaryAccountManager primary_account_manager_;
+ PrimaryAccountPolicyManagerImpl policy_manager_;
+};
+
+TEST_F(PrimaryAccountPolicyManagerImplTest, Prohibited) {
+ local_state_.SetString(prefs::kGoogleServicesUsernamePattern,
+ ".*@google.com");
+ EXPECT_TRUE(policy_manager_.IsAllowedUsername("test@google.com"));
+ EXPECT_TRUE(policy_manager_.IsAllowedUsername("happy@google.com"));
+ EXPECT_FALSE(policy_manager_.IsAllowedUsername("test@invalid.com"));
+ EXPECT_FALSE(policy_manager_.IsAllowedUsername("test@notgoogle.com"));
+ EXPECT_FALSE(policy_manager_.IsAllowedUsername(std::string()));
+}
+
+TEST_F(PrimaryAccountPolicyManagerImplTest, TestAlternateWildcard) {
+ // Test to make sure we accept "*@google.com" as a pattern (treat it as if
+ // the admin entered ".*@google.com").
+ local_state_.SetString(prefs::kGoogleServicesUsernamePattern, "*@google.com");
+ EXPECT_TRUE(policy_manager_.IsAllowedUsername("test@google.com"));
+ EXPECT_TRUE(policy_manager_.IsAllowedUsername("happy@google.com"));
+ EXPECT_FALSE(policy_manager_.IsAllowedUsername("test@invalid.com"));
+ EXPECT_FALSE(policy_manager_.IsAllowedUsername("test@notgoogle.com"));
+ EXPECT_FALSE(policy_manager_.IsAllowedUsername(std::string()));
+}
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.cc b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.cc
new file mode 100644
index 00000000000..6d4f5c1d584
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.cc
@@ -0,0 +1,476 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+
+#include "base/auto_reset.h"
+#include "base/logging.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
+#include "components/signin/public/base/device_id_helper.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "google_apis/gaia/oauth2_access_token_consumer.h"
+#include "google_apis/gaia/oauth2_access_token_fetcher.h"
+#include "google_apis/gaia/oauth2_access_token_manager.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+using signin_metrics::SourceForRefreshTokenOperation;
+
+namespace {
+std::string SourceToString(SourceForRefreshTokenOperation source) {
+ switch (source) {
+ case SourceForRefreshTokenOperation::kUnknown:
+ return "Unknown";
+ case SourceForRefreshTokenOperation::kTokenService_LoadCredentials:
+ return "TokenService::LoadCredentials";
+ case SourceForRefreshTokenOperation::kSupervisedUser_InitSync:
+ return "SupervisedUser::InitSync";
+ case SourceForRefreshTokenOperation::kInlineLoginHandler_Signin:
+ return "InlineLoginHandler::Signin";
+ case SourceForRefreshTokenOperation::kPrimaryAccountManager_ClearAccount:
+ return "PrimaryAccountManager::ClearAccount";
+ case SourceForRefreshTokenOperation::
+ kPrimaryAccountManager_LegacyPreDiceSigninFlow:
+ return "PrimaryAccountManager::LegacyPreDiceSigninFlow";
+ case SourceForRefreshTokenOperation::kUserMenu_RemoveAccount:
+ return "UserMenu::RemoveAccount";
+ case SourceForRefreshTokenOperation::kUserMenu_SignOutAllAccounts:
+ return "UserMenu::SignOutAllAccounts";
+ case SourceForRefreshTokenOperation::kSettings_Signout:
+ return "Settings::Signout";
+ case SourceForRefreshTokenOperation::kSettings_PauseSync:
+ return "Settings::PauseSync";
+ case SourceForRefreshTokenOperation::
+ kAccountReconcilor_GaiaCookiesDeletedByUser:
+ return "AccountReconcilor::GaiaCookiesDeletedByUser";
+ case SourceForRefreshTokenOperation::kAccountReconcilor_GaiaCookiesUpdated:
+ return "AccountReconcilor::GaiaCookiesUpdated";
+ case SourceForRefreshTokenOperation::kAccountReconcilor_Reconcile:
+ return "AccountReconcilor::Reconcile";
+ case SourceForRefreshTokenOperation::kDiceResponseHandler_Signin:
+ return "DiceResponseHandler::Signin";
+ case SourceForRefreshTokenOperation::kDiceResponseHandler_Signout:
+ return "DiceResponseHandler::Signout";
+ case SourceForRefreshTokenOperation::kDiceTurnOnSyncHelper_Abort:
+ return "DiceTurnOnSyncHelper::Abort";
+ case SourceForRefreshTokenOperation::kMachineLogon_CredentialProvider:
+ return "MachineLogon::CredentialProvider";
+ case SourceForRefreshTokenOperation::kTokenService_ExtractCredentials:
+ return "TokenService::ExtractCredentials";
+ }
+}
+} // namespace
+
+ProfileOAuth2TokenService::ProfileOAuth2TokenService(
+ PrefService* user_prefs,
+ std::unique_ptr<ProfileOAuth2TokenServiceDelegate> delegate)
+ : user_prefs_(user_prefs),
+ delegate_(std::move(delegate)),
+ all_credentials_loaded_(false) {
+ DCHECK(user_prefs_);
+ DCHECK(delegate_);
+ token_manager_ = std::make_unique<OAuth2AccessTokenManager>(
+ this /* OAuth2AccessTokenManager::Delegate* */);
+ AddObserver(this);
+}
+
+ProfileOAuth2TokenService::~ProfileOAuth2TokenService() {
+ RemoveObserver(this);
+}
+
+std::unique_ptr<OAuth2AccessTokenFetcher>
+ProfileOAuth2TokenService::CreateAccessTokenFetcher(
+ const CoreAccountId& account_id,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ OAuth2AccessTokenConsumer* consumer) {
+ return delegate_->CreateAccessTokenFetcher(account_id, url_loader_factory,
+ consumer);
+}
+
+bool ProfileOAuth2TokenService::FixRequestErrorIfPossible() {
+ return delegate_->FixRequestErrorIfPossible();
+}
+
+scoped_refptr<network::SharedURLLoaderFactory>
+ProfileOAuth2TokenService::GetURLLoaderFactory() const {
+ return delegate_->GetURLLoaderFactory();
+}
+
+void ProfileOAuth2TokenService::OnAccessTokenInvalidated(
+ const CoreAccountId& account_id,
+ const std::string& client_id,
+ const std::set<std::string>& scopes,
+ const std::string& access_token) {
+ delegate_->OnAccessTokenInvalidated(account_id, client_id, scopes,
+ access_token);
+}
+
+void ProfileOAuth2TokenService::OnAccessTokenFetched(
+ const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error) {
+ // Update the auth error state so auth errors are appropriately communicated
+ // to the user.
+ delegate_->UpdateAuthError(account_id, error);
+}
+
+bool ProfileOAuth2TokenService::HasRefreshToken(
+ const CoreAccountId& account_id) const {
+ return RefreshTokenIsAvailable(account_id);
+}
+
+// static
+void ProfileOAuth2TokenService::RegisterProfilePrefs(
+ PrefRegistrySimple* registry) {
+#if defined(OS_IOS)
+ registry->RegisterBooleanPref(prefs::kTokenServiceExcludeAllSecondaryAccounts,
+ false);
+ registry->RegisterListPref(prefs::kTokenServiceExcludedSecondaryAccounts);
+#endif
+ registry->RegisterStringPref(prefs::kGoogleServicesSigninScopedDeviceId,
+ std::string());
+}
+
+ProfileOAuth2TokenServiceDelegate* ProfileOAuth2TokenService::GetDelegate() {
+ return delegate_.get();
+}
+
+const ProfileOAuth2TokenServiceDelegate*
+ProfileOAuth2TokenService::GetDelegate() const {
+ return delegate_.get();
+}
+
+void ProfileOAuth2TokenService::AddObserver(
+ OAuth2TokenServiceObserver* observer) {
+ delegate_->AddObserver(observer);
+}
+
+void ProfileOAuth2TokenService::RemoveObserver(
+ OAuth2TokenServiceObserver* observer) {
+ delegate_->RemoveObserver(observer);
+}
+
+void ProfileOAuth2TokenService::AddAccessTokenDiagnosticsObserver(
+ OAuth2AccessTokenManager::DiagnosticsObserver* observer) {
+ token_manager_->AddDiagnosticsObserver(observer);
+}
+
+void ProfileOAuth2TokenService::RemoveAccessTokenDiagnosticsObserver(
+ OAuth2AccessTokenManager::DiagnosticsObserver* observer) {
+ token_manager_->RemoveDiagnosticsObserver(observer);
+}
+
+std::unique_ptr<OAuth2AccessTokenManager::Request>
+ProfileOAuth2TokenService::StartRequest(
+ const CoreAccountId& account_id,
+ const OAuth2AccessTokenManager::ScopeSet& scopes,
+ OAuth2AccessTokenManager::Consumer* consumer) {
+ return token_manager_->StartRequest(account_id, scopes, consumer);
+}
+
+std::unique_ptr<OAuth2AccessTokenManager::Request>
+ProfileOAuth2TokenService::StartRequestForMultilogin(
+ const CoreAccountId& account_id,
+ OAuth2AccessTokenManager::Consumer* consumer) {
+ const std::string refresh_token =
+ delegate_->GetTokenForMultilogin(account_id);
+ if (refresh_token.empty()) {
+ // If we can't get refresh token from the delegate, start request for access
+ // token.
+ OAuth2AccessTokenManager::ScopeSet scopes;
+ scopes.insert(GaiaConstants::kOAuth1LoginScope);
+ return token_manager_->StartRequest(account_id, scopes, consumer);
+ }
+ std::unique_ptr<OAuth2AccessTokenManager::RequestImpl> request(
+ new OAuth2AccessTokenManager::RequestImpl(account_id, consumer));
+ // Create token response from token. Expiration time and id token do not
+ // matter and should not be accessed.
+ OAuth2AccessTokenConsumer::TokenResponse token_response(
+ refresh_token, base::Time(), std::string());
+ // If we can get refresh token from the delegate, inform consumer right away.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&OAuth2AccessTokenManager::RequestImpl::InformConsumer,
+ request.get()->AsWeakPtr(),
+ GoogleServiceAuthError(GoogleServiceAuthError::NONE),
+ token_response));
+ return std::move(request);
+}
+
+std::unique_ptr<OAuth2AccessTokenManager::Request>
+ProfileOAuth2TokenService::StartRequestForClient(
+ const CoreAccountId& account_id,
+ const std::string& client_id,
+ const std::string& client_secret,
+ const OAuth2AccessTokenManager::ScopeSet& scopes,
+ OAuth2AccessTokenManager::Consumer* consumer) {
+ return token_manager_->StartRequestForClient(account_id, client_id,
+ client_secret, scopes, consumer);
+}
+
+std::unique_ptr<OAuth2AccessTokenManager::Request>
+ProfileOAuth2TokenService::StartRequestWithContext(
+ const CoreAccountId& account_id,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ const OAuth2AccessTokenManager::ScopeSet& scopes,
+ OAuth2AccessTokenManager::Consumer* consumer) {
+ return token_manager_->StartRequestWithContext(account_id, url_loader_factory,
+ scopes, consumer);
+}
+
+void ProfileOAuth2TokenService::InvalidateAccessToken(
+ const CoreAccountId& account_id,
+ const OAuth2AccessTokenManager::ScopeSet& scopes,
+ const std::string& access_token) {
+ token_manager_->InvalidateAccessToken(account_id, scopes, access_token);
+}
+
+void ProfileOAuth2TokenService::InvalidateTokenForMultilogin(
+ const CoreAccountId& failed_account,
+ const std::string& token) {
+ OAuth2AccessTokenManager::ScopeSet scopes;
+ scopes.insert(GaiaConstants::kOAuth1LoginScope);
+ // Remove from cache. This will have no effect on desktop since token is a
+ // refresh token and is not in cache.
+ InvalidateAccessToken(failed_account, scopes, token);
+ // For desktop refresh tokens can be invalidated directly in delegate. This
+ // will have no effect on mobile.
+ delegate_->InvalidateTokenForMultilogin(failed_account);
+}
+
+void ProfileOAuth2TokenService::SetRefreshTokenAvailableFromSourceCallback(
+ RefreshTokenAvailableFromSourceCallback callback) {
+ on_refresh_token_available_callback_ = callback;
+}
+
+void ProfileOAuth2TokenService::SetRefreshTokenRevokedFromSourceCallback(
+ RefreshTokenRevokedFromSourceCallback callback) {
+ on_refresh_token_revoked_callback_ = callback;
+}
+
+void ProfileOAuth2TokenService::Shutdown() {
+ CancelAllRequests();
+ GetDelegate()->Shutdown();
+}
+
+void ProfileOAuth2TokenService::LoadCredentials(
+ const CoreAccountId& primary_account_id) {
+ DCHECK_EQ(SourceForRefreshTokenOperation::kUnknown,
+ update_refresh_token_source_);
+ update_refresh_token_source_ =
+ SourceForRefreshTokenOperation::kTokenService_LoadCredentials;
+ GetDelegate()->LoadCredentials(primary_account_id);
+}
+
+void ProfileOAuth2TokenService::UpdateCredentials(
+ const CoreAccountId& account_id,
+ const std::string& refresh_token,
+ SourceForRefreshTokenOperation source) {
+ base::AutoReset<SourceForRefreshTokenOperation> auto_reset(
+ &update_refresh_token_source_, source);
+ GetDelegate()->UpdateCredentials(account_id, refresh_token);
+}
+
+void ProfileOAuth2TokenService::RevokeCredentials(
+ const CoreAccountId& account_id,
+ SourceForRefreshTokenOperation source) {
+ base::AutoReset<SourceForRefreshTokenOperation> auto_reset(
+ &update_refresh_token_source_, source);
+ GetDelegate()->RevokeCredentials(account_id);
+}
+
+void ProfileOAuth2TokenService::RevokeAllCredentials(
+ SourceForRefreshTokenOperation source) {
+ base::AutoReset<SourceForRefreshTokenOperation> auto_reset(
+ &update_refresh_token_source_, source);
+ CancelAllRequests();
+ ClearCache();
+ GetDelegate()->RevokeAllCredentials();
+}
+
+const net::BackoffEntry* ProfileOAuth2TokenService::GetDelegateBackoffEntry() {
+ return GetDelegate()->BackoffEntry();
+}
+
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+void ProfileOAuth2TokenService::ExtractCredentials(
+ ProfileOAuth2TokenService* to_service,
+ const CoreAccountId& account_id) {
+ base::AutoReset<SourceForRefreshTokenOperation> auto_reset(
+ &update_refresh_token_source_,
+ SourceForRefreshTokenOperation::kTokenService_ExtractCredentials);
+ GetDelegate()->ExtractCredentials(to_service, account_id);
+}
+#endif
+
+bool ProfileOAuth2TokenService::AreAllCredentialsLoaded() const {
+ return all_credentials_loaded_;
+}
+
+std::vector<CoreAccountId> ProfileOAuth2TokenService::GetAccounts() const {
+ if (!AreAllCredentialsLoaded())
+ return std::vector<CoreAccountId>();
+
+ return GetDelegate()->GetAccounts();
+}
+
+bool ProfileOAuth2TokenService::RefreshTokenIsAvailable(
+ const CoreAccountId& account_id) const {
+ return delegate_->RefreshTokenIsAvailable(account_id);
+}
+
+bool ProfileOAuth2TokenService::RefreshTokenHasError(
+ const CoreAccountId& account_id) const {
+ return GetAuthError(account_id) != GoogleServiceAuthError::AuthErrorNone();
+}
+
+GoogleServiceAuthError ProfileOAuth2TokenService::GetAuthError(
+ const CoreAccountId& account_id) const {
+ GoogleServiceAuthError error = delegate_->GetAuthError(account_id);
+ DCHECK(!error.IsTransientError());
+ return error;
+}
+
+void ProfileOAuth2TokenService::UpdateAuthErrorForTesting(
+ const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error) {
+ GetDelegate()->UpdateAuthError(account_id, error);
+}
+
+int ProfileOAuth2TokenService::GetTokenCacheCountForTesting() {
+ return token_manager_->token_cache().size();
+}
+
+void ProfileOAuth2TokenService::
+ set_max_authorization_token_fetch_retries_for_testing(int max_retries) {
+ token_manager_->set_max_authorization_token_fetch_retries_for_testing(
+ max_retries);
+}
+
+size_t ProfileOAuth2TokenService::GetNumPendingRequestsForTesting(
+ const std::string& client_id,
+ const CoreAccountId& account_id,
+ const OAuth2AccessTokenManager::ScopeSet& scopes) const {
+ return token_manager_->GetNumPendingRequestsForTesting(client_id, account_id,
+ scopes);
+}
+
+void ProfileOAuth2TokenService::OverrideAccessTokenManagerForTesting(
+ std::unique_ptr<OAuth2AccessTokenManager> token_manager) {
+ token_manager_ = std::move(token_manager);
+}
+
+OAuth2AccessTokenManager* ProfileOAuth2TokenService::GetAccessTokenManager() {
+ return token_manager_.get();
+}
+
+void ProfileOAuth2TokenService::OnRefreshTokenAvailable(
+ const CoreAccountId& account_id) {
+ // Check if the newly-updated token is valid (invalid tokens are inserted when
+ // the user signs out on the web with DICE enabled).
+ bool is_valid = true;
+ GoogleServiceAuthError token_error = GetAuthError(account_id);
+ if (token_error == GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
+ GoogleServiceAuthError::InvalidGaiaCredentialsReason::
+ CREDENTIALS_REJECTED_BY_CLIENT)) {
+ is_valid = false;
+ }
+
+ CancelRequestsForAccount(account_id);
+ ClearCacheForAccount(account_id);
+
+ signin_metrics::RecordRefreshTokenUpdatedFromSource(
+ is_valid, update_refresh_token_source_);
+
+ std::string source_string = SourceToString(update_refresh_token_source_);
+ if (on_refresh_token_available_callback_)
+ on_refresh_token_available_callback_.Run(account_id, is_valid,
+ source_string);
+}
+
+void ProfileOAuth2TokenService::OnRefreshTokenRevoked(
+ const CoreAccountId& account_id) {
+ // If this was the last token, recreate the device ID.
+ RecreateDeviceIdIfNeeded();
+
+ CancelRequestsForAccount(account_id);
+ ClearCacheForAccount(account_id);
+
+ signin_metrics::RecordRefreshTokenRevokedFromSource(
+ update_refresh_token_source_);
+ std::string source_string = SourceToString(update_refresh_token_source_);
+ if (on_refresh_token_revoked_callback_)
+ on_refresh_token_revoked_callback_.Run(account_id, source_string);
+}
+
+void ProfileOAuth2TokenService::OnRefreshTokensLoaded() {
+ all_credentials_loaded_ = true;
+
+ DCHECK_NE(signin::LoadCredentialsState::LOAD_CREDENTIALS_NOT_STARTED,
+ GetDelegate()->load_credentials_state());
+ DCHECK_NE(signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS,
+ GetDelegate()->load_credentials_state());
+
+ // Reset the state for update refresh token operations to Unknown as this
+ // was the original state before LoadCredentials was called.
+ update_refresh_token_source_ = SourceForRefreshTokenOperation::kUnknown;
+
+ // Ensure the device ID is not empty, and recreate it if all tokens were
+ // cleared during the loading process.
+ RecreateDeviceIdIfNeeded();
+}
+
+void ProfileOAuth2TokenService::ClearCache() {
+ token_manager_->ClearCache();
+}
+
+void ProfileOAuth2TokenService::ClearCacheForAccount(
+ const CoreAccountId& account_id) {
+ token_manager_->ClearCacheForAccount(account_id);
+}
+
+void ProfileOAuth2TokenService::CancelAllRequests() {
+ token_manager_->CancelAllRequests();
+}
+
+void ProfileOAuth2TokenService::CancelRequestsForAccount(
+ const CoreAccountId& account_id) {
+ token_manager_->CancelRequestsForAccount(account_id);
+}
+
+bool ProfileOAuth2TokenService::HasLoadCredentialsFinishedWithNoErrors() {
+ switch (GetDelegate()->load_credentials_state()) {
+ case signin::LoadCredentialsState::LOAD_CREDENTIALS_NOT_STARTED:
+ case signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS:
+ // LoadCredentials has not finished.
+ return false;
+ case signin::LoadCredentialsState::
+ LOAD_CREDENTIALS_FINISHED_WITH_DB_CANNOT_BE_OPENED:
+ case signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_DB_ERRORS:
+ case signin::LoadCredentialsState::
+ LOAD_CREDENTIALS_FINISHED_WITH_DECRYPT_ERRORS:
+ case signin::LoadCredentialsState::
+ LOAD_CREDENTIALS_FINISHED_WITH_UNKNOWN_ERRORS:
+ // LoadCredentials finished, but with errors
+ return false;
+ case signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS:
+ case signin::LoadCredentialsState::
+ LOAD_CREDENTIALS_FINISHED_WITH_NO_TOKEN_FOR_PRIMARY_ACCOUNT:
+ // Load credentials finished with success.
+ return true;
+ }
+}
+
+void ProfileOAuth2TokenService::RecreateDeviceIdIfNeeded() {
+// On ChromeOS the device ID is not managed by the token service.
+#if !defined(OS_CHROMEOS)
+ if (AreAllCredentialsLoaded() && HasLoadCredentialsFinishedWithNoErrors() &&
+ GetAccounts().empty()) {
+ signin::RecreateSigninScopedDeviceId(user_prefs_);
+ }
+#endif
+}
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.h b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.h
new file mode 100644
index 00000000000..44a08697caa
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.h
@@ -0,0 +1,320 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_H_
+
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "build/buildflag.h"
+#include "components/signin/public/base/signin_buildflags.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "google_apis/gaia/core_account_id.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "google_apis/gaia/oauth2_access_token_manager.h"
+#include "google_apis/gaia/oauth2_token_service_observer.h"
+#include "net/base/backoff_entry.h"
+
+namespace signin {
+class IdentityManager;
+}
+
+class PrefService;
+class PrefRegistrySimple;
+class OAuth2AccessTokenConsumer;
+class ProfileOAuth2TokenServiceDelegate;
+
+// ProfileOAuth2TokenService is a KeyedService that retrieves
+// OAuth2 access tokens for a given set of scopes using the OAuth2 login
+// refresh tokens.
+//
+// To use this service, call StartRequest() with a given set of scopes and a
+// consumer of the request results. The consumer is required to outlive the
+// request. The request can be deleted. The consumer may be called back
+// asynchronously with the fetch results.
+//
+// - If the consumer is not called back before the request is deleted, it will
+// never be called back.
+// Note in this case, the actual network requests are not canceled and the
+// cache will be populated with the fetched results; it is just the consumer
+// callback that is aborted.
+//
+// - Otherwise the consumer will be called back with the request and the fetch
+// results.
+//
+// The caller of StartRequest() owns the returned request and is responsible to
+// delete the request even once the callback has been invoked.
+//
+// Note: after StartRequest returns, in-flight requests will continue
+// even if the TokenService refresh token that was used to initiate
+// the request changes or is cleared. When the request completes,
+// Consumer::OnGetTokenSuccess will be invoked, but the access token
+// won't be cached.
+//
+// Note: requests should be started from the UI thread.
+class ProfileOAuth2TokenService : public OAuth2AccessTokenManager::Delegate,
+ public OAuth2TokenServiceObserver {
+ public:
+ typedef base::RepeatingCallback<void(const CoreAccountId& /* account_id */,
+ bool /* is_refresh_token_valid */,
+ const std::string& /* source */)>
+ RefreshTokenAvailableFromSourceCallback;
+ typedef base::RepeatingCallback<void(const CoreAccountId& /* account_id */,
+ const std::string& /* source */)>
+ RefreshTokenRevokedFromSourceCallback;
+
+ ProfileOAuth2TokenService(
+ PrefService* user_prefs,
+ std::unique_ptr<ProfileOAuth2TokenServiceDelegate> delegate);
+ ~ProfileOAuth2TokenService() override;
+
+ // Overridden from OAuth2AccessTokenManager::Delegate.
+ std::unique_ptr<OAuth2AccessTokenFetcher> CreateAccessTokenFetcher(
+ const CoreAccountId& account_id,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ OAuth2AccessTokenConsumer* consumer) override;
+ bool HasRefreshToken(const CoreAccountId& account_id) const override;
+ bool FixRequestErrorIfPossible() override;
+ scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory()
+ const override;
+ void OnAccessTokenInvalidated(const CoreAccountId& account_id,
+ const std::string& client_id,
+ const std::set<std::string>& scopes,
+ const std::string& access_token) override;
+ void OnAccessTokenFetched(const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error) override;
+
+ // Registers per-profile prefs.
+ static void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
+ ProfileOAuth2TokenServiceDelegate* GetDelegate();
+ const ProfileOAuth2TokenServiceDelegate* GetDelegate() const;
+
+ // Add or remove observers of this token service.
+ void AddObserver(OAuth2TokenServiceObserver* observer);
+ void RemoveObserver(OAuth2TokenServiceObserver* observer);
+
+ // Add or remove observers of access token manager.
+ void AddAccessTokenDiagnosticsObserver(
+ OAuth2AccessTokenManager::DiagnosticsObserver* observer);
+ void RemoveAccessTokenDiagnosticsObserver(
+ OAuth2AccessTokenManager::DiagnosticsObserver* observer);
+
+ // Checks in the cache for a valid access token for a specified |account_id|
+ // and |scopes|, and if not found starts a request for an OAuth2 access token
+ // using the OAuth2 refresh token maintained by this instance for that
+ // |account_id|. The caller owns the returned Request.
+ // |scopes| is the set of scopes to get an access token for, |consumer| is
+ // the object that will be called back with results if the returned request
+ // is not deleted.
+ std::unique_ptr<OAuth2AccessTokenManager::Request> StartRequest(
+ const CoreAccountId& account_id,
+ const OAuth2AccessTokenManager::ScopeSet& scopes,
+ OAuth2AccessTokenManager::Consumer* consumer);
+
+ // Try to get refresh token from delegate. If it is accessible (i.e. not
+ // empty), return it directly, otherwise start request to get access token.
+ // Used for getting tokens to send to Gaia Multilogin endpoint.
+ std::unique_ptr<OAuth2AccessTokenManager::Request> StartRequestForMultilogin(
+ const CoreAccountId& account_id,
+ OAuth2AccessTokenManager::Consumer* consumer);
+
+ // This method does the same as |StartRequest| except it uses |client_id| and
+ // |client_secret| to identify OAuth client app instead of using
+ // Chrome's default values.
+ std::unique_ptr<OAuth2AccessTokenManager::Request> StartRequestForClient(
+ const CoreAccountId& account_id,
+ const std::string& client_id,
+ const std::string& client_secret,
+ const OAuth2AccessTokenManager::ScopeSet& scopes,
+ OAuth2AccessTokenManager::Consumer* consumer);
+
+ // This method does the same as |StartRequest| except it uses the
+ // URLLoaderFactory given by |url_loader_factory| instead of using the one
+ // returned by Delegate::GetURLLoaderFactory().
+ std::unique_ptr<OAuth2AccessTokenManager::Request> StartRequestWithContext(
+ const CoreAccountId& account_id,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ const OAuth2AccessTokenManager::ScopeSet& scopes,
+ OAuth2AccessTokenManager::Consumer* consumer);
+
+ // Mark an OAuth2 |access_token| issued for |account_id| and |scopes| as
+ // invalid. This should be done if the token was received from this class,
+ // but was not accepted by the server (e.g., the server returned
+ // 401 Unauthorized). The token will be removed from the cache for the given
+ // scopes.
+ void InvalidateAccessToken(const CoreAccountId& account_id,
+ const OAuth2AccessTokenManager::ScopeSet& scopes,
+ const std::string& access_token);
+
+ // Removes token from cache (if it is cached) and calls
+ // InvalidateTokenForMultilogin method of the delegate. This should be done if
+ // the token was received from this class, but was not accepted by the server
+ // (e.g., the server returned 401 Unauthorized).
+ virtual void InvalidateTokenForMultilogin(const CoreAccountId& failed_account,
+ const std::string& token);
+
+ // If set, this callback will be invoked when a new refresh token is
+ // available. Contains diagnostic information about the source of the update
+ // credentials operation.
+ void SetRefreshTokenAvailableFromSourceCallback(
+ RefreshTokenAvailableFromSourceCallback callback);
+
+ // If set, this callback will be invoked when a refresh token is revoked.
+ // Contains diagnostic information about the source that initiated the
+ // revocation operation.
+ void SetRefreshTokenRevokedFromSourceCallback(
+ RefreshTokenRevokedFromSourceCallback callback);
+
+ void Shutdown();
+
+ // Loads credentials from a backing persistent store to make them available
+ // after service is used between profile restarts.
+ //
+ // The primary account is specified with the |primary_account_id| argument.
+ // For a regular profile, the primary account id comes from
+ // PrimaryAccountManager.
+ // For a supervised user, the id comes from SupervisedUserService.
+ void LoadCredentials(const CoreAccountId& primary_account_id);
+
+ // Returns true if LoadCredentials finished with no errors.
+ bool HasLoadCredentialsFinishedWithNoErrors();
+
+ // Updates a |refresh_token| for an |account_id|. Credentials are persisted,
+ // and available through |LoadCredentials| after service is restarted.
+ void UpdateCredentials(
+ const CoreAccountId& account_id,
+ const std::string& refresh_token,
+ signin_metrics::SourceForRefreshTokenOperation source =
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+
+ void RevokeCredentials(
+ const CoreAccountId& account_id,
+ signin_metrics::SourceForRefreshTokenOperation source =
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+
+ // Revokes all credentials.
+ void RevokeAllCredentials(
+ signin_metrics::SourceForRefreshTokenOperation source =
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+
+ // Returns a pointer to its instance of net::BackoffEntry or nullptr if there
+ // is no such instance.
+ const net::BackoffEntry* GetDelegateBackoffEntry();
+
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+ // Removes the credentials associated to account_id from the internal storage,
+ // and moves them to |to_service|. The credentials are not revoked on the
+ // server, but the OnRefreshTokenRevoked() notification is sent to the
+ // observers.
+ void ExtractCredentials(ProfileOAuth2TokenService* to_service,
+ const CoreAccountId& account_id);
+#endif
+
+ // Returns true iff all credentials have been loaded from disk.
+ bool AreAllCredentialsLoaded() const;
+
+ void set_all_credentials_loaded_for_testing(bool loaded) {
+ all_credentials_loaded_ = loaded;
+ }
+
+ // Lists account IDs of all accounts with a refresh token maintained by this
+ // instance.
+ // Note: For each account returned by |GetAccounts|, |RefreshTokenIsAvailable|
+ // will return true.
+ // Note: If tokens have not been fully loaded yet, an empty list is returned.
+ std::vector<CoreAccountId> GetAccounts() const;
+
+ // Returns true if a refresh token exists for |account_id|. If false, calls to
+ // |StartRequest| will result in a Consumer::OnGetTokenFailure callback.
+ // Note: This will return |true| if and only if |account_id| is contained in
+ // the list returned by |GetAccounts|.
+ bool RefreshTokenIsAvailable(const CoreAccountId& account_id) const;
+
+ // Returns true if a refresh token exists for |account_id| and it is in a
+ // persistent error state.
+ bool RefreshTokenHasError(const CoreAccountId& account_id) const;
+
+ // Returns the auth error associated with |account_id|. Only persistent errors
+ // will be returned.
+ GoogleServiceAuthError GetAuthError(const CoreAccountId& account_id) const;
+
+ // Exposes the ability to update auth errors to tests.
+ void UpdateAuthErrorForTesting(const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error);
+
+ int GetTokenCacheCountForTesting();
+
+ void set_max_authorization_token_fetch_retries_for_testing(int max_retries);
+
+ // Returns the current number of pending fetchers matching given params.
+ size_t GetNumPendingRequestsForTesting(
+ const std::string& client_id,
+ const CoreAccountId& account_id,
+ const OAuth2AccessTokenManager::ScopeSet& scopes) const;
+
+ // Override |token_manager_| for testing.
+ void OverrideAccessTokenManagerForTesting(
+ std::unique_ptr<OAuth2AccessTokenManager> token_manager);
+
+ protected:
+ OAuth2AccessTokenManager* GetAccessTokenManager();
+
+ private:
+ friend class signin::IdentityManager;
+
+ // OAuth2TokenServiceObserver implementation.
+ void OnRefreshTokenAvailable(const CoreAccountId& account_id) override;
+ void OnRefreshTokenRevoked(const CoreAccountId& account_id) override;
+ void OnRefreshTokensLoaded() override;
+
+ // Clears the internal token cache.
+ void ClearCache();
+
+ // Clears all of the tokens belonging to |account_id| from the internal token
+ // cache. It does not matter what other parameters, like |client_id| were
+ // used to request the tokens.
+ void ClearCacheForAccount(const CoreAccountId& account_id);
+
+ // Cancels all requests that are currently in progress.
+ void CancelAllRequests();
+
+ // Cancels all requests related to a given |account_id|.
+ void CancelRequestsForAccount(const CoreAccountId& account_id);
+
+ // Creates a new device ID if there are no accounts, or if the current device
+ // ID is empty.
+ void RecreateDeviceIdIfNeeded();
+
+ PrefService* user_prefs_;
+
+ std::unique_ptr<ProfileOAuth2TokenServiceDelegate> delegate_;
+
+ // Whether all credentials have been loaded.
+ bool all_credentials_loaded_;
+
+ std::unique_ptr<OAuth2AccessTokenManager> token_manager_;
+
+ // Callbacks to invoke, if set, for refresh token-related events.
+ RefreshTokenAvailableFromSourceCallback on_refresh_token_available_callback_;
+ RefreshTokenRevokedFromSourceCallback on_refresh_token_revoked_callback_;
+
+ signin_metrics::SourceForRefreshTokenOperation update_refresh_token_source_ =
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown;
+
+ FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceTest, UpdateClearsCache);
+ FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceTest, CancelAllRequests);
+ FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceTest,
+ CancelRequestsForAccount);
+
+ DISALLOW_COPY_AND_ASSIGN(ProfileOAuth2TokenService);
+};
+
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_H_
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc
new file mode 100644
index 00000000000..7c95f143435
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc
@@ -0,0 +1,214 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_builder.h"
+
+#include <string>
+#include <utility>
+
+#include "components/prefs/pref_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/base/device_id_helper.h"
+#include "components/signin/public/base/signin_client.h"
+
+#if defined(OS_ANDROID)
+#include "components/signin/internal/identity_manager/oauth2_token_service_delegate_android.h"
+#else
+#include "components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.h"
+#include "components/signin/public/webdata/token_web_data.h"
+#endif
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/components/account_manager/account_manager.h"
+#include "chromeos/constants/chromeos_switches.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.h"
+#include "components/user_manager/user_manager.h"
+#endif // defined(OS_CHROMEOS)
+
+#if defined(OS_IOS)
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h"
+#include "components/signin/public/identity_manager/ios/device_accounts_provider.h"
+#endif
+
+namespace {
+
+#if defined(OS_ANDROID)
+std::unique_ptr<OAuth2TokenServiceDelegateAndroid> CreateAndroidOAuthDelegate(
+ AccountTrackerService* account_tracker_service) {
+ return std::make_unique<OAuth2TokenServiceDelegateAndroid>(
+ account_tracker_service);
+}
+#elif defined(OS_IOS)
+std::unique_ptr<ProfileOAuth2TokenServiceIOSDelegate> CreateIOSOAuthDelegate(
+ SigninClient* signin_client,
+ std::unique_ptr<DeviceAccountsProvider> device_accounts_provider,
+ AccountTrackerService* account_tracker_service) {
+ return std::make_unique<ProfileOAuth2TokenServiceIOSDelegate>(
+ signin_client, std::move(device_accounts_provider),
+ account_tracker_service);
+}
+#else // !defined(OS_ANDROID) && !defined(OS_IOS)
+#if defined(OS_CHROMEOS)
+std::unique_ptr<signin::ProfileOAuth2TokenServiceDelegateChromeOS>
+CreateCrOsOAuthDelegate(
+ AccountTrackerService* account_tracker_service,
+ network::NetworkConnectionTracker* network_connection_tracker,
+ chromeos::AccountManager* account_manager,
+ bool is_regular_profile) {
+ DCHECK(account_manager);
+ return std::make_unique<signin::ProfileOAuth2TokenServiceDelegateChromeOS>(
+ account_tracker_service, network_connection_tracker, account_manager,
+ is_regular_profile);
+}
+#endif // defined(OS_CHROMEOS)
+
+// Supervised users cannot revoke credentials.
+bool CanRevokeCredentials() {
+#if defined(OS_CHROMEOS)
+ // UserManager may not exist in unit_tests.
+ if (user_manager::UserManager::IsInitialized() &&
+ user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser()) {
+ // Don't allow revoking credentials for Chrome OS supervised users.
+ // See http://crbug.com/332032
+ LOG(ERROR) << "Attempt to revoke supervised user refresh "
+ << "token detected, ignoring.";
+ return false;
+ }
+#endif
+
+ return true;
+}
+
+std::unique_ptr<MutableProfileOAuth2TokenServiceDelegate>
+CreateMutableProfileOAuthDelegate(
+ AccountTrackerService* account_tracker_service,
+ signin::AccountConsistencyMethod account_consistency,
+ bool delete_signin_cookies_on_exit,
+ scoped_refptr<TokenWebData> token_web_data,
+ SigninClient* signin_client,
+#if defined(OS_WIN)
+ MutableProfileOAuth2TokenServiceDelegate::FixRequestErrorCallback
+ reauth_callback,
+#endif
+ network::NetworkConnectionTracker* network_connection_tracker) {
+ // When signin cookies are cleared on exit and Dice is enabled, all tokens
+ // should also be cleared.
+ bool revoke_all_tokens_on_load =
+ (account_consistency == signin::AccountConsistencyMethod::kDice) &&
+ delete_signin_cookies_on_exit;
+
+ return std::make_unique<MutableProfileOAuth2TokenServiceDelegate>(
+ signin_client, account_tracker_service, network_connection_tracker,
+ token_web_data, account_consistency, revoke_all_tokens_on_load,
+ CanRevokeCredentials(),
+#if defined(OS_WIN)
+ reauth_callback
+#else
+ MutableProfileOAuth2TokenServiceDelegate::FixRequestErrorCallback()
+#endif // defined(OS_WIN)
+ );
+}
+#endif // defined(OS_ANDROID)
+
+std::unique_ptr<ProfileOAuth2TokenServiceDelegate>
+CreateOAuth2TokenServiceDelegate(
+ AccountTrackerService* account_tracker_service,
+ signin::AccountConsistencyMethod account_consistency,
+ SigninClient* signin_client,
+#if defined(OS_CHROMEOS)
+ chromeos::AccountManager* account_manager,
+ bool is_regular_profile,
+#endif
+#if !defined(OS_ANDROID)
+ bool delete_signin_cookies_on_exit,
+ scoped_refptr<TokenWebData> token_web_data,
+#endif
+#if defined(OS_IOS)
+ std::unique_ptr<DeviceAccountsProvider> device_accounts_provider,
+#endif
+#if defined(OS_WIN)
+ MutableProfileOAuth2TokenServiceDelegate::FixRequestErrorCallback
+ reauth_callback,
+#endif
+ network::NetworkConnectionTracker* network_connection_tracker) {
+#if defined(OS_ANDROID)
+ return CreateAndroidOAuthDelegate(account_tracker_service);
+#elif defined(OS_IOS)
+ return CreateIOSOAuthDelegate(signin_client,
+ std::move(device_accounts_provider),
+ account_tracker_service);
+#else // !defined(OS_ANDROID) && !defined(OS_IOS)
+#if defined(OS_CHROMEOS)
+ if (chromeos::switches::IsAccountManagerEnabled()) {
+ return CreateCrOsOAuthDelegate(account_tracker_service,
+ network_connection_tracker, account_manager,
+ is_regular_profile);
+ }
+#endif // defined(OS_CHROMEOS)
+ // Fall back to |MutableProfileOAuth2TokenServiceDelegate|:
+ // 1. On all platforms other than Android and Chrome OS.
+ // 2. On Chrome OS, if Account Manager has not been switched on yet
+ // (chromeos::switches::IsAccountManagerEnabled).
+ return CreateMutableProfileOAuthDelegate(
+ account_tracker_service, account_consistency,
+ delete_signin_cookies_on_exit, token_web_data, signin_client,
+#if defined(OS_WIN)
+ reauth_callback,
+#endif
+ network_connection_tracker);
+
+#endif // defined(OS_ANDROID)
+}
+
+} // namespace
+
+std::unique_ptr<ProfileOAuth2TokenService> BuildProfileOAuth2TokenService(
+ PrefService* pref_service,
+ AccountTrackerService* account_tracker_service,
+ network::NetworkConnectionTracker* network_connection_tracker,
+ signin::AccountConsistencyMethod account_consistency,
+#if defined(OS_CHROMEOS)
+ chromeos::AccountManager* account_manager,
+ bool is_regular_profile,
+#endif
+#if !defined(OS_ANDROID)
+ bool delete_signin_cookies_on_exit,
+ scoped_refptr<TokenWebData> token_web_data,
+#endif
+#if defined(OS_IOS)
+ std::unique_ptr<DeviceAccountsProvider> device_accounts_provider,
+#endif
+#if defined(OS_WIN)
+ MutableProfileOAuth2TokenServiceDelegate::FixRequestErrorCallback
+ reauth_callback,
+#endif
+ SigninClient* signin_client) {
+// On ChromeOS the device ID is not managed by the token service.
+#if !defined(OS_CHROMEOS)
+ // Ensure the device ID is not empty. This is important for Dice, because the
+ // device ID is needed on the network thread, but can only be generated on the
+ // main thread.
+ std::string device_id = signin::GetSigninScopedDeviceId(pref_service);
+ DCHECK(!device_id.empty());
+#endif
+
+ return std::make_unique<ProfileOAuth2TokenService>(
+ pref_service,
+ CreateOAuth2TokenServiceDelegate(
+ account_tracker_service, account_consistency, signin_client,
+#if defined(OS_CHROMEOS)
+ account_manager, is_regular_profile,
+#endif
+#if !defined(OS_ANDROID)
+ delete_signin_cookies_on_exit, token_web_data,
+#endif
+#if defined(OS_IOS)
+ std::move(device_accounts_provider),
+#endif
+#if defined(OS_WIN)
+ reauth_callback,
+#endif
+ network_connection_tracker));
+}
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.h b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.h
new file mode 100644
index 00000000000..c39bf35241e
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.h
@@ -0,0 +1,68 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_BUILDER_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_BUILDER_H_
+
+#include <memory>
+
+#include "build/build_config.h"
+
+#if !defined(OS_ANDROID)
+#include "base/memory/scoped_refptr.h"
+#endif
+
+#if defined(OS_WIN)
+#include "components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.h"
+#endif
+
+class AccountTrackerService;
+class PrefService;
+class ProfileOAuth2TokenService;
+class SigninClient;
+
+#if defined(OS_IOS)
+class DeviceAccountsProvider;
+#endif
+
+namespace signin {
+enum class AccountConsistencyMethod;
+}
+
+namespace network {
+class NetworkConnectionTracker;
+}
+
+#if !defined(OS_ANDROID)
+class TokenWebData;
+#endif
+
+#if defined(OS_CHROMEOS)
+namespace chromeos {
+class AccountManager;
+}
+#endif
+
+std::unique_ptr<ProfileOAuth2TokenService> BuildProfileOAuth2TokenService(
+ PrefService* pref_service,
+ AccountTrackerService* account_tracker_service,
+ network::NetworkConnectionTracker* network_connection_tracker,
+ signin::AccountConsistencyMethod account_consistency,
+#if defined(OS_CHROMEOS)
+ chromeos::AccountManager* account_manager,
+ bool is_regular_profile,
+#endif
+#if !defined(OS_ANDROID)
+ bool delete_signin_cookies_on_exit,
+ scoped_refptr<TokenWebData> token_web_data,
+#endif
+#if defined(OS_IOS)
+ std::unique_ptr<DeviceAccountsProvider> device_accounts_provider,
+#endif
+#if defined(OS_WIN)
+ MutableProfileOAuth2TokenServiceDelegate::FixRequestErrorCallback
+ reauth_callback,
+#endif
+ SigninClient* signin_client);
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_BUILDER_H_
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.cc b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.cc
new file mode 100644
index 00000000000..15c4384edfe
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.cc
@@ -0,0 +1,136 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
+
+#include "google_apis/gaia/oauth2_access_token_consumer.h"
+#include "google_apis/gaia/oauth2_token_service_observer.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+ProfileOAuth2TokenServiceDelegate::ScopedBatchChange::ScopedBatchChange(
+ ProfileOAuth2TokenServiceDelegate* delegate)
+ : delegate_(delegate) {
+ DCHECK(delegate_);
+ delegate_->StartBatchChanges();
+}
+
+ProfileOAuth2TokenServiceDelegate::ScopedBatchChange::~ScopedBatchChange() {
+ delegate_->EndBatchChanges();
+}
+
+ProfileOAuth2TokenServiceDelegate::ProfileOAuth2TokenServiceDelegate()
+ : batch_change_depth_(0) {}
+
+ProfileOAuth2TokenServiceDelegate::~ProfileOAuth2TokenServiceDelegate() =
+ default;
+
+bool ProfileOAuth2TokenServiceDelegate::ValidateAccountId(
+ const CoreAccountId& account_id) const {
+ bool valid = !account_id.empty();
+
+ // If the account is given as an email, make sure its a canonical email.
+ // Note that some tests don't use email strings as account id, and after
+ // the gaia id migration it won't be an email. So only check for
+ // canonicalization if the account_id is suspected to be an email.
+ if (account_id.id.find('@') != std::string::npos &&
+ gaia::CanonicalizeEmail(account_id.id) != account_id.id) {
+ valid = false;
+ }
+
+ DCHECK(valid);
+ return valid;
+}
+
+void ProfileOAuth2TokenServiceDelegate::AddObserver(
+ OAuth2TokenServiceObserver* observer) {
+ observer_list_.AddObserver(observer);
+}
+
+void ProfileOAuth2TokenServiceDelegate::RemoveObserver(
+ OAuth2TokenServiceObserver* observer) {
+ observer_list_.RemoveObserver(observer);
+}
+
+void ProfileOAuth2TokenServiceDelegate::StartBatchChanges() {
+ ++batch_change_depth_;
+}
+
+void ProfileOAuth2TokenServiceDelegate::EndBatchChanges() {
+ --batch_change_depth_;
+ DCHECK_LE(0, batch_change_depth_);
+ if (batch_change_depth_ == 0) {
+ for (auto& observer : observer_list_)
+ observer.OnEndBatchChanges();
+ }
+}
+
+void ProfileOAuth2TokenServiceDelegate::FireRefreshTokenAvailable(
+ const CoreAccountId& account_id) {
+ DCHECK(!account_id.empty());
+ for (auto& observer : observer_list_)
+ observer.OnRefreshTokenAvailable(account_id);
+}
+
+void ProfileOAuth2TokenServiceDelegate::FireRefreshTokenRevoked(
+ const CoreAccountId& account_id) {
+ DCHECK(!account_id.empty());
+ for (auto& observer : observer_list_)
+ observer.OnRefreshTokenRevoked(account_id);
+}
+
+void ProfileOAuth2TokenServiceDelegate::FireRefreshTokensLoaded() {
+ for (auto& observer : observer_list_)
+ observer.OnRefreshTokensLoaded();
+}
+
+void ProfileOAuth2TokenServiceDelegate::FireAuthErrorChanged(
+ const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error) {
+ DCHECK(!account_id.empty());
+ for (auto& observer : observer_list_)
+ observer.OnAuthErrorChanged(account_id, error);
+}
+
+std::string ProfileOAuth2TokenServiceDelegate::GetTokenForMultilogin(
+ const CoreAccountId& account_id) const {
+ return std::string();
+}
+
+scoped_refptr<network::SharedURLLoaderFactory>
+ProfileOAuth2TokenServiceDelegate::GetURLLoaderFactory() const {
+ return nullptr;
+}
+
+GoogleServiceAuthError ProfileOAuth2TokenServiceDelegate::GetAuthError(
+ const CoreAccountId& account_id) const {
+ return GoogleServiceAuthError::AuthErrorNone();
+}
+
+std::vector<CoreAccountId> ProfileOAuth2TokenServiceDelegate::GetAccounts()
+ const {
+ return std::vector<CoreAccountId>();
+}
+
+const net::BackoffEntry* ProfileOAuth2TokenServiceDelegate::BackoffEntry()
+ const {
+ return nullptr;
+}
+
+void ProfileOAuth2TokenServiceDelegate::LoadCredentials(
+ const CoreAccountId& primary_account_id) {
+ NOTREACHED()
+ << "ProfileOAuth2TokenServiceDelegate does not load credentials. "
+ "Subclasses that need to load credentials must provide "
+ "an implemenation of this method";
+}
+
+void ProfileOAuth2TokenServiceDelegate::ExtractCredentials(
+ ProfileOAuth2TokenService* to_service,
+ const CoreAccountId& account_id) {
+ NOTREACHED();
+}
+
+bool ProfileOAuth2TokenServiceDelegate::FixRequestErrorIfPossible() {
+ return false;
+}
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h
new file mode 100644
index 00000000000..3e7738c8bfd
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h
@@ -0,0 +1,188 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_
+
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/observer_list.h"
+#include "build/build_config.h"
+#include "components/signin/public/identity_manager/load_credentials_state.h"
+#include "google_apis/gaia/gaia_auth_util.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "net/base/backoff_entry.h"
+
+namespace network {
+class SharedURLLoaderFactory;
+}
+
+class OAuth2AccessTokenFetcher;
+class OAuth2AccessTokenConsumer;
+class OAuth2TokenServiceObserver;
+class ProfileOAuth2TokenService;
+
+// Abstract base class to fetch and maintain refresh tokens from various
+// entities. Concrete subclasses should implement RefreshTokenIsAvailable and
+// CreateAccessTokenFetcher properly.
+class ProfileOAuth2TokenServiceDelegate {
+ public:
+ ProfileOAuth2TokenServiceDelegate();
+ virtual ~ProfileOAuth2TokenServiceDelegate();
+
+ virtual std::unique_ptr<OAuth2AccessTokenFetcher> CreateAccessTokenFetcher(
+ const CoreAccountId& account_id,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ OAuth2AccessTokenConsumer* consumer) WARN_UNUSED_RESULT = 0;
+
+ // Returns |true| if a refresh token is available for |account_id|, and
+ // |false| otherwise.
+ // Note: Implementations must make sure that |RefreshTokenIsAvailable| returns
+ // |true| if and only if |account_id| is contained in the list of accounts
+ // returned by |GetAccounts|.
+ virtual bool RefreshTokenIsAvailable(
+ const CoreAccountId& account_id) const = 0;
+ virtual GoogleServiceAuthError GetAuthError(
+ const CoreAccountId& account_id) const;
+ virtual void UpdateAuthError(const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error) {}
+
+ // Returns a list of accounts for which a refresh token is maintained by
+ // |this| instance.
+ // Note: If tokens have not been fully loaded yet, an empty list is returned.
+ // Also, see |RefreshTokenIsAvailable|.
+ virtual std::vector<CoreAccountId> GetAccounts() const;
+ virtual void RevokeAllCredentials() {}
+
+ virtual void OnAccessTokenInvalidated(const CoreAccountId& account_id,
+ const std::string& client_id,
+ const std::set<std::string>& scopes,
+ const std::string& access_token) {}
+
+ // If refresh token is accessible (on Desktop) sets error for it to
+ // INVALID_GAIA_CREDENTIALS and notifies the observers. Otherwise
+ // does nothing.
+ virtual void InvalidateTokenForMultilogin(
+ const CoreAccountId& failed_account) {}
+
+ virtual void Shutdown() {}
+ virtual void UpdateCredentials(const CoreAccountId& account_id,
+ const std::string& refresh_token) {}
+ virtual void RevokeCredentials(const CoreAccountId& account_id) {}
+ virtual scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory()
+ const;
+
+ // Returns refresh token if the platform allows it (on Desktop) and if it is
+ // available and doesn't have error. Otherwise returns empty string (for iOS
+ // and Android).
+ virtual std::string GetTokenForMultilogin(
+ const CoreAccountId& account_id) const;
+
+ bool ValidateAccountId(const CoreAccountId& account_id) const;
+
+ // Add or remove observers of this token service.
+ void AddObserver(OAuth2TokenServiceObserver* observer);
+ void RemoveObserver(OAuth2TokenServiceObserver* observer);
+
+ // Returns a pointer to its instance of net::BackoffEntry if it has one, or
+ // a nullptr otherwise.
+ virtual const net::BackoffEntry* BackoffEntry() const;
+
+ // -----------------------------------------------------------------------
+ // Methods that are only used by ProfileOAuth2TokenService.
+ // -----------------------------------------------------------------------
+
+ // Loads the credentials from disk. Called only once when the token service
+ // is initialized. Default implementation is NOTREACHED - subsclasses that
+ // are used by the ProfileOAuth2TokenService must provide an implementation
+ // for this method.
+ virtual void LoadCredentials(const CoreAccountId& primary_account_id);
+
+ // Returns the state of the load credentials operation.
+ signin::LoadCredentialsState load_credentials_state() const {
+ return load_credentials_state_;
+ }
+
+ // Removes the credentials associated to account_id from the internal storage,
+ // and moves them to |to_service|. The credentials are not revoked on the
+ // server, but the OnRefreshTokenRevoked() notification is sent to the
+ // observers.
+ virtual void ExtractCredentials(ProfileOAuth2TokenService* to_service,
+ const CoreAccountId& account_id);
+
+ // Attempts to fix the error if possible. Returns true if the error was fixed
+ // and false otherwise.
+ virtual bool FixRequestErrorIfPossible();
+
+#if defined(OS_IOS)
+ // Triggers platform specific implementation for iOS to reload all accounts
+ // from system.
+ virtual void ReloadAllAccountsFromSystem() {}
+
+ // Triggers platform specific implementation for iOS to add a given account
+ // to the token service from a system account.
+ virtual void ReloadAccountFromSystem(const CoreAccountId& account_id) {}
+#endif
+
+#if defined(OS_ANDROID)
+ // Triggers platform specific implementation for Android to reload accounts
+ // from system.
+ virtual void ReloadAccountsFromSystem(
+ const CoreAccountId& primary_account_id) {}
+#endif
+
+ // -----------------------------------------------------------------------
+ // End of methods that are only used by ProfileOAuth2TokenService
+ // -----------------------------------------------------------------------
+
+ protected:
+ void set_load_credentials_state(signin::LoadCredentialsState state) {
+ load_credentials_state_ = state;
+ }
+
+ // Called by subclasses to notify observers.
+ void FireRefreshTokenAvailable(const CoreAccountId& account_id);
+ void FireRefreshTokenRevoked(const CoreAccountId& account_id);
+ // FireRefreshTokensLoaded is virtual and overridden in android implementation
+ // where additional actions are required.
+ virtual void FireRefreshTokensLoaded();
+ void FireAuthErrorChanged(const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error);
+
+ // Helper class to scope batch changes.
+ class ScopedBatchChange {
+ public:
+ explicit ScopedBatchChange(ProfileOAuth2TokenServiceDelegate* delegate);
+ ~ScopedBatchChange();
+
+ private:
+ ProfileOAuth2TokenServiceDelegate* delegate_; // Weak.
+ DISALLOW_COPY_AND_ASSIGN(ScopedBatchChange);
+ };
+
+ private:
+ // List of observers to notify when refresh token availability changes.
+ // Makes sure list is empty on destruction.
+ base::ObserverList<OAuth2TokenServiceObserver, true>::Unchecked
+ observer_list_;
+
+ // The state of the load credentials operation.
+ signin::LoadCredentialsState load_credentials_state_ =
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_NOT_STARTED;
+
+ void StartBatchChanges();
+ void EndBatchChanges();
+
+ // The depth of batch changes.
+ int batch_change_depth_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProfileOAuth2TokenServiceDelegate);
+};
+
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_
diff --git a/chromium/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos.cc b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.cc
index 00d05e5fabb..3a064c68e01 100644
--- a/chromium/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos.cc
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.h"
#include <string>
#include <utility>
@@ -11,7 +11,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/stl_util.h"
-#include "components/signin/core/browser/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
#include "google_apis/gaia/oauth2_access_token_fetcher_immediate_error.h"
#include "net/base/backoff_entry.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -42,17 +42,17 @@ const net::BackoffEntry::Policy kBackoffPolicy = {
// and non-Gaia accounts. Non-Gaia accounts will be filtered out.
// |account_keys| is the set of accounts that need to be translated.
// |account_tracker_service| is an unowned pointer.
-std::vector<std::string> GetOAuthAccountIdsFromAccountKeys(
+std::vector<CoreAccountId> GetOAuthAccountIdsFromAccountKeys(
const std::set<chromeos::AccountManager::AccountKey>& account_keys,
const AccountTrackerService* const account_tracker_service) {
- std::vector<std::string> accounts;
+ std::vector<CoreAccountId> accounts;
for (auto& account_key : account_keys) {
if (account_key.account_type !=
chromeos::account_manager::AccountType::ACCOUNT_TYPE_GAIA) {
continue;
}
- std::string account_id =
+ CoreAccountId account_id =
account_tracker_service
->FindAccountInfoByGaiaId(account_key.id /* gaia_id */)
.account_id;
@@ -87,13 +87,15 @@ ProfileOAuth2TokenServiceDelegateChromeOS::
network_connection_tracker_->RemoveNetworkConnectionObserver(this);
}
-OAuth2AccessTokenFetcher*
+std::unique_ptr<OAuth2AccessTokenFetcher>
ProfileOAuth2TokenServiceDelegateChromeOS::CreateAccessTokenFetcher(
- const std::string& account_id,
+ const CoreAccountId& account_id,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
OAuth2AccessTokenConsumer* consumer) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK_EQ(LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS, load_credentials_state());
+ DCHECK_EQ(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ load_credentials_state());
ValidateAccountId(account_id);
@@ -105,7 +107,7 @@ ProfileOAuth2TokenServiceDelegateChromeOS::CreateAccessTokenFetcher(
VLOG(1) << "Request for token has been rejected due to persistent error #"
<< it->second.last_auth_error.state();
// |OAuth2TokenService| will manage the lifetime of this pointer.
- return new OAuth2AccessTokenFetcherImmediateError(
+ return std::make_unique<OAuth2AccessTokenFetcherImmediateError>(
consumer, it->second.last_auth_error);
}
// Or when we need to backoff.
@@ -113,18 +115,16 @@ ProfileOAuth2TokenServiceDelegateChromeOS::CreateAccessTokenFetcher(
VLOG(1) << "Request for token has been rejected due to backoff rules from"
<< " previous error #" << backoff_error_.state();
// |OAuth2TokenService| will manage the lifetime of this pointer.
- return new OAuth2AccessTokenFetcherImmediateError(consumer, backoff_error_);
+ return std::make_unique<OAuth2AccessTokenFetcherImmediateError>(
+ consumer, backoff_error_);
}
- // |OAuth2TokenService| will manage the lifetime of the released pointer.
- return account_manager_
- ->CreateAccessTokenFetcher(
- chromeos::AccountManager::AccountKey{
- account_tracker_service_->GetAccountInfo(account_id).gaia,
- chromeos::account_manager::AccountType::
- ACCOUNT_TYPE_GAIA} /* account_key */,
- url_loader_factory, consumer)
- .release();
+ return account_manager_->CreateAccessTokenFetcher(
+ chromeos::AccountManager::AccountKey{
+ account_tracker_service_->GetAccountInfo(account_id).gaia,
+ chromeos::account_manager::AccountType::
+ ACCOUNT_TYPE_GAIA} /* account_key */,
+ url_loader_factory, consumer);
}
// Note: This method should use the same logic for filtering accounts as
@@ -132,20 +132,21 @@ ProfileOAuth2TokenServiceDelegateChromeOS::CreateAccessTokenFetcher(
// both |GetAccounts| and |RefreshTokenIsAvailable| use
// |GetOAuthAccountIdsFromAccountKeys|.
bool ProfileOAuth2TokenServiceDelegateChromeOS::RefreshTokenIsAvailable(
- const std::string& account_id) const {
- if (load_credentials_state() != LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS) {
+ const CoreAccountId& account_id) const {
+ if (load_credentials_state() !=
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS) {
return false;
}
// We intentionally do NOT check if the refresh token associated with
// |account_id| is valid or not. See crbug.com/919793 for details.
- return base::ContainsValue(GetOAuthAccountIdsFromAccountKeys(
- account_keys_, account_tracker_service_),
- account_id);
+ return base::Contains(GetOAuthAccountIdsFromAccountKeys(
+ account_keys_, account_tracker_service_),
+ account_id);
}
void ProfileOAuth2TokenServiceDelegateChromeOS::UpdateAuthError(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const GoogleServiceAuthError& error) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -158,6 +159,8 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::UpdateAuthError(
auto it = errors_.find(account_id);
if (it != errors_.end()) {
+ if (error == it->second.last_auth_error)
+ return;
// Update the existing error.
if (error.state() == GoogleServiceAuthError::NONE)
errors_.erase(it);
@@ -172,7 +175,7 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::UpdateAuthError(
}
GoogleServiceAuthError ProfileOAuth2TokenServiceDelegateChromeOS::GetAuthError(
- const std::string& account_id) const {
+ const CoreAccountId& account_id) const {
auto it = errors_.find(account_id);
if (it != errors_.end()) {
return it->second.last_auth_error;
@@ -185,8 +188,8 @@ GoogleServiceAuthError ProfileOAuth2TokenServiceDelegateChromeOS::GetAuthError(
// |RefreshTokenIsAvailable|. See crbug.com/919793 for details. At the time of
// writing, both |GetAccounts| and |RefreshTokenIsAvailable| use
// |GetOAuthAccountIdsFromAccountKeys|.
-std::vector<std::string>
-ProfileOAuth2TokenServiceDelegateChromeOS::GetAccounts() {
+std::vector<CoreAccountId>
+ProfileOAuth2TokenServiceDelegateChromeOS::GetAccounts() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// |GetAccounts| intentionally does not care about the state of
@@ -198,13 +201,15 @@ ProfileOAuth2TokenServiceDelegateChromeOS::GetAccounts() {
}
void ProfileOAuth2TokenServiceDelegateChromeOS::LoadCredentials(
- const std::string& primary_account_id) {
+ const CoreAccountId& primary_account_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (load_credentials_state() != LOAD_CREDENTIALS_NOT_STARTED) {
+ if (load_credentials_state() !=
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_NOT_STARTED) {
return;
}
- set_load_credentials_state(LOAD_CREDENTIALS_IN_PROGRESS);
+ set_load_credentials_state(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS);
if (!is_regular_profile_) {
// |LoadCredentials| needs to complete successfully for a successful Profile
@@ -213,7 +218,8 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::LoadCredentials(
// to them. Note: They do have access to an Account Manager instance, but
// that instance is never set up (|AccountManager::Initialize|). Also, see
// http://crbug.com/891818
- set_load_credentials_state(LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
+ set_load_credentials_state(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
FireRefreshTokensLoaded();
return;
}
@@ -226,16 +232,16 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::LoadCredentials(
}
void ProfileOAuth2TokenServiceDelegateChromeOS::UpdateCredentials(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& refresh_token) {
// This API could have been called for upserting the Device/Primary
// |account_id| or a Secondary |account_id|.
// Account insertion:
// Device Account insertion on Chrome OS happens as a 2 step process:
- // 1. The account is inserted into SigninManager / AccountTrackerService, via
- // IdentityManager, with a valid Gaia id and email but an invalid refresh
- // token.
+ // 1. The account is inserted into PrimaryAccountManager /
+ // AccountTrackerService, via IdentityManager, with a valid Gaia id and email
+ // but an invalid refresh token.
// 2. This API is called to update the aforementioned account with a valid
// refresh token.
// Secondary Account insertion on Chrome OS happens atomically in
@@ -254,7 +260,9 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::UpdateCredentials(
// Accounts) we can be sure that |account_id| is present in
// |AccountTrackerService|.
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK_EQ(LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS, load_credentials_state());
+ DCHECK_EQ(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ load_credentials_state());
DCHECK(!account_id.empty());
DCHECK(!refresh_token.empty());
@@ -287,10 +295,12 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::OnGetAccounts(
// This callback should only be triggered during |LoadCredentials|, which
// implies that |load_credentials_state())| should in
// |LOAD_CREDENTIALS_IN_PROGRESS| state.
- DCHECK_EQ(LOAD_CREDENTIALS_IN_PROGRESS, load_credentials_state());
+ DCHECK_EQ(signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS,
+ load_credentials_state());
- set_load_credentials_state(LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
- // The typical order of |OAuth2TokenService::Observer| callbacks is:
+ set_load_credentials_state(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
+ // The typical order of |OAuth2TokenServiceObserver| callbacks is:
// 1. OnRefreshTokenAvailable
// 2. OnEndBatchChanges
// 3. OnRefreshTokensLoaded
@@ -341,7 +351,7 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::OnTokenUpserted(
ScopedBatchChange batch(this);
FireRefreshTokenAvailable(account_id);
- // See |OAuth2TokenService::Observer::OnAuthErrorChanged|.
+ // See |OAuth2TokenServiceObserver::OnAuthErrorChanged|.
// |OnAuthErrorChanged| must be always called after
// |OnRefreshTokenAvailable|, when refresh token is updated.
FireAuthErrorChanged(account_id, error);
@@ -350,7 +360,9 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::OnTokenUpserted(
void ProfileOAuth2TokenServiceDelegateChromeOS::OnAccountRemoved(
const chromeos::AccountManager::Account& account) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK_EQ(LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS, load_credentials_state());
+ DCHECK_EQ(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ load_credentials_state());
auto it = account_keys_.find(account.key);
if (it == account_keys_.end()) {
@@ -376,7 +388,7 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::OnAccountRemoved(
}
void ProfileOAuth2TokenServiceDelegateChromeOS::RevokeCredentials(
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
// Signing out of Chrome is not possible on Chrome OS.
NOTREACHED();
}
diff --git a/chromium/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos.h b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.h
index b515c53df60..affc6247883 100644
--- a/chromium/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos.h
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_CHROMEOS_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_CHROMEOS_H_
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_CHROMEOS_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_CHROMEOS_H_
#include <map>
#include <memory>
@@ -15,15 +15,14 @@
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "chromeos/components/account_manager/account_manager.h"
-#include "google_apis/gaia/oauth2_token_service_delegate.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
#include "services/network/public/cpp/network_connection_tracker.h"
class AccountTrackerService;
namespace signin {
-
class ProfileOAuth2TokenServiceDelegateChromeOS
- : public OAuth2TokenServiceDelegate,
+ : public ProfileOAuth2TokenServiceDelegate,
public chromeos::AccountManager::Observer,
public network::NetworkConnectionTracker::NetworkConnectionObserver {
public:
@@ -37,23 +36,23 @@ class ProfileOAuth2TokenServiceDelegateChromeOS
bool is_regular_profile);
~ProfileOAuth2TokenServiceDelegateChromeOS() override;
- // OAuth2TokenServiceDelegate overrides.
- OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
- const std::string& account_id,
+ // ProfileOAuth2TokenServiceDelegate overrides.
+ std::unique_ptr<OAuth2AccessTokenFetcher> CreateAccessTokenFetcher(
+ const CoreAccountId& account_id,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
OAuth2AccessTokenConsumer* consumer) override;
- bool RefreshTokenIsAvailable(const std::string& account_id) const override;
- void UpdateAuthError(const std::string& account_id,
+ bool RefreshTokenIsAvailable(const CoreAccountId& account_id) const override;
+ void UpdateAuthError(const CoreAccountId& account_id,
const GoogleServiceAuthError& error) override;
GoogleServiceAuthError GetAuthError(
- const std::string& account_id) const override;
- std::vector<std::string> GetAccounts() override;
- void LoadCredentials(const std::string& primary_account_id) override;
- void UpdateCredentials(const std::string& account_id,
+ const CoreAccountId& account_id) const override;
+ std::vector<CoreAccountId> GetAccounts() const override;
+ void LoadCredentials(const CoreAccountId& primary_account_id) override;
+ void UpdateCredentials(const CoreAccountId& account_id,
const std::string& refresh_token) override;
scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory()
const override;
- void RevokeCredentials(const std::string& account_id) override;
+ void RevokeCredentials(const CoreAccountId& account_id) override;
void RevokeAllCredentials() override;
const net::BackoffEntry* BackoffEntry() const override;
@@ -91,7 +90,7 @@ class ProfileOAuth2TokenServiceDelegateChromeOS
std::set<chromeos::AccountManager::AccountKey> account_keys_;
// A map from account id to the last seen error for that account.
- std::map<std::string, AccountErrorStatus> errors_;
+ std::map<CoreAccountId, AccountErrorStatus> errors_;
// Used to rate-limit token fetch requests so as to not overload the server.
net::BackoffEntry backoff_entry_;
@@ -108,4 +107,4 @@ class ProfileOAuth2TokenServiceDelegateChromeOS
} // namespace signin
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_CHROMEOS_H_
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_CHROMEOS_H_
diff --git a/chromium/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos_unittest.cc b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos_unittest.cc
index 088a552ca34..d161cb81862 100644
--- a/chromium/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.h"
#include <memory>
#include <set>
@@ -16,15 +16,16 @@
#include "base/stl_util.h"
#include "base/test/scoped_task_environment.h"
#include "chromeos/components/account_manager/account_manager.h"
-#include "components/signin/core/browser/account_info.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "components/signin/core/browser/test_signin_client.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/base/test_signin_client.h"
+#include "components/signin/public/identity_manager/account_info.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/oauth2_access_token_consumer.h"
-#include "google_apis/gaia/oauth2_token_service.h"
-#include "google_apis/gaia/oauth2_token_service_test_util.h"
+#include "google_apis/gaia/oauth2_access_token_fetcher.h"
+#include "google_apis/gaia/oauth2_access_token_manager_test_util.h"
+#include "google_apis/gaia/oauth2_token_service_observer.h"
#include "services/network/test/test_network_connection_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -59,16 +60,19 @@ class AccessTokenConsumer : public OAuth2AccessTokenConsumer {
DISALLOW_COPY_AND_ASSIGN(AccessTokenConsumer);
};
-class TokenServiceObserver : public OAuth2TokenService::Observer {
+class TestOAuth2TokenServiceObserver : public OAuth2TokenServiceObserver {
public:
- // |delegate| is a non-owning pointer to an |OAuth2TokenServiceDelegate| that
- // MUST outlive |this| instance.
- explicit TokenServiceObserver(OAuth2TokenServiceDelegate* delegate)
+ // |delegate| is a non-owning pointer to an
+ // |ProfileOAuth2TokenServiceDelegate| that MUST outlive |this| instance.
+ explicit TestOAuth2TokenServiceObserver(
+ ProfileOAuth2TokenServiceDelegate* delegate)
: delegate_(delegate) {
delegate_->AddObserver(this);
}
- ~TokenServiceObserver() override { delegate_->RemoveObserver(this); }
+ ~TestOAuth2TokenServiceObserver() override {
+ delegate_->RemoveObserver(this);
+ }
void StartBatchChanges() {
EXPECT_FALSE(is_inside_batch_);
@@ -83,7 +87,7 @@ class TokenServiceObserver : public OAuth2TokenService::Observer {
is_inside_batch_ = false;
}
- void OnRefreshTokenAvailable(const std::string& account_id) override {
+ void OnRefreshTokenAvailable(const CoreAccountId& account_id) override {
if (!is_inside_batch_)
StartBatchChanges();
@@ -106,7 +110,7 @@ class TokenServiceObserver : public OAuth2TokenService::Observer {
void OnRefreshTokensLoaded() override { refresh_tokens_loaded_ = true; }
- void OnRefreshTokenRevoked(const std::string& account_id) override {
+ void OnRefreshTokenRevoked(const CoreAccountId& account_id) override {
if (!is_inside_batch_)
StartBatchChanges();
@@ -115,12 +119,15 @@ class TokenServiceObserver : public OAuth2TokenService::Observer {
batch_change_records_.rbegin()->emplace_back(account_id);
}
- void OnAuthErrorChanged(const std::string& account_id,
+ void OnAuthErrorChanged(const CoreAccountId& account_id,
const GoogleServiceAuthError& auth_error) override {
last_err_account_id_ = account_id;
last_err_ = auth_error;
+ on_auth_error_changed_calls++;
}
+ int on_auth_error_changed_calls = 0;
+
std::string last_err_account_id_;
GoogleServiceAuthError last_err_;
std::set<std::string> account_ids_;
@@ -133,7 +140,7 @@ class TokenServiceObserver : public OAuth2TokenService::Observer {
std::vector<std::vector<std::string>> batch_change_records_;
// Non-owning pointer.
- OAuth2TokenServiceDelegate* const delegate_;
+ ProfileOAuth2TokenServiceDelegate* const delegate_;
};
} // namespace
@@ -229,54 +236,51 @@ TEST_F(CrOSOAuthDelegateTest, RefreshTokensAreLoadedForNonRegularProfiles) {
&account_tracker_service_,
network::TestNetworkConnectionTracker::GetInstance(), &account_manager,
false /* is_regular_profile */);
- TokenServiceObserver observer(delegate.get());
+ TestOAuth2TokenServiceObserver observer(delegate.get());
// Test that LoadCredentials works as expected.
EXPECT_FALSE(observer.refresh_tokens_loaded_);
delegate->LoadCredentials("" /* primary_account_id */);
EXPECT_TRUE(observer.refresh_tokens_loaded_);
- EXPECT_EQ(OAuth2TokenServiceDelegate::LoadCredentialsState::
- LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ EXPECT_EQ(LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
delegate->load_credentials_state());
}
TEST_F(CrOSOAuthDelegateTest,
RefreshTokenIsAvailableReturnsTrueForValidGaiaTokens) {
- EXPECT_EQ(OAuth2TokenServiceDelegate::LoadCredentialsState::
- LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ EXPECT_EQ(LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
delegate_->load_credentials_state());
EXPECT_FALSE(delegate_->RefreshTokenIsAvailable(account_info_.account_id));
EXPECT_FALSE(
- base::ContainsValue(delegate_->GetAccounts(), account_info_.account_id));
+ base::Contains(delegate_->GetAccounts(), account_info_.account_id));
account_manager_.UpsertAccount(gaia_account_key_, kUserEmail, kGaiaToken);
EXPECT_TRUE(delegate_->RefreshTokenIsAvailable(account_info_.account_id));
EXPECT_TRUE(
- base::ContainsValue(delegate_->GetAccounts(), account_info_.account_id));
+ base::Contains(delegate_->GetAccounts(), account_info_.account_id));
}
TEST_F(CrOSOAuthDelegateTest,
RefreshTokenIsAvailableReturnsTrueForInvalidGaiaTokens) {
- EXPECT_EQ(OAuth2TokenServiceDelegate::LoadCredentialsState::
- LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ EXPECT_EQ(LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
delegate_->load_credentials_state());
EXPECT_FALSE(delegate_->RefreshTokenIsAvailable(account_info_.account_id));
EXPECT_FALSE(
- base::ContainsValue(delegate_->GetAccounts(), account_info_.account_id));
+ base::Contains(delegate_->GetAccounts(), account_info_.account_id));
account_manager_.UpsertAccount(gaia_account_key_, kUserEmail,
chromeos::AccountManager::kInvalidToken);
EXPECT_TRUE(delegate_->RefreshTokenIsAvailable(account_info_.account_id));
EXPECT_TRUE(
- base::ContainsValue(delegate_->GetAccounts(), account_info_.account_id));
+ base::Contains(delegate_->GetAccounts(), account_info_.account_id));
}
TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnAuthErrorChange) {
- TokenServiceObserver observer(delegate_.get());
+ TestOAuth2TokenServiceObserver observer(delegate_.get());
auto error =
GoogleServiceAuthError(GoogleServiceAuthError::State::SERVICE_ERROR);
@@ -286,8 +290,33 @@ TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnAuthErrorChange) {
EXPECT_EQ(error, observer.last_err_);
}
+TEST_F(CrOSOAuthDelegateTest, ObserversAreNotNotifiedIfErrorDidntChange) {
+ TestOAuth2TokenServiceObserver observer(delegate_.get());
+ auto error =
+ GoogleServiceAuthError(GoogleServiceAuthError::State::SERVICE_ERROR);
+
+ delegate_->UpdateAuthError(account_info_.account_id, error);
+ EXPECT_EQ(1, observer.on_auth_error_changed_calls);
+ delegate_->UpdateAuthError(account_info_.account_id, error);
+ EXPECT_EQ(1, observer.on_auth_error_changed_calls);
+}
+
+TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedIfErrorDidChange) {
+ TestOAuth2TokenServiceObserver observer(delegate_.get());
+ delegate_->UpdateAuthError(
+ account_info_.account_id,
+ GoogleServiceAuthError(GoogleServiceAuthError::State::SERVICE_ERROR));
+ EXPECT_EQ(1, observer.on_auth_error_changed_calls);
+
+ delegate_->UpdateAuthError(
+ account_info_.account_id,
+ GoogleServiceAuthError(
+ GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS));
+ EXPECT_EQ(2, observer.on_auth_error_changed_calls);
+}
+
TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnCredentialsInsertion) {
- TokenServiceObserver observer(delegate_.get());
+ TestOAuth2TokenServiceObserver observer(delegate_.get());
delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
EXPECT_EQ(1UL, observer.account_ids_.size());
@@ -298,7 +327,7 @@ TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnCredentialsInsertion) {
TEST_F(CrOSOAuthDelegateTest,
ObserversDoNotSeeCachedErrorsOnCredentialsUpdate) {
- TokenServiceObserver observer(delegate_.get());
+ TestOAuth2TokenServiceObserver observer(delegate_.get());
auto error =
GoogleServiceAuthError(GoogleServiceAuthError::State::SERVICE_ERROR);
delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
@@ -310,7 +339,7 @@ TEST_F(CrOSOAuthDelegateTest,
}
TEST_F(CrOSOAuthDelegateTest, DummyTokensArePreEmptivelyRejected) {
- TokenServiceObserver observer(delegate_.get());
+ TestOAuth2TokenServiceObserver observer(delegate_.get());
delegate_->UpdateCredentials(account_info_.account_id,
chromeos::AccountManager::kInvalidToken);
@@ -328,7 +357,7 @@ TEST_F(CrOSOAuthDelegateTest, DummyTokensArePreEmptivelyRejected) {
}
TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnCredentialsUpdate) {
- TokenServiceObserver observer(delegate_.get());
+ TestOAuth2TokenServiceObserver observer(delegate_.get());
delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
EXPECT_EQ(1UL, observer.account_ids_.size());
@@ -339,7 +368,7 @@ TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnCredentialsUpdate) {
TEST_F(CrOSOAuthDelegateTest,
ObserversAreNotNotifiedIfCredentialsAreNotUpdated) {
- TokenServiceObserver observer(delegate_.get());
+ TestOAuth2TokenServiceObserver observer(delegate_.get());
delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
observer.account_ids_.clear();
@@ -352,7 +381,7 @@ TEST_F(CrOSOAuthDelegateTest,
TEST_F(CrOSOAuthDelegateTest,
BatchChangeObserversAreNotifiedOnCredentialsUpdate) {
- TokenServiceObserver observer(delegate_.get());
+ TestOAuth2TokenServiceObserver observer(delegate_.get());
delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
EXPECT_EQ(1UL, observer.batch_change_records_.size());
@@ -360,9 +389,9 @@ TEST_F(CrOSOAuthDelegateTest,
EXPECT_EQ(account_info_.account_id, observer.batch_change_records_[0][0]);
}
-// If observers register themselves with |OAuth2TokenServiceDelegate| before
-// |chromeos::AccountManager| has been initialized, they should receive all the
-// accounts stored in |chromeos::AccountManager| in a single batch.
+// If observers register themselves with |ProfileOAuth2TokenServiceDelegate|
+// before |chromeos::AccountManager| has been initialized, they should receive
+// all the accounts stored in |chromeos::AccountManager| in a single batch.
TEST_F(CrOSOAuthDelegateTest, BatchChangeObserversAreNotifiedOncePerBatch) {
// Setup
AccountInfo account1 = CreateAccountInfoTestFixture(
@@ -393,7 +422,7 @@ TEST_F(CrOSOAuthDelegateTest, BatchChangeObserversAreNotifiedOncePerBatch) {
network::TestNetworkConnectionTracker::GetInstance(), &account_manager,
true /* is_regular_profile */);
delegate->LoadCredentials(account1.account_id /* primary_account_id */);
- TokenServiceObserver observer(delegate.get());
+ TestOAuth2TokenServiceObserver observer(delegate.get());
// Wait until chromeos::AccountManager is fully initialized.
task_environment_.RunUntilIdle();
@@ -411,8 +440,8 @@ TEST_F(CrOSOAuthDelegateTest, BatchChangeObserversAreNotifiedOncePerBatch) {
const std::vector<std::string>& first_batch =
observer.batch_change_records_[0];
EXPECT_EQ(2UL, first_batch.size());
- EXPECT_TRUE(base::ContainsValue(first_batch, account1.account_id));
- EXPECT_TRUE(base::ContainsValue(first_batch, account2.account_id));
+ EXPECT_TRUE(base::Contains(first_batch, account1.account_id));
+ EXPECT_TRUE(base::Contains(first_batch, account2.account_id));
}
TEST_F(CrOSOAuthDelegateTest, GetAccountsShouldNotReturnAdAccounts) {
@@ -432,7 +461,7 @@ TEST_F(CrOSOAuthDelegateTest, GetAccountsReturnsGaiaAccounts) {
account_manager_.UpsertAccount(gaia_account_key_, kUserEmail, kGaiaToken);
- std::vector<std::string> accounts = delegate_->GetAccounts();
+ std::vector<CoreAccountId> accounts = delegate_->GetAccounts();
EXPECT_EQ(1UL, accounts.size());
EXPECT_EQ(account_info_.account_id, accounts[0]);
}
@@ -445,15 +474,14 @@ TEST_F(CrOSOAuthDelegateTest, GetAccountsReturnsGaiaAccountsWithInvalidTokens) {
account_manager_.UpsertAccount(gaia_account_key_, kUserEmail,
chromeos::AccountManager::kInvalidToken);
- std::vector<std::string> accounts = delegate_->GetAccounts();
+ std::vector<CoreAccountId> accounts = delegate_->GetAccounts();
EXPECT_EQ(1UL, accounts.size());
EXPECT_EQ(account_info_.account_id, accounts[0]);
}
TEST_F(CrOSOAuthDelegateTest,
RefreshTokenMustBeAvailableForAllAccountsReturnedByGetAccounts) {
- EXPECT_EQ(OAuth2TokenServiceDelegate::LoadCredentialsState::
- LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ EXPECT_EQ(LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
delegate_->load_credentials_state());
EXPECT_TRUE(delegate_->GetAccounts().empty());
const std::string kUserEmail2 = "random-email2@example.com";
@@ -475,11 +503,11 @@ TEST_F(CrOSOAuthDelegateTest,
chromeos::AccountManager::kActiveDirectoryDummyToken);
// Verify.
- const std::vector<std::string> accounts = delegate_->GetAccounts();
+ const std::vector<CoreAccountId> accounts = delegate_->GetAccounts();
// 2 Gaia accounts should be returned.
EXPECT_EQ(2UL, accounts.size());
// And |RefreshTokenIsAvailable| should return true for these accounts.
- for (const std::string& account : accounts) {
+ for (const CoreAccountId& account : accounts) {
EXPECT_TRUE(delegate_->RefreshTokenIsAvailable(account));
}
}
@@ -489,7 +517,7 @@ TEST_F(CrOSOAuthDelegateTest, UpdateCredentialsSucceeds) {
delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
- std::vector<std::string> accounts = delegate_->GetAccounts();
+ std::vector<CoreAccountId> accounts = delegate_->GetAccounts();
EXPECT_EQ(1UL, accounts.size());
EXPECT_EQ(account_info_.account_id, accounts[0]);
}
@@ -497,7 +525,7 @@ TEST_F(CrOSOAuthDelegateTest, UpdateCredentialsSucceeds) {
TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnAccountRemoval) {
delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
- TokenServiceObserver observer(delegate_.get());
+ TestOAuth2TokenServiceObserver observer(delegate_.get());
account_manager_.RemoveAccount(gaia_account_key_);
EXPECT_EQ(1UL, observer.batch_change_records_.size());
@@ -542,10 +570,10 @@ TEST_F(CrOSOAuthDelegateTest, BackOffIsTriggerredForTransientErrors) {
EXPECT_EQ(0, access_token_consumer.num_access_token_fetch_success_);
EXPECT_EQ(0, access_token_consumer.num_access_token_fetch_failure_);
std::vector<std::string> scopes{"scope"};
- std::unique_ptr<OAuth2AccessTokenFetcher> fetcher(
+ std::unique_ptr<OAuth2AccessTokenFetcher> fetcher =
delegate_->CreateAccessTokenFetcher(account_info_.account_id,
delegate_->GetURLLoaderFactory(),
- &access_token_consumer));
+ &access_token_consumer);
task_environment_.RunUntilIdle();
fetcher->Start("client_id", "client_secret", scopes);
task_environment_.RunUntilIdle();
@@ -556,9 +584,9 @@ TEST_F(CrOSOAuthDelegateTest, BackOffIsTriggerredForTransientErrors) {
// Pretend that backoff has expired and try again.
delegate_->backoff_entry_.SetCustomReleaseTime(base::TimeTicks());
- fetcher.reset(delegate_->CreateAccessTokenFetcher(
+ fetcher = delegate_->CreateAccessTokenFetcher(
account_info_.account_id, delegate_->GetURLLoaderFactory(),
- &access_token_consumer));
+ &access_token_consumer);
fetcher->Start("client_id", "client_secret", scopes);
task_environment_.RunUntilIdle();
EXPECT_EQ(1, access_token_consumer.num_access_token_fetch_success_);
@@ -579,10 +607,10 @@ TEST_F(CrOSOAuthDelegateTest, BackOffIsResetOnNetworkChange) {
EXPECT_EQ(0, access_token_consumer.num_access_token_fetch_success_);
EXPECT_EQ(0, access_token_consumer.num_access_token_fetch_failure_);
std::vector<std::string> scopes{"scope"};
- std::unique_ptr<OAuth2AccessTokenFetcher> fetcher(
+ std::unique_ptr<OAuth2AccessTokenFetcher> fetcher =
delegate_->CreateAccessTokenFetcher(account_info_.account_id,
delegate_->GetURLLoaderFactory(),
- &access_token_consumer));
+ &access_token_consumer);
task_environment_.RunUntilIdle();
fetcher->Start("client_id", "client_secret", scopes);
task_environment_.RunUntilIdle();
@@ -594,9 +622,9 @@ TEST_F(CrOSOAuthDelegateTest, BackOffIsResetOnNetworkChange) {
// Notify of network change and ensure that request now runs.
delegate_->OnConnectionChanged(
network::mojom::ConnectionType::CONNECTION_WIFI);
- fetcher.reset(delegate_->CreateAccessTokenFetcher(
+ fetcher = delegate_->CreateAccessTokenFetcher(
account_info_.account_id, delegate_->GetURLLoaderFactory(),
- &access_token_consumer));
+ &access_token_consumer);
fetcher->Start("client_id", "client_secret", scopes);
task_environment_.RunUntilIdle();
EXPECT_EQ(1, access_token_consumer.num_access_token_fetch_success_);
diff --git a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h
index 8815bc9f0d3..f82091685a0 100644
--- a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h
@@ -1,47 +1,51 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_IOS_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_IOS_DELEGATE_H_
-#define COMPONENTS_SIGNIN_IOS_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_IOS_DELEGATE_H_
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_IOS_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_IOS_H_
+#include <map>
+#include <memory>
#include <string>
+#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/threading/thread_checker.h"
-#include "google_apis/gaia/oauth2_token_service_delegate.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
class AccountTrackerService;
-class ProfileOAuth2TokenServiceIOSProvider;
+class DeviceAccountsProvider;
class SigninClient;
-class ProfileOAuth2TokenServiceIOSDelegate : public OAuth2TokenServiceDelegate {
+class ProfileOAuth2TokenServiceIOSDelegate
+ : public ProfileOAuth2TokenServiceDelegate {
public:
ProfileOAuth2TokenServiceIOSDelegate(
SigninClient* client,
- std::unique_ptr<ProfileOAuth2TokenServiceIOSProvider> provider,
+ std::unique_ptr<DeviceAccountsProvider> provider,
AccountTrackerService* account_tracker_service);
~ProfileOAuth2TokenServiceIOSDelegate() override;
- OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
- const std::string& account_id,
+ std::unique_ptr<OAuth2AccessTokenFetcher> CreateAccessTokenFetcher(
+ const CoreAccountId& account_id,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
OAuth2AccessTokenConsumer* consumer) override;
// KeyedService
void Shutdown() override;
- bool RefreshTokenIsAvailable(const std::string& account_id) const override;
+ bool RefreshTokenIsAvailable(const CoreAccountId& account_id) const override;
GoogleServiceAuthError GetAuthError(
- const std::string& account_id) const override;
- void UpdateAuthError(const std::string& account_id,
+ const CoreAccountId& account_id) const override;
+ void UpdateAuthError(const CoreAccountId& account_id,
const GoogleServiceAuthError& error) override;
- void LoadCredentials(const std::string& primary_account_id) override;
- std::vector<std::string> GetAccounts() override;
+ void LoadCredentials(const CoreAccountId& primary_account_id) override;
+ std::vector<CoreAccountId> GetAccounts() const override;
// This method should not be called when using shared authentication.
- void UpdateCredentials(const std::string& account_id,
+ void UpdateCredentials(const CoreAccountId& account_id,
const std::string& refresh_token) override;
// Removes all credentials from this instance of |ProfileOAuth2TokenService|,
@@ -49,35 +53,32 @@ class ProfileOAuth2TokenServiceIOSDelegate : public OAuth2TokenServiceDelegate {
// Subsequent calls to |RefreshTokenIsAvailable| will return |false|.
void RevokeAllCredentials() override;
- void AddAccountFromSystem(const std::string& account_id) override;
+ void ReloadAllAccountsFromSystem() override;
- void ReloadAccountsFromSystem(const std::string& primary_account_id) override;
-
- // Reloads accounts from the provider. Fires |OnRefreshTokenAvailable| for
- // each new account. Fires |OnRefreshTokenRevoked| for each account that was
- // removed.
- // It expects that there is already a primary account id.
- void ReloadCredentials();
-
- // Sets the primary account and then reloads the accounts from the provider.
- // Should be called when the user signs in to a new account.
- // |primary_account_id| must not be an empty string.
- void ReloadCredentials(const std::string& primary_account_id);
+ void ReloadAccountFromSystem(const CoreAccountId& account_id) override;
// Adds |account_id| to |accounts_| if it does not exist or udpates
// the auth error state of |account_id| if it exists. Fires
// |OnRefreshTokenAvailable| if the account info is updated.
- virtual void AddOrUpdateAccount(const std::string& account_id);
+ virtual void AddOrUpdateAccount(const CoreAccountId& account_id);
protected:
// Removes |account_id| from |accounts_|. Fires |OnRefreshTokenRevoked|
// if the account info is removed.
- virtual void RemoveAccount(const std::string& account_id);
+ virtual void RemoveAccount(const CoreAccountId& account_id);
private:
friend class ProfileOAuth2TokenServiceIOSDelegateTest;
FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceIOSDelegateTest,
LoadRevokeCredentialsClearsExcludedAccounts);
+ FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceIOSDelegateTest,
+ ReloadCredentials);
+ FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceIOSDelegateTest,
+ ReloadCredentialsWithPrimaryAccountId);
+ FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceIOSDelegateTest,
+ UpdateAuthErrorAfterRevokeCredentials);
+ FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceIOSDelegateTest,
+ GetAuthError);
struct AccountStatus {
GoogleServiceAuthError last_auth_error;
@@ -85,27 +86,29 @@ class ProfileOAuth2TokenServiceIOSDelegate : public OAuth2TokenServiceDelegate {
// Maps the |account_id| of accounts known to ProfileOAuth2TokenService
// to information about the account.
- typedef std::map<std::string, AccountStatus> AccountStatusMap;
+ typedef std::map<CoreAccountId, AccountStatus> AccountStatusMap;
+
+ // Reloads accounts from the provider. Fires |OnRefreshTokenAvailable| for
+ // each new account. Fires |OnRefreshTokenRevoked| for each account that was
+ // removed.
+ void ReloadCredentials();
// Clears exclude secondary accounts preferences.
void ClearExcludedSecondaryAccounts();
- // The primary account id.
- std::string primary_account_id_;
-
// Info about the existing accounts.
AccountStatusMap accounts_;
// Calls to this class are expected to be made from the browser UI thread.
// The purpose of this checker is to detect access to
// ProfileOAuth2TokenService from multiple threads in upstream code.
- base::ThreadChecker thread_checker_;
+ THREAD_CHECKER(thread_checker_);
- // The client with which this instance was initialied, or NULL.
- SigninClient* client_;
- std::unique_ptr<ProfileOAuth2TokenServiceIOSProvider> provider_;
+ // The client with which this instance was initialied, or null.
+ SigninClient* client_ = nullptr;
+ std::unique_ptr<DeviceAccountsProvider> provider_;
AccountTrackerService* account_tracker_service_;
DISALLOW_COPY_AND_ASSIGN(ProfileOAuth2TokenServiceIOSDelegate);
};
-#endif // COMPONENTS_SIGNIN_IOS_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_IOS_DELEGATE_H_
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_IOS_H_
diff --git a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.mm b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.mm
index d931066f992..17e96fd1c93 100644
--- a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.mm
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.mm
@@ -2,14 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h"
#import <Foundation/Foundation.h>
-#include <memory>
#include <set>
-#include <string>
-#include <vector>
+#include <utility>
#include "base/bind.h"
#include "base/macros.h"
@@ -18,11 +16,11 @@
#include "base/values.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
-#include "components/signin/core/browser/account_info.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/signin_client.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/public/base/signin_client.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/identity_manager/account_info.h"
+#include "components/signin/public/identity_manager/ios/device_accounts_provider.h"
#include "google_apis/gaia/oauth2_access_token_fetcher.h"
#include "net/url_request/url_request_status.h"
@@ -35,7 +33,7 @@ namespace {
// Match the way Chromium handles authentication errors in
// google_apis/gaia/oauth2_access_token_fetcher.cc:
GoogleServiceAuthError GetGoogleServiceAuthErrorFromNSError(
- ProfileOAuth2TokenServiceIOSProvider* provider,
+ DeviceAccountsProvider* provider,
const std::string& gaia_id,
NSError* error) {
if (!error)
@@ -70,10 +68,20 @@ GoogleServiceAuthError GetGoogleServiceAuthErrorFromNSError(
}
}
+// Converts a DeviceAccountsProvider::AccountInfo to an AccountInfo.
+AccountInfo AccountInfoFromDeviceAccount(
+ const DeviceAccountsProvider::AccountInfo& account) {
+ AccountInfo account_info;
+ account_info.email = account.email;
+ account_info.gaia = account.gaia;
+ account_info.hosted_domain = account.hosted_domain;
+ return account_info;
+}
+
class SSOAccessTokenFetcher : public OAuth2AccessTokenFetcher {
public:
SSOAccessTokenFetcher(OAuth2AccessTokenConsumer* consumer,
- ProfileOAuth2TokenServiceIOSProvider* provider,
+ DeviceAccountsProvider* provider,
const AccountInfo& account);
~SSOAccessTokenFetcher() override;
@@ -89,7 +97,7 @@ class SSOAccessTokenFetcher : public OAuth2AccessTokenFetcher {
NSError* error);
private:
- ProfileOAuth2TokenServiceIOSProvider* provider_; // weak
+ DeviceAccountsProvider* provider_; // weak
AccountInfo account_;
bool request_was_cancelled_;
base::WeakPtrFactory<SSOAccessTokenFetcher> weak_factory_;
@@ -99,7 +107,7 @@ class SSOAccessTokenFetcher : public OAuth2AccessTokenFetcher {
SSOAccessTokenFetcher::SSOAccessTokenFetcher(
OAuth2AccessTokenConsumer* consumer,
- ProfileOAuth2TokenServiceIOSProvider* provider,
+ DeviceAccountsProvider* provider,
const AccountInfo& account)
: OAuth2AccessTokenFetcher(consumer),
provider_(provider),
@@ -109,8 +117,7 @@ SSOAccessTokenFetcher::SSOAccessTokenFetcher(
DCHECK(provider_);
}
-SSOAccessTokenFetcher::~SSOAccessTokenFetcher() {
-}
+SSOAccessTokenFetcher::~SSOAccessTokenFetcher() {}
void SSOAccessTokenFetcher::Start(const std::string& client_id,
const std::string& client_secret_unused,
@@ -118,8 +125,8 @@ void SSOAccessTokenFetcher::Start(const std::string& client_id,
std::set<std::string> scopes_set(scopes.begin(), scopes.end());
provider_->GetAccessToken(
account_.gaia, client_id, scopes_set,
- base::Bind(&SSOAccessTokenFetcher::OnAccessTokenResponse,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&SSOAccessTokenFetcher::OnAccessTokenResponse,
+ weak_factory_.GetWeakPtr()));
}
void SSOAccessTokenFetcher::CancelRequest() {
@@ -149,7 +156,7 @@ void SSOAccessTokenFetcher::OnAccessTokenResponse(NSString* token,
ProfileOAuth2TokenServiceIOSDelegate::ProfileOAuth2TokenServiceIOSDelegate(
SigninClient* client,
- std::unique_ptr<ProfileOAuth2TokenServiceIOSProvider> provider,
+ std::unique_ptr<DeviceAccountsProvider> provider,
AccountTrackerService* account_tracker_service)
: client_(client),
provider_(std::move(provider)),
@@ -160,20 +167,22 @@ ProfileOAuth2TokenServiceIOSDelegate::ProfileOAuth2TokenServiceIOSDelegate(
}
ProfileOAuth2TokenServiceIOSDelegate::~ProfileOAuth2TokenServiceIOSDelegate() {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
void ProfileOAuth2TokenServiceIOSDelegate::Shutdown() {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
accounts_.clear();
}
void ProfileOAuth2TokenServiceIOSDelegate::LoadCredentials(
- const std::string& primary_account_id) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ const CoreAccountId& primary_account_id) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK_EQ(LOAD_CREDENTIALS_NOT_STARTED, load_credentials_state());
- set_load_credentials_state(LOAD_CREDENTIALS_IN_PROGRESS);
+ DCHECK_EQ(signin::LoadCredentialsState::LOAD_CREDENTIALS_NOT_STARTED,
+ load_credentials_state());
+ set_load_credentials_state(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS);
// Clean-up stale data from prefs.
ClearExcludedSecondaryAccounts();
@@ -181,32 +190,21 @@ void ProfileOAuth2TokenServiceIOSDelegate::LoadCredentials(
if (primary_account_id.empty()) {
// On startup, always fire refresh token loaded even if there is nothing
// to load (not authenticated).
- set_load_credentials_state(LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
+ set_load_credentials_state(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
FireRefreshTokensLoaded();
return;
}
- ReloadCredentials(primary_account_id);
+ ReloadCredentials();
- set_load_credentials_state(LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
+ set_load_credentials_state(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
FireRefreshTokensLoaded();
}
-void ProfileOAuth2TokenServiceIOSDelegate::ReloadCredentials(
- const std::string& primary_account_id) {
- DCHECK(!primary_account_id.empty());
- DCHECK(primary_account_id_.empty() ||
- primary_account_id_ == primary_account_id);
- primary_account_id_ = primary_account_id;
- ReloadCredentials();
-}
-
void ProfileOAuth2TokenServiceIOSDelegate::ReloadCredentials() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (primary_account_id_.empty()) {
- // Avoid loading the credentials if there is no primary account id.
- return;
- }
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Get the list of new account ids.
std::set<std::string> new_account_ids;
@@ -219,20 +217,20 @@ void ProfileOAuth2TokenServiceIOSDelegate::ReloadCredentials() {
// a fetch access token operation when it receives a
// |OnRefreshTokenAvailable| notification.
std::string account_id = account_tracker_service_->SeedAccountInfo(
- new_account.gaia, new_account.email);
+ AccountInfoFromDeviceAccount(new_account));
new_account_ids.insert(account_id);
}
// Get the list of existing account ids.
- std::vector<std::string> old_account_ids = GetAccounts();
+ std::vector<CoreAccountId> old_account_ids = GetAccounts();
std::sort(old_account_ids.begin(), old_account_ids.end());
- std::set<std::string> accounts_to_add =
- base::STLSetDifference<std::set<std::string>>(new_account_ids,
- old_account_ids);
- std::set<std::string> accounts_to_remove =
- base::STLSetDifference<std::set<std::string>>(old_account_ids,
- new_account_ids);
+ std::set<CoreAccountId> accounts_to_add =
+ base::STLSetDifference<std::set<CoreAccountId>>(new_account_ids,
+ old_account_ids);
+ std::set<CoreAccountId> accounts_to_remove =
+ base::STLSetDifference<std::set<CoreAccountId>>(old_account_ids,
+ new_account_ids);
if (accounts_to_add.empty() && accounts_to_remove.empty())
return;
@@ -250,15 +248,15 @@ void ProfileOAuth2TokenServiceIOSDelegate::ReloadCredentials() {
}
void ProfileOAuth2TokenServiceIOSDelegate::UpdateCredentials(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& refresh_token) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
NOTREACHED() << "Unexpected call to UpdateCredentials when using shared "
"authentication.";
}
void ProfileOAuth2TokenServiceIOSDelegate::RevokeAllCredentials() {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
ScopedBatchChange batch(this);
AccountStatusMap toRemove = accounts_;
@@ -266,59 +264,56 @@ void ProfileOAuth2TokenServiceIOSDelegate::RevokeAllCredentials() {
RemoveAccount(accountStatus.first);
DCHECK_EQ(0u, accounts_.size());
- primary_account_id_.clear();
ClearExcludedSecondaryAccounts();
}
-void ProfileOAuth2TokenServiceIOSDelegate::AddAccountFromSystem(
- const std::string& account_id) {
- AddOrUpdateAccount(account_id);
+void ProfileOAuth2TokenServiceIOSDelegate::ReloadAllAccountsFromSystem() {
+ ReloadCredentials();
}
-void ProfileOAuth2TokenServiceIOSDelegate::ReloadAccountsFromSystem(
- const std::string& primary_account_id) {
- if (primary_account_id.empty())
- return;
-
- ReloadCredentials(primary_account_id);
+void ProfileOAuth2TokenServiceIOSDelegate::ReloadAccountFromSystem(
+ const CoreAccountId& account_id) {
+ AddOrUpdateAccount(account_id);
}
-OAuth2AccessTokenFetcher*
+std::unique_ptr<OAuth2AccessTokenFetcher>
ProfileOAuth2TokenServiceIOSDelegate::CreateAccessTokenFetcher(
- const std::string& account_id,
+ const CoreAccountId& account_id,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
OAuth2AccessTokenConsumer* consumer) {
AccountInfo account_info =
account_tracker_service_->GetAccountInfo(account_id);
- return new SSOAccessTokenFetcher(consumer, provider_.get(), account_info);
+ return std::make_unique<SSOAccessTokenFetcher>(consumer, provider_.get(),
+ account_info);
}
-std::vector<std::string> ProfileOAuth2TokenServiceIOSDelegate::GetAccounts() {
- DCHECK(thread_checker_.CalledOnValidThread());
- std::vector<std::string> account_ids;
- for (auto i = accounts_.begin(); i != accounts_.end(); ++i)
- account_ids.push_back(i->first);
+std::vector<CoreAccountId> ProfileOAuth2TokenServiceIOSDelegate::GetAccounts()
+ const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ std::vector<CoreAccountId> account_ids;
+ for (const auto& account : accounts_)
+ account_ids.push_back(account.first);
return account_ids;
}
bool ProfileOAuth2TokenServiceIOSDelegate::RefreshTokenIsAvailable(
- const std::string& account_id) const {
- DCHECK(thread_checker_.CalledOnValidThread());
+ const CoreAccountId& account_id) const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return accounts_.count(account_id) > 0;
}
GoogleServiceAuthError ProfileOAuth2TokenServiceIOSDelegate::GetAuthError(
- const std::string& account_id) const {
+ const CoreAccountId& account_id) const {
auto it = accounts_.find(account_id);
return (it == accounts_.end()) ? GoogleServiceAuthError::AuthErrorNone()
: it->second.last_auth_error;
}
void ProfileOAuth2TokenServiceIOSDelegate::UpdateAuthError(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const GoogleServiceAuthError& error) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Do not report connection errors as these are not actually auth errors.
// We also want to avoid masking a "real" auth error just because we
@@ -341,8 +336,8 @@ void ProfileOAuth2TokenServiceIOSDelegate::UpdateAuthError(
// Clear the authentication error state and notify all observers that a new
// refresh token is available so that they request new access tokens.
void ProfileOAuth2TokenServiceIOSDelegate::AddOrUpdateAccount(
- const std::string& account_id) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ const CoreAccountId& account_id) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Account must have been seeded before attempting to add it.
DCHECK(!account_tracker_service_->GetAccountInfo(account_id).gaia.empty());
@@ -363,8 +358,8 @@ void ProfileOAuth2TokenServiceIOSDelegate::AddOrUpdateAccount(
}
void ProfileOAuth2TokenServiceIOSDelegate::RemoveAccount(
- const std::string& account_id) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ const CoreAccountId& account_id) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!account_id.empty());
if (accounts_.count(account_id) > 0) {
diff --git a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate_unittest.mm b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios_unittest.mm
index 38767190d58..0ae0cd018da 100644
--- a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate_unittest.mm
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios_unittest.mm
@@ -2,37 +2,39 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "components/signin/core/browser/test_signin_client.h"
-#include "components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/base/test_signin_client.h"
+#include "components/signin/public/identity_manager/ios/fake_device_accounts_provider.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/oauth2_access_token_consumer.h"
-#include "google_apis/gaia/oauth2_token_service_test_util.h"
+#include "google_apis/gaia/oauth2_access_token_fetcher.h"
+#include "google_apis/gaia/oauth2_access_token_manager_test_util.h"
+#include "google_apis/gaia/oauth2_token_service_observer.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
-typedef ProfileOAuth2TokenServiceIOSProvider::AccountInfo ProviderAccount;
+typedef DeviceAccountsProvider::AccountInfo ProviderAccount;
class ProfileOAuth2TokenServiceIOSDelegateTest
- : public testing::Test,
+ : public PlatformTest,
public OAuth2AccessTokenConsumer,
- public OAuth2TokenService::Observer {
+ public OAuth2TokenServiceObserver {
public:
ProfileOAuth2TokenServiceIOSDelegateTest()
- : factory_(NULL),
+ : factory_(nullptr),
client_(&prefs_),
token_available_count_(0),
token_revoked_count_(0),
@@ -51,7 +53,7 @@ class ProfileOAuth2TokenServiceIOSDelegateTest
prefs_.registry()->RegisterListPref(
prefs::kTokenServiceExcludedSecondaryAccounts);
- fake_provider_ = new FakeProfileOAuth2TokenServiceIOSProvider();
+ fake_provider_ = new FakeDeviceAccountsProvider();
factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_revoke_url(), "",
net::HTTP_OK, net::URLRequestStatus::SUCCESS);
oauth2_delegate_.reset(new ProfileOAuth2TokenServiceIOSDelegate(
@@ -75,15 +77,15 @@ class ProfileOAuth2TokenServiceIOSDelegateTest
last_access_token_error_ = error;
}
- // OAuth2TokenService::Observer implementation.
- void OnRefreshTokenAvailable(const std::string& account_id) override {
+ // OAuth2TokenServiceObserver implementation.
+ void OnRefreshTokenAvailable(const CoreAccountId& account_id) override {
++token_available_count_;
}
- void OnRefreshTokenRevoked(const std::string& account_id) override {
+ void OnRefreshTokenRevoked(const CoreAccountId& account_id) override {
++token_revoked_count_;
}
void OnRefreshTokensLoaded() override { ++tokens_loaded_count_; }
- void OnAuthErrorChanged(const std::string& account_id,
+ void OnAuthErrorChanged(const CoreAccountId& account_id,
const GoogleServiceAuthError& error) override {
++auth_error_changed_count_;
}
@@ -103,14 +105,14 @@ class ProfileOAuth2TokenServiceIOSDelegateTest
}
protected:
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
net::FakeURLFetcherFactory factory_;
TestingPrefServiceSimple prefs_;
TestSigninClient client_;
AccountTrackerService account_tracker_;
- FakeProfileOAuth2TokenServiceIOSProvider* fake_provider_;
+ FakeDeviceAccountsProvider* fake_provider_;
std::unique_ptr<ProfileOAuth2TokenServiceIOSDelegate> oauth2_delegate_;
- TestingOAuth2TokenServiceConsumer consumer_;
+ TestingOAuth2AccessTokenManagerConsumer consumer_;
int token_available_count_;
int token_revoked_count_;
int tokens_loaded_count_;
@@ -201,26 +203,10 @@ TEST_F(ProfileOAuth2TokenServiceIOSDelegateTest, ReloadCredentials) {
}
TEST_F(ProfileOAuth2TokenServiceIOSDelegateTest,
- ReloadCredentialsIgnoredIfNoPrimaryAccountId) {
- ProviderAccount account1 = fake_provider_->AddAccount("gaia_1", "email_1@x");
- ProviderAccount account2 = fake_provider_->AddAccount("gaia_2", "email_2@x");
- oauth2_delegate_->ReloadCredentials();
-
- EXPECT_EQ(0, token_available_count_);
- EXPECT_EQ(0, tokens_loaded_count_);
- EXPECT_EQ(0, token_revoked_count_);
- EXPECT_EQ(0U, oauth2_delegate_->GetAccounts().size());
- EXPECT_FALSE(
- oauth2_delegate_->RefreshTokenIsAvailable(GetAccountId(account1)));
- EXPECT_FALSE(
- oauth2_delegate_->RefreshTokenIsAvailable(GetAccountId(account2)));
-}
-
-TEST_F(ProfileOAuth2TokenServiceIOSDelegateTest,
ReloadCredentialsWithPrimaryAccountId) {
ProviderAccount account1 = fake_provider_->AddAccount("gaia_1", "email_1@x");
ProviderAccount account2 = fake_provider_->AddAccount("gaia_2", "email_2@x");
- oauth2_delegate_->ReloadCredentials(GetAccountId(account1));
+ oauth2_delegate_->ReloadCredentials();
EXPECT_EQ(2, token_available_count_);
EXPECT_EQ(0, tokens_loaded_count_);
@@ -285,7 +271,7 @@ TEST_F(ProfileOAuth2TokenServiceIOSDelegateTest, StartRequestFailure) {
TEST_F(ProfileOAuth2TokenServiceIOSDelegateTest,
UpdateAuthErrorAfterRevokeCredentials) {
ProviderAccount account1 = fake_provider_->AddAccount("gaia_1", "email_1@x");
- oauth2_delegate_->ReloadCredentials(GetAccountId(account1));
+ oauth2_delegate_->ReloadCredentials();
base::RunLoop().RunUntilIdle();
ResetObserverCounts();
@@ -303,7 +289,7 @@ TEST_F(ProfileOAuth2TokenServiceIOSDelegateTest,
TEST_F(ProfileOAuth2TokenServiceIOSDelegateTest, GetAuthError) {
// Accounts have no error by default.
ProviderAccount account1 = fake_provider_->AddAccount("gaia_1", "email_1@x");
- oauth2_delegate_->ReloadCredentials(GetAccountId(account1));
+ oauth2_delegate_->ReloadCredentials();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
oauth2_delegate_->GetAuthError("gaia_1"));
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_unittest.cc b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_unittest.cc
new file mode 100644
index 00000000000..f6132ef08f7
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_unittest.cc
@@ -0,0 +1,57 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+
+#include <string>
+
+#include "base/macros.h"
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "google_apis/gaia/oauth2_token_service_observer.h"
+#include "services/network/test/test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// The default implementation of
+// ProfileOAuth2TokenServiceDelegate::InvalidateTokensForMultilogin is used on
+// mobile where refresh tokens are not accessible. This test checks that refresh
+// tokens are not affected on INVALID_TOKENS Multilogin error.
+TEST(ProfileOAuth2TokenServiceDelegateTest, InvalidateTokensForMultilogin) {
+ class TestOAuth2TokenServiceObserver : public OAuth2TokenServiceObserver {
+ public:
+ MOCK_METHOD2(OnAuthErrorChanged,
+ void(const CoreAccountId&, const GoogleServiceAuthError&));
+ };
+
+ FakeProfileOAuth2TokenServiceDelegate delegate;
+
+ TestOAuth2TokenServiceObserver observer;
+ delegate.AddObserver(&observer);
+ // Check that OnAuthErrorChanged is not fired from
+ // InvalidateTokensForMultilogin and refresh tokens are not set in error.
+ EXPECT_CALL(
+ observer,
+ OnAuthErrorChanged(::testing::_,
+ GoogleServiceAuthError(
+ GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)))
+ .Times(0);
+
+ const CoreAccountId account_id1("account_id1");
+ const CoreAccountId account_id2("account_id2");
+
+ delegate.UpdateCredentials(account_id1, "refresh_token1");
+ delegate.UpdateCredentials(account_id2, "refresh_token2");
+
+ delegate.InvalidateTokenForMultilogin(account_id1);
+
+ EXPECT_EQ(delegate.GetAuthError(account_id1).state(),
+ GoogleServiceAuthError::NONE);
+ EXPECT_EQ(delegate.GetAuthError(account_id2).state(),
+ GoogleServiceAuthError::NONE);
+
+ delegate.RemoveObserver(&observer);
+}
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_unittest.cc b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_unittest.cc
new file mode 100644
index 00000000000..c77c9336b7f
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_unittest.cc
@@ -0,0 +1,824 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+
+#include <stddef.h>
+#include <string>
+
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/threading/platform_thread.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "google_apis/gaia/oauth2_access_token_consumer.h"
+#include "google_apis/gaia/oauth2_access_token_fetcher_immediate_error.h"
+#include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
+#include "google_apis/gaia/oauth2_access_token_manager.h"
+#include "google_apis/gaia/oauth2_access_token_manager_test_util.h"
+#include "net/http/http_status_code.h"
+#include "net/url_request/test_url_fetcher_factory.h"
+#include "net/url_request/url_fetcher_delegate.h"
+#include "net/url_request/url_request_test_util.h"
+#include "services/network/test/test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// A testing consumer that retries on error.
+class RetryingTestingOAuth2AccessTokenManagerConsumer
+ : public TestingOAuth2AccessTokenManagerConsumer {
+ public:
+ RetryingTestingOAuth2AccessTokenManagerConsumer(
+ ProfileOAuth2TokenService* oauth2_service,
+ const CoreAccountId& account_id)
+ : oauth2_service_(oauth2_service), account_id_(account_id) {}
+ ~RetryingTestingOAuth2AccessTokenManagerConsumer() override {}
+
+ void OnGetTokenFailure(const OAuth2AccessTokenManager::Request* request,
+ const GoogleServiceAuthError& error) override {
+ if (retry_counter_ <= 0)
+ return;
+ retry_counter_--;
+ TestingOAuth2AccessTokenManagerConsumer::OnGetTokenFailure(request, error);
+ request_ = oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), this);
+ }
+
+ int retry_counter_ = 2;
+ ProfileOAuth2TokenService* oauth2_service_;
+ CoreAccountId account_id_;
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request_;
+};
+
+class FakeOAuth2TokenServiceObserver : public OAuth2TokenServiceObserver {
+ public:
+ MOCK_METHOD2(OnAuthErrorChanged,
+ void(const CoreAccountId&, const GoogleServiceAuthError&));
+};
+
+// This class fakes the behaviour of a MutableProfileOAuth2TokenServiceDelegate
+// used on Desktop.
+class FakeProfileOAuth2TokenServiceDelegateDesktop
+ : public FakeProfileOAuth2TokenServiceDelegate {
+ std::string GetTokenForMultilogin(
+ const CoreAccountId& account_id) const override {
+ if (GetAuthError(account_id) == GoogleServiceAuthError::AuthErrorNone())
+ return GetRefreshToken(account_id);
+ return std::string();
+ }
+
+ std::unique_ptr<OAuth2AccessTokenFetcher> CreateAccessTokenFetcher(
+ const CoreAccountId& account_id,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ OAuth2AccessTokenConsumer* consumer) override {
+ if (GetAuthError(account_id).IsPersistentError()) {
+ return std::make_unique<OAuth2AccessTokenFetcherImmediateError>(
+ consumer, GetAuthError(account_id));
+ }
+ return FakeProfileOAuth2TokenServiceDelegate::CreateAccessTokenFetcher(
+ account_id, url_loader_factory, consumer);
+ }
+ void InvalidateTokenForMultilogin(
+ const CoreAccountId& failed_account) override {
+ UpdateAuthError(failed_account,
+ GoogleServiceAuthError(
+ GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
+ }
+};
+
+class ProfileOAuth2TokenServiceTest : public testing::Test {
+ public:
+ void SetUp() override {
+ auto delegate = std::make_unique<FakeProfileOAuth2TokenServiceDelegate>();
+ // Save raw delegate pointer for later.
+ delegate_ptr_ = delegate.get();
+
+ test_url_loader_factory_ = delegate->test_url_loader_factory();
+ oauth2_service_ = std::make_unique<ProfileOAuth2TokenService>(
+ &prefs_, std::move(delegate));
+ account_id_ = CoreAccountId("test_user@gmail.com");
+ }
+
+ void TearDown() override {
+ // Makes sure that all the clean up tasks are run.
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void SimulateOAuthTokenResponse(const std::string& token,
+ net::HttpStatusCode status = net::HTTP_OK) {
+ test_url_loader_factory_->AddResponse(
+ GaiaUrls::GetInstance()->oauth2_token_url().spec(), token, status);
+ }
+
+ protected:
+ base::MessageLoopForIO message_loop_; // net:: stuff needs IO message loop.
+ network::TestURLLoaderFactory* test_url_loader_factory_ = nullptr;
+ FakeProfileOAuth2TokenServiceDelegate* delegate_ptr_ = nullptr; // Not owned.
+ std::unique_ptr<ProfileOAuth2TokenService> oauth2_service_;
+ CoreAccountId account_id_;
+ TestingOAuth2AccessTokenManagerConsumer consumer_;
+ TestingPrefServiceSimple prefs_;
+};
+
+TEST_F(ProfileOAuth2TokenServiceTest, NoOAuth2RefreshToken) {
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(1, consumer_.number_of_errors_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, GetAccounts) {
+ // Accounts should start off empty.
+ auto accounts = oauth2_service_->GetAccounts();
+ EXPECT_TRUE(accounts.empty());
+
+ // Add an account.
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+
+ // Accounts should still be empty as tokens have not yet been loaded from
+ // disk.
+ accounts = oauth2_service_->GetAccounts();
+ EXPECT_TRUE(accounts.empty());
+
+ // Load tokens from disk.
+ oauth2_service_->GetDelegate()->LoadCredentials(CoreAccountId());
+
+ // |account_id_| should now be visible in the accounts.
+ accounts = oauth2_service_->GetAccounts();
+ EXPECT_THAT(accounts, testing::ElementsAre(account_id_));
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, FailureShouldNotRetry) {
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ SimulateOAuthTokenResponse("", net::HTTP_UNAUTHORIZED);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(1, consumer_.number_of_errors_);
+ EXPECT_EQ(0, test_url_loader_factory_->NumPending());
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, SuccessWithoutCaching) {
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+
+ SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("token", consumer_.last_token_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, SuccessWithCaching) {
+ OAuth2AccessTokenManager::ScopeSet scopes1;
+ scopes1.insert("s1");
+ scopes1.insert("s2");
+ OAuth2AccessTokenManager::ScopeSet scopes1_same;
+ scopes1_same.insert("s2");
+ scopes1_same.insert("s1");
+ OAuth2AccessTokenManager::ScopeSet scopes2;
+ scopes2.insert("s3");
+
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+
+ // First request.
+ SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(account_id_, scopes1, &consumer_));
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("token", consumer_.last_token_);
+
+ // Second request to the same set of scopes, should return the same token
+ // without needing a network request.
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request2(
+ oauth2_service_->StartRequest(account_id_, scopes1_same, &consumer_));
+ base::RunLoop().RunUntilIdle();
+
+ // No new network fetcher.
+ EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("token", consumer_.last_token_);
+
+ // Third request to a new set of scopes, should return another token.
+ SimulateOAuthTokenResponse(GetValidTokenResponse("token2", 3600));
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request3(
+ oauth2_service_->StartRequest(account_id_, scopes2, &consumer_));
+ EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(3, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("token2", consumer_.last_token_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, SuccessAndExpirationAndFailure) {
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+
+ // First request.
+ SimulateOAuthTokenResponse(GetValidTokenResponse("token", 0));
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("token", consumer_.last_token_);
+
+ // Second request must try to access the network as the token has expired.
+ SimulateOAuthTokenResponse("", net::HTTP_UNAUTHORIZED); // Network failure.
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request2(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(1, consumer_.number_of_errors_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, SuccessAndExpirationAndSuccess) {
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+
+ // First request.
+ SimulateOAuthTokenResponse(GetValidTokenResponse("token", 0));
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("token", consumer_.last_token_);
+
+ // Second request must try to access the network as the token has expired.
+ SimulateOAuthTokenResponse(GetValidTokenResponse("another token", 0));
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request2(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("another token", consumer_.last_token_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, RequestDeletedBeforeCompletion) {
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ(1, test_url_loader_factory_->NumPending());
+
+ request.reset();
+
+ SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
+
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, RequestDeletedAfterCompletion) {
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+
+ SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("token", consumer_.last_token_);
+
+ request.reset();
+
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("token", consumer_.last_token_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest,
+ MultipleRequestsForTheSameScopesWithOneDeleted) {
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+ base::RunLoop().RunUntilIdle();
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request2(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+ base::RunLoop().RunUntilIdle();
+
+ request.reset();
+
+ SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest,
+ ClearedRefreshTokenFailsSubsequentRequests) {
+ // We have a valid refresh token; the first request is successful.
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+ SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("token", consumer_.last_token_);
+
+ // The refresh token is no longer available; subsequent requests fail.
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_, "");
+ request = oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(1, consumer_.number_of_errors_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest,
+ ChangedRefreshTokenCancelsInFlightRequests) {
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "first refreshToken");
+ OAuth2AccessTokenManager::ScopeSet scopes;
+ scopes.insert("s1");
+ scopes.insert("s2");
+ OAuth2AccessTokenManager::ScopeSet scopes1;
+ scopes.insert("s3");
+ scopes.insert("s4");
+
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(account_id_, scopes, &consumer_));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(1, test_url_loader_factory_->NumPending());
+
+ // Note |request| is still pending when the refresh token changes.
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "second refreshToken");
+
+ // UpdateCredentials() triggers OnRefreshTokenAvailable() which causes
+ // CancelRequestsForAccount(). |consumer_| should have an error and the
+ // request pending should be 0 since it's canceled at
+ // OnRefreshTokenAvailable().
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(1, consumer_.number_of_errors_);
+ ASSERT_EQ(0, test_url_loader_factory_->NumPending());
+
+ // Verify that an access token request started after the refresh token was
+ // updated can complete successfully.
+ TestingOAuth2AccessTokenManagerConsumer consumer2;
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request2(
+ oauth2_service_->StartRequest(account_id_, scopes1, &consumer2));
+ base::RunLoop().RunUntilIdle();
+
+ network::URLLoaderCompletionStatus ok_status(net::OK);
+ network::ResourceResponseHead response_head =
+ network::CreateResourceResponseHead(net::HTTP_OK);
+ EXPECT_TRUE(test_url_loader_factory_->SimulateResponseForPendingRequest(
+ GaiaUrls::GetInstance()->oauth2_token_url(), ok_status, response_head,
+ GetValidTokenResponse("second token", 3600),
+ network::TestURLLoaderFactory::kMostRecentMatch));
+ EXPECT_EQ(1, consumer2.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer2.number_of_errors_);
+ EXPECT_EQ("second token", consumer2.last_token_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, StartRequestForMultiloginDesktop) {
+ class MockOAuth2AccessTokenConsumer
+ : public TestingOAuth2AccessTokenManagerConsumer {
+ public:
+ MockOAuth2AccessTokenConsumer() = default;
+ ~MockOAuth2AccessTokenConsumer() = default;
+
+ MOCK_METHOD2(
+ OnGetTokenSuccess,
+ void(const OAuth2AccessTokenManager::Request* request,
+ const OAuth2AccessTokenConsumer::TokenResponse& token_response));
+
+ MOCK_METHOD2(OnGetTokenFailure,
+ void(const OAuth2AccessTokenManager::Request* request,
+ const GoogleServiceAuthError& error));
+
+ DISALLOW_COPY_AND_ASSIGN(MockOAuth2AccessTokenConsumer);
+ };
+ ProfileOAuth2TokenService token_service(
+ &prefs_,
+ std::make_unique<FakeProfileOAuth2TokenServiceDelegateDesktop>());
+
+ token_service.GetDelegate()->UpdateCredentials(account_id_, "refreshToken");
+ const CoreAccountId account_id_2("account_id_2");
+ token_service.GetDelegate()->UpdateCredentials(account_id_2, "refreshToken");
+ token_service.GetDelegate()->UpdateAuthError(
+ account_id_2,
+ GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
+
+ MockOAuth2AccessTokenConsumer consumer;
+
+ EXPECT_CALL(consumer, OnGetTokenSuccess(::testing::_, ::testing::_)).Times(1);
+ EXPECT_CALL(
+ consumer,
+ OnGetTokenFailure(
+ ::testing::_,
+ GoogleServiceAuthError(GoogleServiceAuthError::USER_NOT_SIGNED_UP)))
+ .Times(1);
+ EXPECT_CALL(
+ consumer,
+ OnGetTokenFailure(::testing::_,
+ GoogleServiceAuthError(
+ GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)))
+ .Times(1);
+
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request1(
+ token_service.StartRequestForMultilogin(account_id_, &consumer));
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request2(
+ token_service.StartRequestForMultilogin(account_id_2, &consumer));
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request3(
+ token_service.StartRequestForMultilogin(CoreAccountId("unknown_account"),
+ &consumer));
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, StartRequestForMultiloginMobile) {
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequestForMultilogin(account_id_, &consumer_));
+
+ base::RunLoop().RunUntilIdle();
+ network::URLLoaderCompletionStatus ok_status(net::OK);
+ network::ResourceResponseHead response_head =
+ network::CreateResourceResponseHead(net::HTTP_OK);
+ EXPECT_TRUE(test_url_loader_factory_->SimulateResponseForPendingRequest(
+ GaiaUrls::GetInstance()->oauth2_token_url(), ok_status, response_head,
+ GetValidTokenResponse("second token", 3600),
+ network::TestURLLoaderFactory::kMostRecentMatch));
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, ServiceShutDownBeforeFetchComplete) {
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+
+ // The destructor should cancel all in-flight fetchers.
+ oauth2_service_.reset(nullptr);
+
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(1, consumer_.number_of_errors_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, RetryingConsumer) {
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+ RetryingTestingOAuth2AccessTokenManagerConsumer consumer(
+ oauth2_service_.get(), account_id_);
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer));
+ EXPECT_EQ(0, consumer.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer.number_of_errors_);
+
+ SimulateOAuthTokenResponse("", net::HTTP_UNAUTHORIZED);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0, consumer.number_of_successful_tokens_);
+ EXPECT_EQ(2, consumer.number_of_errors_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, InvalidateTokensForMultiloginDesktop) {
+ auto delegate =
+ std::make_unique<FakeProfileOAuth2TokenServiceDelegateDesktop>();
+ ProfileOAuth2TokenService token_service(&prefs_, std::move(delegate));
+ FakeOAuth2TokenServiceObserver observer;
+ token_service.GetDelegate()->AddObserver(&observer);
+ EXPECT_CALL(
+ observer,
+ OnAuthErrorChanged(account_id_,
+ GoogleServiceAuthError(
+ GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)))
+ .Times(1);
+
+ token_service.GetDelegate()->UpdateCredentials(account_id_, "refreshToken");
+ const CoreAccountId account_id_2("account_id_2");
+ token_service.GetDelegate()->UpdateCredentials(account_id_2, "refreshToken2");
+ token_service.InvalidateTokenForMultilogin(account_id_, "refreshToken");
+ // Check that refresh tokens for failed accounts are set in error.
+ EXPECT_EQ(token_service.GetDelegate()->GetAuthError(account_id_).state(),
+ GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
+ EXPECT_EQ(token_service.GetDelegate()->GetAuthError(account_id_2).state(),
+ GoogleServiceAuthError::NONE);
+
+ token_service.GetDelegate()->RemoveObserver(&observer);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, InvalidateTokensForMultiloginMobile) {
+ FakeOAuth2TokenServiceObserver observer;
+ oauth2_service_->GetDelegate()->AddObserver(&observer);
+ EXPECT_CALL(
+ observer,
+ OnAuthErrorChanged(account_id_,
+ GoogleServiceAuthError(
+ GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)))
+ .Times(0);
+
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+ const CoreAccountId account_id_2("account_id_2");
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_2,
+ "refreshToken2");
+ ;
+ oauth2_service_->InvalidateTokenForMultilogin(account_id_, "refreshToken");
+ // Check that refresh tokens are not affected.
+ EXPECT_EQ(oauth2_service_->GetDelegate()->GetAuthError(account_id_).state(),
+ GoogleServiceAuthError::NONE);
+ EXPECT_EQ(oauth2_service_->GetDelegate()->GetAuthError(account_id_2).state(),
+ GoogleServiceAuthError::NONE);
+
+ oauth2_service_->GetDelegate()->RemoveObserver(&observer);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, InvalidateToken) {
+ OAuth2AccessTokenManager::ScopeSet scopes;
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+
+ // First request.
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(account_id_, scopes, &consumer_));
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+
+ SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("token", consumer_.last_token_);
+
+ // Second request, should return the same token without needing a network
+ // request.
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request2(
+ oauth2_service_->StartRequest(account_id_, scopes, &consumer_));
+ base::RunLoop().RunUntilIdle();
+
+ // No new network fetcher.
+ EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("token", consumer_.last_token_);
+
+ // Clear previous response so the token request will be pending and we can
+ // simulate a response after it started.
+ test_url_loader_factory_->ClearResponses();
+
+ // Invalidating the token should return a new token on the next request.
+ oauth2_service_->InvalidateAccessToken(account_id_, scopes,
+ consumer_.last_token_);
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request3(
+ oauth2_service_->StartRequest(account_id_, scopes, &consumer_));
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+
+ SimulateOAuthTokenResponse(GetValidTokenResponse("token2", 3600));
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(3, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("token2", consumer_.last_token_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, CancelAllRequests) {
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+ const CoreAccountId account_id_2("account_id_2");
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_2,
+ "refreshToken2");
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request2(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+
+ oauth2_service_->CancelAllRequests();
+
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(2, consumer_.number_of_errors_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, CancelRequestsForAccount) {
+ OAuth2AccessTokenManager::ScopeSet scope_set_1;
+ scope_set_1.insert("scope1");
+ scope_set_1.insert("scope2");
+ OAuth2AccessTokenManager::ScopeSet scope_set_2(scope_set_1.begin(),
+ scope_set_1.end());
+ scope_set_2.insert("scope3");
+
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request1(
+ oauth2_service_->StartRequest(account_id_, scope_set_1, &consumer_));
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request2(
+ oauth2_service_->StartRequest(account_id_, scope_set_2, &consumer_));
+
+ const CoreAccountId account_id_2("account_id_2");
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_2,
+ "refreshToken2");
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request3(
+ oauth2_service_->StartRequest(account_id_2, scope_set_1, &consumer_));
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+
+ oauth2_service_->CancelRequestsForAccount(account_id_);
+
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(2, consumer_.number_of_errors_);
+
+ oauth2_service_->CancelRequestsForAccount(account_id_2);
+
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(3, consumer_.number_of_errors_);
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, SameScopesRequestedForDifferentClients) {
+ std::string client_id_1("client1");
+ std::string client_secret_1("secret1");
+ std::string client_id_2("client2");
+ std::string client_secret_2("secret2");
+ std::set<std::string> scope_set;
+ scope_set.insert("scope1");
+ scope_set.insert("scope2");
+
+ std::string refresh_token("refreshToken");
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_, refresh_token);
+
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request1(
+ oauth2_service_->StartRequestForClient(
+ account_id_, client_id_1, client_secret_1, scope_set, &consumer_));
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request2(
+ oauth2_service_->StartRequestForClient(
+ account_id_, client_id_2, client_secret_2, scope_set, &consumer_));
+ // Start a request that should be duplicate of |request1|.
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request3(
+ oauth2_service_->StartRequestForClient(
+ account_id_, client_id_1, client_secret_1, scope_set, &consumer_));
+ base::RunLoop().RunUntilIdle();
+
+ ASSERT_EQ(2U, oauth2_service_->GetNumPendingRequestsForTesting(
+ client_id_1, account_id_, scope_set));
+ ASSERT_EQ(1U, oauth2_service_->GetNumPendingRequestsForTesting(
+ client_id_2, account_id_, scope_set));
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, RequestParametersOrderTest) {
+ OAuth2AccessTokenManager::ScopeSet set_0;
+ OAuth2AccessTokenManager::ScopeSet set_1;
+ set_1.insert("1");
+
+ const CoreAccountId account_id0("0");
+ const CoreAccountId account_id1("1");
+ OAuth2AccessTokenManager::RequestParameters params[] = {
+ OAuth2AccessTokenManager::RequestParameters("0", "0", set_0),
+ OAuth2AccessTokenManager::RequestParameters("0", "0", set_1),
+ OAuth2AccessTokenManager::RequestParameters("0", "1", set_0),
+ OAuth2AccessTokenManager::RequestParameters("0", "1", set_1),
+ OAuth2AccessTokenManager::RequestParameters("1", "0", set_0),
+ OAuth2AccessTokenManager::RequestParameters("1", "0", set_1),
+ OAuth2AccessTokenManager::RequestParameters("1", "1", set_0),
+ OAuth2AccessTokenManager::RequestParameters("1", "1", set_1),
+ };
+
+ for (size_t i = 0; i < base::size(params); i++) {
+ for (size_t j = 0; j < base::size(params); j++) {
+ if (i == j) {
+ EXPECT_FALSE(params[i] < params[j]) << " i=" << i << ", j=" << j;
+ EXPECT_FALSE(params[j] < params[i]) << " i=" << i << ", j=" << j;
+ } else if (i < j) {
+ EXPECT_TRUE(params[i] < params[j]) << " i=" << i << ", j=" << j;
+ EXPECT_FALSE(params[j] < params[i]) << " i=" << i << ", j=" << j;
+ } else {
+ EXPECT_TRUE(params[j] < params[i]) << " i=" << i << ", j=" << j;
+ EXPECT_FALSE(params[i] < params[j]) << " i=" << i << ", j=" << j;
+ }
+ }
+ }
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, UpdateClearsCache) {
+ const CoreAccountId account_id("test@gmail.com");
+ std::set<std::string> scope_list;
+ scope_list.insert("scope");
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id, "refreshToken");
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(account_id, scope_list, &consumer_));
+ SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("token", consumer_.last_token_);
+ EXPECT_EQ(1, oauth2_service_->GetTokenCacheCountForTesting());
+
+ oauth2_service_->ClearCache();
+
+ EXPECT_EQ(0, oauth2_service_->GetTokenCacheCountForTesting());
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id, "refreshToken");
+ SimulateOAuthTokenResponse(GetValidTokenResponse("another token", 3600));
+ request = oauth2_service_->StartRequest(account_id, scope_list, &consumer_);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("another token", consumer_.last_token_);
+ EXPECT_EQ(1, oauth2_service_->GetTokenCacheCountForTesting());
+}
+
+TEST_F(ProfileOAuth2TokenServiceTest, FixRequestErrorIfPossible) {
+ oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
+ "refreshToken");
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request(
+ oauth2_service_->StartRequest(
+ account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+
+ delegate_ptr_->set_fix_request_if_possible(true);
+ SimulateOAuthTokenResponse("", net::HTTP_UNAUTHORIZED);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+
+ SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
+ base::RunLoop().RunUntilIdle();
+ for (int max_reties = 5;
+ max_reties >= 0 && consumer_.number_of_successful_tokens_ != 1;
+ --max_reties) {
+ base::RunLoop().RunUntilIdle();
+ base::PlatformThread::Sleep(TimeDelta::FromSeconds(1));
+ }
+
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("token", consumer_.last_token_);
+}
diff --git a/chromium/components/signin/core/browser/ubertoken_fetcher_impl.cc b/chromium/components/signin/internal/identity_manager/ubertoken_fetcher_impl.cc
index 61501805576..bc5b9f19b3e 100644
--- a/chromium/components/signin/core/browser/ubertoken_fetcher_impl.cc
+++ b/chromium/components/signin/internal/identity_manager/ubertoken_fetcher_impl.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/ubertoken_fetcher_impl.h"
+#include "components/signin/internal/identity_manager/ubertoken_fetcher_impl.h"
#include <vector>
@@ -13,7 +13,6 @@
#include "base/time/time.h"
#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/google_service_auth_error.h"
-#include "google_apis/gaia/oauth2_token_service.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
namespace {
@@ -31,8 +30,8 @@ namespace signin {
const int UbertokenFetcherImpl::kMaxRetries = 3;
UbertokenFetcherImpl::UbertokenFetcherImpl(
- const std::string& account_id,
- OAuth2TokenService* token_service,
+ const CoreAccountId& account_id,
+ ProfileOAuth2TokenService* token_service,
CompletionCallback ubertoken_callback,
gaia::GaiaSource source,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
@@ -47,13 +46,13 @@ UbertokenFetcherImpl::UbertokenFetcherImpl(
is_bound_to_channel_id) {}
UbertokenFetcherImpl::UbertokenFetcherImpl(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& access_token,
- OAuth2TokenService* token_service,
+ ProfileOAuth2TokenService* token_service,
CompletionCallback ubertoken_callback,
GaiaAuthFetcherFactory factory,
bool is_bound_to_channel_id)
- : OAuth2TokenService::Consumer("uber_token_fetcher"),
+ : OAuth2AccessTokenManager::Consumer("uber_token_fetcher"),
token_service_(token_service),
ubertoken_callback_(std::move(ubertoken_callback)),
is_bound_to_channel_id_(is_bound_to_channel_id),
@@ -101,7 +100,7 @@ void UbertokenFetcherImpl::OnUberAuthTokenFailure(
}
} else {
// The access token is invalid. Tell the token service.
- OAuth2TokenService::ScopeSet scopes;
+ OAuth2AccessTokenManager::ScopeSet scopes;
scopes.insert(GaiaConstants::kOAuth1LoginScope);
token_service_->InvalidateAccessToken(account_id_, scopes, access_token_);
@@ -119,7 +118,7 @@ void UbertokenFetcherImpl::OnUberAuthTokenFailure(
}
void UbertokenFetcherImpl::OnGetTokenSuccess(
- const OAuth2TokenService::Request* request,
+ const OAuth2AccessTokenManager::Request* request,
const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
DCHECK(!token_response.access_token.empty());
access_token_ = token_response.access_token;
@@ -128,7 +127,7 @@ void UbertokenFetcherImpl::OnGetTokenSuccess(
}
void UbertokenFetcherImpl::OnGetTokenFailure(
- const OAuth2TokenService::Request* request,
+ const OAuth2AccessTokenManager::Request* request,
const GoogleServiceAuthError& error) {
access_token_request_.reset();
std::move(ubertoken_callback_).Run(error, /*access_token=*/std::string());
@@ -139,7 +138,7 @@ void UbertokenFetcherImpl::RequestAccessToken() {
gaia_auth_fetcher_.reset();
retry_timer_.Stop();
- OAuth2TokenService::ScopeSet scopes;
+ OAuth2AccessTokenManager::ScopeSet scopes;
scopes.insert(GaiaConstants::kOAuth1LoginScope);
access_token_request_ =
token_service_->StartRequest(account_id_, scopes, this);
diff --git a/chromium/components/signin/core/browser/ubertoken_fetcher_impl.h b/chromium/components/signin/internal/identity_manager/ubertoken_fetcher_impl.h
index 423e675fb0d..8f38c5d99a3 100644
--- a/chromium/components/signin/core/browser/ubertoken_fetcher_impl.h
+++ b/chromium/components/signin/internal/identity_manager/ubertoken_fetcher_impl.h
@@ -2,21 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_UBERTOKEN_FETCHER_IMPL_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_UBERTOKEN_FETCHER_IMPL_H_
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_UBERTOKEN_FETCHER_IMPL_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_UBERTOKEN_FETCHER_IMPL_H_
#include <memory>
#include "base/macros.h"
#include "base/timer/timer.h"
-#include "components/signin/core/browser/ubertoken_fetcher.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/public/identity_manager/ubertoken_fetcher.h"
#include "google_apis/gaia/gaia_auth_consumer.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
-#include "google_apis/gaia/oauth2_token_service.h"
// Allow to retrieves an uber-auth token for the user. This class uses the
-// |OAuth2TokenService| and considers that the user is already logged in. It
-// will use the OAuth2 access token to generate the uber-auth token.
+// |ProfileOAuth2TokenService| and considers that the user is already logged in.
+// It will use the OAuth2 access token to generate the uber-auth token.
//
// This class should be used on a single thread, but it can be whichever thread
// that you like.
@@ -38,7 +38,7 @@ using GaiaAuthFetcherFactory =
// Allows to retrieve an uber-auth token.
class UbertokenFetcherImpl : public UbertokenFetcher,
public GaiaAuthConsumer,
- public OAuth2TokenService::Consumer {
+ public OAuth2AccessTokenManager::Consumer {
public:
// Maximum number of retries to get the uber-auth token before giving up.
static const int kMaxRetries;
@@ -51,32 +51,31 @@ class UbertokenFetcherImpl : public UbertokenFetcher,
// sequentially for |account_id|. Uses a default GaiaAuthFetcherFactory which
// returns base GaiaAuthFetcher instances.
UbertokenFetcherImpl(
- const std::string& account_id,
- OAuth2TokenService* token_service,
+ const CoreAccountId& account_id,
+ ProfileOAuth2TokenService* token_service,
CompletionCallback ubertoken_callback,
gaia::GaiaSource source,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
bool is_bound_to_channel_id = true);
// Constructs an instance and starts fetching the ubertoken for |account_id|.
- UbertokenFetcherImpl(
- const std::string& account_id,
- const std::string& access_token,
- OAuth2TokenService* token_service,
- CompletionCallback ubertoken_callback,
- GaiaAuthFetcherFactory factory,
- bool is_bound_to_channel_id = true);
+ UbertokenFetcherImpl(const CoreAccountId& account_id,
+ const std::string& access_token,
+ ProfileOAuth2TokenService* token_service,
+ CompletionCallback ubertoken_callback,
+ GaiaAuthFetcherFactory factory,
+ bool is_bound_to_channel_id = true);
~UbertokenFetcherImpl() override;
- // Overriden from GaiaAuthConsumer
+ // Overridden from GaiaAuthConsumer
void OnUberAuthTokenSuccess(const std::string& token) override;
void OnUberAuthTokenFailure(const GoogleServiceAuthError& error) override;
- // Overriden from OAuth2TokenService::Consumer:
+ // Overridden from OAuth2AccessTokenManager::Consumer:
void OnGetTokenSuccess(
- const OAuth2TokenService::Request* request,
+ const OAuth2AccessTokenManager::Request* request,
const OAuth2AccessTokenConsumer::TokenResponse& token_response) override;
- void OnGetTokenFailure(const OAuth2TokenService::Request* request,
+ void OnGetTokenFailure(const OAuth2AccessTokenManager::Request* request,
const GoogleServiceAuthError& error) override;
private:
@@ -86,13 +85,13 @@ class UbertokenFetcherImpl : public UbertokenFetcher,
// Exchanges an oauth2 access token for an uber-auth token.
void ExchangeTokens();
- OAuth2TokenService* token_service_;
+ ProfileOAuth2TokenService* token_service_;
CompletionCallback ubertoken_callback_;
bool is_bound_to_channel_id_; // defaults to true
GaiaAuthFetcherFactory gaia_auth_fetcher_factory_;
std::unique_ptr<GaiaAuthFetcher> gaia_auth_fetcher_;
- std::unique_ptr<OAuth2TokenService::Request> access_token_request_;
- std::string account_id_;
+ std::unique_ptr<OAuth2AccessTokenManager::Request> access_token_request_;
+ CoreAccountId account_id_;
std::string access_token_;
int retry_number_;
base::OneShotTimer retry_timer_;
@@ -103,4 +102,4 @@ class UbertokenFetcherImpl : public UbertokenFetcher,
} // namespace signin
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_UBERTOKEN_FETCHER_IMPL_H_
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_UBERTOKEN_FETCHER_IMPL_H_
diff --git a/chromium/components/signin/core/browser/ubertoken_fetcher_impl_unittest.cc b/chromium/components/signin/internal/identity_manager/ubertoken_fetcher_impl_unittest.cc
index 0dbf5eb1662..f4e7d910727 100644
--- a/chromium/components/signin/core/browser/ubertoken_fetcher_impl_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/ubertoken_fetcher_impl_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/ubertoken_fetcher_impl.h"
+#include "components/signin/internal/identity_manager/ubertoken_fetcher_impl.h"
#include <memory>
@@ -10,7 +10,8 @@
#include "base/memory/ref_counted.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "google_apis/gaia/fake_oauth2_token_service.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -52,6 +53,7 @@ class UbertokenFetcherImplTest : public testing::Test {
UbertokenFetcherImplTest()
: scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::UI),
+ token_service_(&pref_service_),
test_shared_loader_factory_(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&url_loader_factory_)) {
@@ -64,7 +66,8 @@ class UbertokenFetcherImplTest : public testing::Test {
protected:
base::test::ScopedTaskEnvironment scoped_task_environment_;
- FakeOAuth2TokenService token_service_;
+ TestingPrefServiceSimple pref_service_;
+ FakeProfileOAuth2TokenService token_service_;
network::TestURLLoaderFactory url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
MockUbertokenConsumer consumer_;
@@ -74,7 +77,7 @@ class UbertokenFetcherImplTest : public testing::Test {
TEST_F(UbertokenFetcherImplTest, Basic) {}
TEST_F(UbertokenFetcherImplTest, Success) {
- fetcher_->OnGetTokenSuccess(NULL,
+ fetcher_->OnGetTokenSuccess(nullptr,
OAuth2AccessTokenConsumer::TokenResponse(
"accessToken", base::Time(), std::string()));
fetcher_->OnUberAuthTokenSuccess("uberToken");
@@ -86,7 +89,7 @@ TEST_F(UbertokenFetcherImplTest, Success) {
TEST_F(UbertokenFetcherImplTest, NoRefreshToken) {
GoogleServiceAuthError error(GoogleServiceAuthError::USER_NOT_SIGNED_UP);
- fetcher_->OnGetTokenFailure(NULL, error);
+ fetcher_->OnGetTokenFailure(nullptr, error);
EXPECT_EQ(1, consumer_.nb_error_);
EXPECT_EQ(0, consumer_.nb_correct_token_);
@@ -94,7 +97,7 @@ TEST_F(UbertokenFetcherImplTest, NoRefreshToken) {
TEST_F(UbertokenFetcherImplTest, FailureToGetAccessToken) {
GoogleServiceAuthError error(GoogleServiceAuthError::USER_NOT_SIGNED_UP);
- fetcher_->OnGetTokenFailure(NULL, error);
+ fetcher_->OnGetTokenFailure(nullptr, error);
EXPECT_EQ(1, consumer_.nb_error_);
EXPECT_EQ(0, consumer_.nb_correct_token_);
@@ -103,7 +106,7 @@ TEST_F(UbertokenFetcherImplTest, FailureToGetAccessToken) {
TEST_F(UbertokenFetcherImplTest, TransientFailureEventualFailure) {
GoogleServiceAuthError error(GoogleServiceAuthError::CONNECTION_FAILED);
- fetcher_->OnGetTokenSuccess(NULL,
+ fetcher_->OnGetTokenSuccess(nullptr,
OAuth2AccessTokenConsumer::TokenResponse(
"accessToken", base::Time(), std::string()));
@@ -122,7 +125,7 @@ TEST_F(UbertokenFetcherImplTest, TransientFailureEventualFailure) {
TEST_F(UbertokenFetcherImplTest, TransientFailureEventualSuccess) {
GoogleServiceAuthError error(GoogleServiceAuthError::CONNECTION_FAILED);
- fetcher_->OnGetTokenSuccess(NULL,
+ fetcher_->OnGetTokenSuccess(nullptr,
OAuth2AccessTokenConsumer::TokenResponse(
"accessToken", base::Time(), std::string()));
@@ -140,7 +143,7 @@ TEST_F(UbertokenFetcherImplTest, TransientFailureEventualSuccess) {
}
TEST_F(UbertokenFetcherImplTest, PermanentFailureEventualFailure) {
- fetcher_->OnGetTokenSuccess(NULL,
+ fetcher_->OnGetTokenSuccess(nullptr,
OAuth2AccessTokenConsumer::TokenResponse(
"accessToken", base::Time(), std::string()));
@@ -150,7 +153,7 @@ TEST_F(UbertokenFetcherImplTest, PermanentFailureEventualFailure) {
EXPECT_EQ(0, consumer_.nb_correct_token_);
EXPECT_EQ("", consumer_.last_token_);
- fetcher_->OnGetTokenSuccess(NULL,
+ fetcher_->OnGetTokenSuccess(nullptr,
OAuth2AccessTokenConsumer::TokenResponse(
"accessToken", base::Time(), std::string()));
fetcher_->OnUberAuthTokenFailure(error);
@@ -161,7 +164,7 @@ TEST_F(UbertokenFetcherImplTest, PermanentFailureEventualFailure) {
TEST_F(UbertokenFetcherImplTest, PermanentFailureEventualSuccess) {
GoogleServiceAuthError error(GoogleServiceAuthError::USER_NOT_SIGNED_UP);
- fetcher_->OnGetTokenSuccess(NULL,
+ fetcher_->OnGetTokenSuccess(nullptr,
OAuth2AccessTokenConsumer::TokenResponse(
"accessToken", base::Time(), std::string()));
@@ -170,7 +173,7 @@ TEST_F(UbertokenFetcherImplTest, PermanentFailureEventualSuccess) {
EXPECT_EQ(0, consumer_.nb_correct_token_);
EXPECT_EQ("", consumer_.last_token_);
- fetcher_->OnGetTokenSuccess(NULL,
+ fetcher_->OnGetTokenSuccess(nullptr,
OAuth2AccessTokenConsumer::TokenResponse(
"accessToken", base::Time(), std::string()));
fetcher_->OnUberAuthTokenSuccess("uberToken");
diff --git a/chromium/components/signin/ios/DEPS b/chromium/components/signin/ios/DEPS
index bb46705add5..228a84fcbbe 100644
--- a/chromium/components/signin/ios/DEPS
+++ b/chromium/components/signin/ios/DEPS
@@ -1,5 +1,5 @@
include_rules = [
+ "+ios/web/common",
"+ios/web/public",
- "+services/identity/public/cpp",
"+third_party/ocmock",
]
diff --git a/chromium/components/signin/ios/browser/BUILD.gn b/chromium/components/signin/ios/browser/BUILD.gn
index 07fd4e192ae..7a6fc1ae28e 100644
--- a/chromium/components/signin/ios/browser/BUILD.gn
+++ b/chromium/components/signin/ios/browser/BUILD.gn
@@ -8,26 +8,27 @@ source_set("browser") {
"account_consistency_service.h",
"account_consistency_service.mm",
"manage_accounts_delegate.h",
- "profile_oauth2_token_service_ios_delegate.h",
- "profile_oauth2_token_service_ios_delegate.mm",
- "profile_oauth2_token_service_ios_provider.h",
- "profile_oauth2_token_service_ios_provider.mm",
"wait_for_network_callback_helper.cc",
"wait_for_network_callback_helper.h",
]
deps = [
- ":active_state_manager",
"//components/content_settings/core/browser",
"//components/google/core/browser",
- "//components/keyed_service/core",
- "//components/pref_registry",
"//components/prefs",
"//components/signin/core/browser",
- "//google_apis",
- "//ios/web",
+ "//components/signin/public/base",
+ "//ios/web/common:web_view_creation_util",
+ "//ios/web/public",
+ "//url",
+ ]
+
+ public_deps = [
+ ":active_state_manager",
+ "//base",
+ "//components/keyed_service/core",
+ "//components/signin/public/identity_manager",
"//net",
- "//services/identity/public/cpp:cpp",
]
}
@@ -45,41 +46,32 @@ source_set("active_state_manager") {
]
}
-source_set("test_support") {
- configs += [ "//build/config/compiler:enable_arc" ]
- testonly = true
- sources = [
- "fake_profile_oauth2_token_service_ios_provider.h",
- "fake_profile_oauth2_token_service_ios_provider.mm",
- ]
-
- public_deps = [
- ":browser",
- "//base",
- "//google_apis:test_support",
- ]
-}
-
source_set("unit_tests") {
configs += [ "//build/config/compiler:enable_arc" ]
testonly = true
sources = [
"account_consistency_service_unittest.mm",
"active_state_manager_impl_unittest.mm",
- "profile_oauth2_token_service_ios_delegate_unittest.mm",
"wait_for_network_callback_helper_unittest.cc",
]
deps = [
":active_state_manager",
- ":test_support",
- "//components/prefs:test_support",
+ ":browser",
+ "//base",
+ "//components/content_settings/core/browser",
+ "//components/prefs",
"//components/signin/core/browser",
+ "//components/signin/public/base:test_support",
+ "//components/signin/public/identity_manager",
+ "//components/signin/public/identity_manager:test_support",
"//components/sync_preferences:test_support",
"//ios/web",
"//ios/web/public/test",
"//ios/web/public/test/fakes",
- "//services/identity/public/cpp:test_support",
+ "//net:test_support",
+ "//testing/gmock",
+ "//testing/gtest",
"//third_party/ocmock",
]
}
diff --git a/chromium/components/signin/ios/browser/DEPS b/chromium/components/signin/ios/browser/DEPS
new file mode 100644
index 00000000000..1cbae6d899d
--- /dev/null
+++ b/chromium/components/signin/ios/browser/DEPS
@@ -0,0 +1,10 @@
+specific_include_rules = {
+ "account_consistency_service.mm": [
+ "+components/signin/core/browser/account_reconcilor.h",
+ "+components/signin/core/browser/signin_header_helper.h",
+ ],
+ "account_consistency_service_unittest.mm": [
+ "+components/signin/core/browser/account_reconcilor.h",
+ "+components/signin/core/browser/account_reconcilor_delegate.h",
+ ],
+}
diff --git a/chromium/components/signin/ios/browser/account_consistency_service.h b/chromium/components/signin/ios/browser/account_consistency_service.h
index e70f21b52c8..3d53f0a0f87 100644
--- a/chromium/components/signin/ios/browser/account_consistency_service.h
+++ b/chromium/components/signin/ios/browser/account_consistency_service.h
@@ -15,11 +15,14 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
-#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/signin/ios/browser/active_state_manager.h"
#import "components/signin/ios/browser/manage_accounts_delegate.h"
-#import "services/identity/public/cpp/identity_manager.h"
+#import "components/signin/public/identity_manager/identity_manager.h"
+
+namespace content_settings {
+class CookieSettings;
+}
namespace web {
class BrowserState;
@@ -28,6 +31,7 @@ class WebStatePolicyDecider;
}
class AccountReconcilor;
+class PrefService;
@class AccountConsistencyNavigationDelegate;
@class WKWebView;
@@ -38,7 +42,7 @@ class AccountReconcilor;
//
// This is currently only used when WKWebView is enabled.
class AccountConsistencyService : public KeyedService,
- public identity::IdentityManager::Observer,
+ public signin::IdentityManager::Observer,
public ActiveStateManager::Observer {
public:
// Name of the preference property that persists the domains that have a
@@ -50,7 +54,7 @@ class AccountConsistencyService : public KeyedService,
PrefService* prefs,
AccountReconcilor* account_reconcilor,
scoped_refptr<content_settings::CookieSettings> cookie_settings,
- identity::IdentityManager* identity_manager);
+ signin::IdentityManager* identity_manager);
~AccountConsistencyService() override;
// Registers the preferences used by AccountConsistencyService.
@@ -147,7 +151,7 @@ class AccountConsistencyService : public KeyedService,
void OnPrimaryAccountCleared(
const CoreAccountInfo& previous_account_info) override;
void OnAccountsInCookieUpdated(
- const identity::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+ const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
const GoogleServiceAuthError& error) override;
// ActiveStateManager::Observer implementation.
@@ -166,7 +170,7 @@ class AccountConsistencyService : public KeyedService,
scoped_refptr<content_settings::CookieSettings> cookie_settings_;
// Identity manager, observed to be notified of primary account signin and
// signout events.
- identity::IdentityManager* identity_manager_;
+ signin::IdentityManager* identity_manager_;
// Whether a CHROME_CONNECTED cookie request is currently being applied.
bool applying_cookie_requests_;
diff --git a/chromium/components/signin/ios/browser/account_consistency_service.mm b/chromium/components/signin/ios/browser/account_consistency_service.mm
index 66f2a50052a..0f8da0cafce 100644
--- a/chromium/components/signin/ios/browser/account_consistency_service.mm
+++ b/chromium/components/signin/ios/browser/account_consistency_service.mm
@@ -11,15 +11,17 @@
#import "base/mac/foundation_util.h"
#include "base/macros.h"
#include "base/strings/sys_string_conversions.h"
+#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/google/core/common/google_util.h"
#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
-#include "components/signin/core/browser/account_consistency_method.h"
#include "components/signin/core/browser/account_reconcilor.h"
#include "components/signin/core/browser/signin_header_helper.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "ios/web/common/web_view_creation_util.h"
#include "ios/web/public/browser_state.h"
-#include "ios/web/public/web_state/web_state_policy_decider.h"
-#include "ios/web/public/web_view_creation_util.h"
+#import "ios/web/public/navigation/web_state_policy_decider.h"
#include "net/base/mac/url_conversions.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "url/gurl.h"
@@ -42,7 +44,8 @@ NSString* const kChromeConnectedCookieTemplate =
"document.cookie=\"X-CHROME-CONNECTED=; path=/; domain=\" + domain + \";"
" expires=Thu, 01-Jan-1970 00:00:01 GMT\";"
"document.cookie=\"CHROME_CONNECTED=%@; path=/; domain=\" + domain + \";"
- " expires=\" + new Date(%f).toGMTString() + \"; secure;\"</script></html>";
+ " expires=\" + new Date(%f).toGMTString() + \"; secure;"
+ " samesite=lax;\"</script></html>";
// WebStatePolicyDecider that monitors the HTTP headers on Gaia responses,
// reacting on the X-Chrome-Manage-Accounts header and notifying its delegate.
@@ -219,7 +222,7 @@ AccountConsistencyService::AccountConsistencyService(
PrefService* prefs,
AccountReconcilor* account_reconcilor,
scoped_refptr<content_settings::CookieSettings> cookie_settings,
- identity::IdentityManager* identity_manager)
+ signin::IdentityManager* identity_manager)
: browser_state_(browser_state),
prefs_(prefs),
account_reconcilor_(account_reconcilor),
@@ -486,7 +489,7 @@ void AccountConsistencyService::OnPrimaryAccountCleared(
}
void AccountConsistencyService::OnAccountsInCookieUpdated(
- const identity::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+ const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
const GoogleServiceAuthError& error) {
AddChromeConnectedCookies();
}
diff --git a/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm b/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm
index 0a2e3d0648f..66f0de142e3 100644
--- a/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm
+++ b/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm
@@ -11,18 +11,21 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/values.h"
+#include "components/content_settings/core/browser/cookie_settings.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/prefs/pref_service.h"
#include "components/signin/core/browser/account_reconcilor.h"
#include "components/signin/core/browser/account_reconcilor_delegate.h"
-#include "components/signin/core/browser/list_accounts_test_utils.h"
-#include "components/signin/core/browser/test_signin_client.h"
+#include "components/signin/public/base/list_accounts_test_utils.h"
+#include "components/signin/public/base/test_signin_client.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "components/signin/public/identity_manager/test_identity_manager_observer.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "ios/web/public/navigation/web_state_policy_decider.h"
#include "ios/web/public/test/fakes/test_browser_state.h"
#import "ios/web/public/test/fakes/test_web_state.h"
#include "ios/web/public/test/test_web_thread_bundle.h"
-#include "ios/web/public/web_state/web_state_policy_decider.h"
-#import "services/identity/public/cpp/identity_manager.h"
-#import "services/identity/public/cpp/identity_test_environment.h"
-#include "services/identity/public/cpp/test_identity_manager_observer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
@@ -57,7 +60,7 @@ class FakeAccountConsistencyService : public AccountConsistencyService {
PrefService* prefs,
AccountReconcilor* account_reconcilor,
scoped_refptr<content_settings::CookieSettings> cookie_settings,
- identity::IdentityManager* identity_manager)
+ signin::IdentityManager* identity_manager)
: AccountConsistencyService(browser_state,
prefs,
account_reconcilor,
@@ -132,7 +135,7 @@ class AccountConsistencyServiceTest : public PlatformTest {
web_view_load_expection_count_ = 0;
signin_client_.reset(
new TestSigninClient(&prefs_, &test_url_loader_factory_));
- identity_test_env_.reset(new identity::IdentityTestEnvironment(
+ identity_test_env_.reset(new signin::IdentityTestEnvironment(
/*test_url_loader_factory=*/nullptr, &prefs_,
signin::AccountConsistencyMethod::kDisabled, signin_client_.get()));
settings_map_ = new HostContentSettingsMap(
@@ -184,14 +187,14 @@ class AccountConsistencyServiceTest : public PlatformTest {
}
void SignIn() {
- identity::MakePrimaryAccountAvailable(
- identity_test_env_->identity_manager(), "user@gmail.com");
+ signin::MakePrimaryAccountAvailable(identity_test_env_->identity_manager(),
+ "user@gmail.com");
EXPECT_EQ(0, web_view_load_expection_count_);
}
void SignOutAndSimulateGaiaCookieManagerServiceLogout() {
- identity::ClearPrimaryAccount(identity_test_env_->identity_manager(),
- identity::ClearPrimaryAccountPolicy::DEFAULT);
+ signin::ClearPrimaryAccount(identity_test_env_->identity_manager(),
+ signin::ClearPrimaryAccountPolicy::DEFAULT);
SimulateGaiaCookieManagerServiceLogout(true);
}
@@ -238,7 +241,7 @@ class AccountConsistencyServiceTest : public PlatformTest {
TestWebState web_state_;
network::TestURLLoaderFactory test_url_loader_factory_;
- std::unique_ptr<identity::IdentityTestEnvironment> identity_test_env_;
+ std::unique_ptr<signin::IdentityTestEnvironment> identity_test_env_;
// AccountConsistencyService being tested. Actually a
// FakeAccountConsistencyService to be able to use a mock web view.
std::unique_ptr<AccountConsistencyService> account_consistency_service_;
diff --git a/chromium/components/signin/ios/browser/active_state_manager_impl.mm b/chromium/components/signin/ios/browser/active_state_manager_impl.mm
index 26a7fc57fa0..494c88e2e20 100644
--- a/chromium/components/signin/ios/browser/active_state_manager_impl.mm
+++ b/chromium/components/signin/ios/browser/active_state_manager_impl.mm
@@ -7,7 +7,7 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "ios/web/public/browser_state.h"
-#include "ios/web/public/web_thread.h"
+#include "ios/web/public/thread/web_thread.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
diff --git a/chromium/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.mm b/chromium/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.mm
deleted file mode 100644
index ceed68ee896..00000000000
--- a/chromium/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.mm
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.h"
-
-#import <Foundation/Foundation.h>
-
-#include "base/logging.h"
-#include "base/strings/sys_string_conversions.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-FakeProfileOAuth2TokenServiceIOSProvider::
- FakeProfileOAuth2TokenServiceIOSProvider() {
-}
-
-FakeProfileOAuth2TokenServiceIOSProvider::
- ~FakeProfileOAuth2TokenServiceIOSProvider() {
-}
-
-void FakeProfileOAuth2TokenServiceIOSProvider::GetAccessToken(
- const std::string& account_id,
- const std::string& client_id,
- const std::set<std::string>& scopes,
- const AccessTokenCallback& callback) {
- requests_.push_back(AccessTokenRequest(account_id, callback));
-}
-
-std::vector<ProfileOAuth2TokenServiceIOSProvider::AccountInfo>
-FakeProfileOAuth2TokenServiceIOSProvider::GetAllAccounts() const {
- return accounts_;
-}
-
-ProfileOAuth2TokenServiceIOSProvider::AccountInfo
-FakeProfileOAuth2TokenServiceIOSProvider::AddAccount(const std::string& gaia,
- const std::string& email) {
- ProfileOAuth2TokenServiceIOSProvider::AccountInfo account;
- account.gaia = gaia;
- account.email = email;
- accounts_.push_back(account);
- return account;
-}
-
-void FakeProfileOAuth2TokenServiceIOSProvider::ClearAccounts() {
- accounts_.clear();
-}
-
-void FakeProfileOAuth2TokenServiceIOSProvider::
- IssueAccessTokenForAllRequests() {
- for (auto i = requests_.begin(); i != requests_.end(); ++i) {
- std::string account_id = i->first;
- AccessTokenCallback callback = i->second;
- NSString* access_token = [NSString
- stringWithFormat:@"fake_access_token [account=%s]", account_id.c_str()];
- NSDate* one_hour_from_now = [NSDate dateWithTimeIntervalSinceNow:3600];
- callback.Run(access_token, one_hour_from_now, nil);
- }
- requests_.clear();
-}
-
-void FakeProfileOAuth2TokenServiceIOSProvider::
- IssueAccessTokenErrorForAllRequests() {
- for (auto i = requests_.begin(); i != requests_.end(); ++i) {
- std::string account_id = i->first;
- AccessTokenCallback callback = i->second;
- NSError* error = [[NSError alloc] initWithDomain:@"fake_access_token_error"
- code:-1
- userInfo:nil];
- callback.Run(nil, nil, error);
- }
- requests_.clear();
-}
-
-AuthenticationErrorCategory
-FakeProfileOAuth2TokenServiceIOSProvider::GetAuthenticationErrorCategory(
- const std::string& gaia_id,
- NSError* error) const {
- DCHECK(error);
- return kAuthenticationErrorCategoryAuthorizationErrors;
-}
diff --git a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.mm b/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.mm
deleted file mode 100644
index f7b511916d3..00000000000
--- a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.mm
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-std::vector<ProfileOAuth2TokenServiceIOSProvider::AccountInfo>
-ProfileOAuth2TokenServiceIOSProvider::GetAllAccounts() const {
- return std::vector<ProfileOAuth2TokenServiceIOSProvider::AccountInfo>();
-}
-
-void ProfileOAuth2TokenServiceIOSProvider::GetAccessToken(
- const std::string& gaia_id,
- const std::string& client_id,
- const std::set<std::string>& scopes,
- const AccessTokenCallback& callback) {}
-
-AuthenticationErrorCategory
-ProfileOAuth2TokenServiceIOSProvider::GetAuthenticationErrorCategory(
- const std::string& gaia_id,
- NSError* error) const {
- return kAuthenticationErrorCategoryUnknownErrors;
-}
-
diff --git a/chromium/components/signin/ios/browser/wait_for_network_callback_helper_unittest.cc b/chromium/components/signin/ios/browser/wait_for_network_callback_helper_unittest.cc
index 78fe1caa9b1..7fb8e7cc040 100644
--- a/chromium/components/signin/ios/browser/wait_for_network_callback_helper_unittest.cc
+++ b/chromium/components/signin/ios/browser/wait_for_network_callback_helper_unittest.cc
@@ -4,6 +4,8 @@
#include "components/signin/ios/browser/wait_for_network_callback_helper.h"
+#include <memory>
+
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
@@ -20,12 +22,13 @@ class WaitForNetworkCallbackHelperTest : public testing::Test {
int num_callbacks_invoked_;
base::test::ScopedTaskEnvironment scoped_task_environment_;
- net::test::MockNetworkChangeNotifier network_change_notifier_;
+ std::unique_ptr<net::test::MockNetworkChangeNotifier>
+ network_change_notifier_ = net::test::MockNetworkChangeNotifier::Create();
WaitForNetworkCallbackHelper callback_helper_;
};
TEST_F(WaitForNetworkCallbackHelperTest, CallbackInvokedImmediately) {
- network_change_notifier_.SetConnectionType(
+ network_change_notifier_->SetConnectionType(
net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI);
callback_helper_.HandleCallback(
base::Bind(&WaitForNetworkCallbackHelperTest::CallbackFunction,
@@ -34,7 +37,7 @@ TEST_F(WaitForNetworkCallbackHelperTest, CallbackInvokedImmediately) {
}
TEST_F(WaitForNetworkCallbackHelperTest, CallbackInvokedLater) {
- network_change_notifier_.SetConnectionType(
+ network_change_notifier_->SetConnectionType(
net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE);
callback_helper_.HandleCallback(
base::Bind(&WaitForNetworkCallbackHelperTest::CallbackFunction,
@@ -44,9 +47,9 @@ TEST_F(WaitForNetworkCallbackHelperTest, CallbackInvokedLater) {
base::Unretained(this)));
EXPECT_EQ(0, num_callbacks_invoked_);
- network_change_notifier_.SetConnectionType(
+ network_change_notifier_->SetConnectionType(
net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI);
- network_change_notifier_.NotifyObserversOfConnectionTypeChangeForTests(
+ network_change_notifier_->NotifyObserversOfConnectionTypeChangeForTests(
net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(2, num_callbacks_invoked_);
diff --git a/chromium/components/signin/public/base/BUILD.gn b/chromium/components/signin/public/base/BUILD.gn
new file mode 100644
index 00000000000..688252e9342
--- /dev/null
+++ b/chromium/components/signin/public/base/BUILD.gn
@@ -0,0 +1,93 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/buildflag_header.gni")
+import("//components/signin/features.gni")
+
+if (is_android) {
+ import("//build/config/android/rules.gni")
+}
+
+buildflag_header("signin_buildflags") {
+ header = "signin_buildflags.h"
+ flags = [
+ "ENABLE_DICE_SUPPORT=$enable_dice_support",
+ "ENABLE_MIRROR=$enable_mirror",
+ ]
+}
+
+static_library("base") {
+ sources = [
+ "account_consistency_method.cc",
+ "account_consistency_method.h",
+ "avatar_icon_util.cc",
+ "avatar_icon_util.h",
+ "device_id_helper.cc",
+ "device_id_helper.h",
+ "signin_client.cc",
+ "signin_client.h",
+ "signin_metrics.cc",
+ "signin_metrics.h",
+ "signin_pref_names.cc",
+ "signin_pref_names.h",
+ "signin_switches.cc",
+ "signin_switches.h",
+ ]
+ deps = [
+ "//components/prefs",
+ "//third_party/icu:icui18n",
+ "//third_party/re2",
+ ]
+ public_deps = [
+ ":signin_buildflags",
+ "//base",
+ "//components/keyed_service/core",
+ "//google_apis",
+ "//url",
+ ]
+
+ if (is_chromeos) {
+ deps += [ "//components/user_manager" ]
+ }
+}
+
+static_library("test_support") {
+ testonly = true
+ sources = [
+ "list_accounts_test_utils.cc",
+ "list_accounts_test_utils.h",
+ "test_signin_client.cc",
+ "test_signin_client.h",
+ ]
+
+ deps = [
+ "//base/test:test_support",
+ "//components/prefs",
+ "//google_apis:test_support",
+ ]
+
+ public_deps = [
+ ":base",
+ "//base",
+ "//services/network:test_support",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "avatar_icon_util_unittest.cc",
+ "device_id_helper_unittest.cc",
+ "signin_metrics_unittest.cc",
+ ]
+
+ deps = [
+ ":base",
+ "//base",
+ "//base/test:test_support",
+ "//components/sync_preferences:test_support",
+ "//testing/gtest",
+ "//url",
+ ]
+}
diff --git a/chromium/components/signin/public/base/DEPS b/chromium/components/signin/public/base/DEPS
new file mode 100644
index 00000000000..ab69e125b8b
--- /dev/null
+++ b/chromium/components/signin/public/base/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+third_party/re2/src/re2/re2.h",
+]
diff --git a/chromium/components/signin/core/browser/account_consistency_method.cc b/chromium/components/signin/public/base/account_consistency_method.cc
index b0b031ae515..ba77c9a7afb 100644
--- a/chromium/components/signin/core/browser/account_consistency_method.cc
+++ b/chromium/components/signin/public/base/account_consistency_method.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/account_consistency_method.h"
+#include "components/signin/public/base/account_consistency_method.h"
#include "base/logging.h"
diff --git a/chromium/components/signin/core/browser/account_consistency_method.h b/chromium/components/signin/public/base/account_consistency_method.h
index c46becfe07d..5ca1dfeafa6 100644
--- a/chromium/components/signin/core/browser/account_consistency_method.h
+++ b/chromium/components/signin/public/base/account_consistency_method.h
@@ -6,8 +6,8 @@
// possible overrides from Experiements. This is done inside chrome/common
// because it is accessed by files through the chrome/ directory tree.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_CONSISTENCY_METHOD_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_CONSISTENCY_METHOD_H_
+#ifndef COMPONENTS_SIGNIN_PUBLIC_BASE_ACCOUNT_CONSISTENCY_METHOD_H_
+#define COMPONENTS_SIGNIN_PUBLIC_BASE_ACCOUNT_CONSISTENCY_METHOD_H_
#include "base/feature_list.h"
#include "build/build_config.h"
@@ -47,4 +47,4 @@ bool DiceMethodGreaterOrEqual(AccountConsistencyMethod a,
} // namespace signin
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_CONSISTENCY_METHOD_H_
+#endif // COMPONENTS_SIGNIN_PUBLIC_BASE_ACCOUNT_CONSISTENCY_METHOD_H_
diff --git a/chromium/components/signin/core/browser/avatar_icon_util.cc b/chromium/components/signin/public/base/avatar_icon_util.cc
index 2a74566b464..ff2dfa389df 100644
--- a/chromium/components/signin/core/browser/avatar_icon_util.cc
+++ b/chromium/components/signin/public/base/avatar_icon_util.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/avatar_icon_util.h"
+#include "components/signin/public/base/avatar_icon_util.h"
#include <string>
#include <vector>
diff --git a/chromium/components/signin/core/browser/avatar_icon_util.h b/chromium/components/signin/public/base/avatar_icon_util.h
index 4209820a8e0..26b6b83c0c4 100644
--- a/chromium/components/signin/core/browser/avatar_icon_util.h
+++ b/chromium/components/signin/public/base/avatar_icon_util.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_AVATAR_ICON_UTIL_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_AVATAR_ICON_UTIL_H_
+#ifndef COMPONENTS_SIGNIN_PUBLIC_BASE_AVATAR_ICON_UTIL_H_
+#define COMPONENTS_SIGNIN_PUBLIC_BASE_AVATAR_ICON_UTIL_H_
class GURL;
@@ -24,4 +24,4 @@ GURL GetAvatarImageURLWithOptions(const GURL& old_url,
} // namespace signin
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_AVATAR_ICON_UTIL_H_
+#endif // COMPONENTS_SIGNIN_PUBLIC_BASE_AVATAR_ICON_UTIL_H_
diff --git a/chromium/components/signin/core/browser/avatar_icon_util_unittest.cc b/chromium/components/signin/public/base/avatar_icon_util_unittest.cc
index f3686240080..0c8f7ce7f45 100644
--- a/chromium/components/signin/core/browser/avatar_icon_util_unittest.cc
+++ b/chromium/components/signin/public/base/avatar_icon_util_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/avatar_icon_util.h"
+#include "components/signin/public/base/avatar_icon_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
diff --git a/chromium/components/signin/core/browser/device_id_helper.cc b/chromium/components/signin/public/base/device_id_helper.cc
index 6f0dcbb748b..99c262add34 100644
--- a/chromium/components/signin/core/browser/device_id_helper.cc
+++ b/chromium/components/signin/public/base/device_id_helper.cc
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/device_id_helper.h"
+#include "components/signin/public/base/device_id_helper.h"
#include "base/command_line.h"
#include "base/guid.h"
#include "base/logging.h"
#include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "components/signin/core/browser/signin_switches.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/base/signin_switches.h"
namespace signin {
diff --git a/chromium/components/signin/core/browser/device_id_helper.h b/chromium/components/signin/public/base/device_id_helper.h
index 8e9980c99ae..6bda97cd33e 100644
--- a/chromium/components/signin/core/browser/device_id_helper.h
+++ b/chromium/components/signin/public/base/device_id_helper.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_DEVICE_ID_HELPER_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_DEVICE_ID_HELPER_H_
+#ifndef COMPONENTS_SIGNIN_PUBLIC_BASE_DEVICE_ID_HELPER_H_
+#define COMPONENTS_SIGNIN_PUBLIC_BASE_DEVICE_ID_HELPER_H_
#include <string>
@@ -39,4 +39,4 @@ std::string GetOrCreateScopedDeviceId(PrefService* prefs);
} // namespace signin
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_DEVICE_ID_HELPER_H_
+#endif // COMPONENTS_SIGNIN_PUBLIC_BASE_DEVICE_ID_HELPER_H_
diff --git a/chromium/components/signin/core/browser/device_id_helper_unittest.cc b/chromium/components/signin/public/base/device_id_helper_unittest.cc
index 3d35da3908b..1a0e30038bd 100644
--- a/chromium/components/signin/core/browser/device_id_helper_unittest.cc
+++ b/chromium/components/signin/public/base/device_id_helper_unittest.cc
@@ -2,13 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/device_id_helper.h"
+#include "components/signin/public/base/device_id_helper.h"
#include <string>
#include "build/build_config.h"
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_pref_names.h"
+#include "components/signin/public/base/signin_pref_names.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -24,7 +23,8 @@ TEST(DeviceIdHelper, GenerateSigninScopedDeviceId) {
TEST(DeviceIdHelper, RecreateSigninScopedDeviceId) {
sync_preferences::TestingPrefServiceSyncable prefs;
- ProfileOAuth2TokenService::RegisterProfilePrefs(prefs.registry());
+ prefs.registry()->RegisterStringPref(
+ prefs::kGoogleServicesSigninScopedDeviceId, std::string());
ASSERT_TRUE(
prefs.GetString(prefs::kGoogleServicesSigninScopedDeviceId).empty());
@@ -42,7 +42,9 @@ TEST(DeviceIdHelper, RecreateSigninScopedDeviceId) {
TEST(DeviceIdHelper, GetOrCreateScopedDeviceId) {
sync_preferences::TestingPrefServiceSyncable prefs;
- ProfileOAuth2TokenService::RegisterProfilePrefs(prefs.registry());
+ prefs.registry()->RegisterStringPref(
+ prefs::kGoogleServicesSigninScopedDeviceId, std::string());
+
ASSERT_TRUE(
prefs.GetString(prefs::kGoogleServicesSigninScopedDeviceId).empty());
diff --git a/chromium/components/signin/core/browser/list_accounts_test_utils.cc b/chromium/components/signin/public/base/list_accounts_test_utils.cc
index a8a41b2e2e7..d63a72d102c 100644
--- a/chromium/components/signin/core/browser/list_accounts_test_utils.cc
+++ b/chromium/components/signin/public/base/list_accounts_test_utils.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/list_accounts_test_utils.h"
+#include "components/signin/public/base/list_accounts_test_utils.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -23,13 +23,20 @@ void SetListAccountsResponseHttpNotFound(
/*content=*/"", net::HTTP_NOT_FOUND);
}
-void SetListAccountsResponseWebLoginRequired(
+void SetListAccountsResponseWithUnexpectedServiceResponse(
TestURLLoaderFactory* test_url_loader_factory) {
+ std::string source = GaiaConstants::kChromeSource;
+ // Set response for first request that will lead to a one time retry request.
+ test_url_loader_factory->AddResponse(
+ GaiaUrls::GetInstance()->ListAccountsURLWithSource(source).spec(), "");
+
+ // Seconde request would have the source with the error as a suffix.
test_url_loader_factory->AddResponse(
GaiaUrls::GetInstance()
- ->ListAccountsURLWithSource(GaiaConstants::kChromeSource)
+ ->ListAccountsURLWithSource(source +
+ GaiaConstants::kUnexpectedServiceResponse)
.spec(),
- "Info=WebLoginRequired");
+ "");
}
void SetListAccountsResponseWithParams(
diff --git a/chromium/components/signin/core/browser/list_accounts_test_utils.h b/chromium/components/signin/public/base/list_accounts_test_utils.h
index 9a5d897f0df..782c36402c2 100644
--- a/chromium/components/signin/core/browser/list_accounts_test_utils.h
+++ b/chromium/components/signin/public/base/list_accounts_test_utils.h
@@ -1,8 +1,8 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_LIST_ACCOUNTS_TEST_UTILS_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_LIST_ACCOUNTS_TEST_UTILS_H_
+#ifndef COMPONENTS_SIGNIN_PUBLIC_BASE_LIST_ACCOUNTS_TEST_UTILS_H_
+#define COMPONENTS_SIGNIN_PUBLIC_BASE_LIST_ACCOUNTS_TEST_UTILS_H_
#include <string>
#include <vector>
@@ -26,8 +26,9 @@ struct CookieParams {
void SetListAccountsResponseHttpNotFound(
network::TestURLLoaderFactory* test_url_loader_factory);
-// Make ListAccounts call return Info=WebLoginRequired.
-void SetListAccountsResponseWebLoginRequired(
+// Make ListAccounts call return an unexpected service response that leads to
+// a one time retry request. It also sets the response for the retry request.
+void SetListAccountsResponseWithUnexpectedServiceResponse(
network::TestURLLoaderFactory* test_url_loader_factory);
// Make ListAccounts return a list of accounts based on the provided |params|.
@@ -64,4 +65,4 @@ void SetListAccountsResponseTwoAccounts(
} // namespace signin
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_LIST_ACCOUNTS_TEST_UTILS_H_
+#endif // COMPONENTS_SIGNIN_PUBLIC_BASE_LIST_ACCOUNTS_TEST_UTILS_H_
diff --git a/chromium/components/signin/core/browser/signin_client.cc b/chromium/components/signin/public/base/signin_client.cc
index b6741ad109a..8a358e0d2ef 100644
--- a/chromium/components/signin/core/browser/signin_client.cc
+++ b/chromium/components/signin/public/base/signin_client.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/signin_client.h"
+#include "components/signin/public/base/signin_client.h"
void SigninClient::PreSignOut(
base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached,
diff --git a/chromium/components/signin/core/browser/signin_client.h b/chromium/components/signin/public/base/signin_client.h
index 8587e23de6c..d5c7889000c 100644
--- a/chromium/components/signin/core/browser/signin_client.h
+++ b/chromium/components/signin/public/base/signin_client.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_CLIENT_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_CLIENT_H_
+#ifndef COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_CLIENT_H_
+#define COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_CLIENT_H_
#include <memory>
@@ -12,9 +12,8 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "components/signin/core/browser/account_consistency_method.h"
-#include "components/signin/core/browser/account_info.h"
-#include "components/signin/core/browser/signin_metrics.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/base/signin_metrics.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
#include "url/gurl.h"
@@ -30,7 +29,7 @@ class SharedURLLoaderFactory;
namespace mojom {
class CookieManager;
}
-}
+} // namespace network
// An interface that needs to be supplied to the Signin component by its
// embedder.
@@ -73,9 +72,6 @@ class SigninClient : public KeyedService {
// For iOS, cookies should be cleaned up.
virtual void PreGaiaLogout(base::OnceClosure callback);
- virtual bool IsFirstRun() const = 0;
- virtual base::Time GetInstallDate() = 0;
-
// Returns true if GAIA cookies are allowed in the content area.
virtual bool AreSigninCookiesAllowed() = 0;
@@ -101,4 +97,4 @@ class SigninClient : public KeyedService {
virtual void SetReadyForDiceMigration(bool is_ready) {}
};
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_CLIENT_H_
+#endif // COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_CLIENT_H_
diff --git a/chromium/components/signin/core/browser/signin_metrics.cc b/chromium/components/signin/public/base/signin_metrics.cc
index 3827846b2f9..64a04cb7543 100644
--- a/chromium/components/signin/core/browser/signin_metrics.cc
+++ b/chromium/components/signin/public/base/signin_metrics.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/signin_metrics.h"
+#include "components/signin/public/base/signin_metrics.h"
#include <limits.h>
@@ -707,25 +707,6 @@ void LogSigninAccountReconciliationDuration(base::TimeDelta duration,
}
}
-void LogSigninProfile(bool is_first_run, base::Time install_date) {
- // Track whether or not the user signed in during the first run of Chrome.
- UMA_HISTOGRAM_BOOLEAN("Signin.DuringFirstRun", is_first_run);
-
- // Determine how much time passed since install when this profile was signed
- // in.
- base::TimeDelta elapsed_time = base::Time::Now() - install_date;
- UMA_HISTOGRAM_COUNTS_1M("Signin.ElapsedTimeFromInstallToSignin",
- elapsed_time.InMinutes());
-}
-
-void LogSigninAddAccount() {
- // Account signin may fail for a wide variety of reasons. There is no
- // explicit false, but one can compare this value with the various UI
- // flows that lead to account sign-in, and deduce that the difference
- // counts the failures.
- UMA_HISTOGRAM_BOOLEAN("Signin.AddAccount", true);
-}
-
void LogSignout(ProfileSignout source_metric, SignoutDelete delete_metric) {
UMA_HISTOGRAM_ENUMERATION("Signin.SignoutProfile", source_metric,
NUM_PROFILE_SIGNOUT_METRICS);
@@ -742,13 +723,11 @@ void LogExternalCcResultFetches(
UMA_HISTOGRAM_BOOLEAN("Signin.Reconciler.AllExternalCcResultCompleted",
fetches_completed);
if (fetches_completed) {
- UMA_HISTOGRAM_TIMES(
- "Signin.Reconciler.ExternalCcResultTime.Completed",
- time_to_check_connections);
+ UMA_HISTOGRAM_TIMES("Signin.Reconciler.ExternalCcResultTime.Completed",
+ time_to_check_connections);
} else {
- UMA_HISTOGRAM_TIMES(
- "Signin.Reconciler.ExternalCcResultTime.NotCompleted",
- time_to_check_connections);
+ UMA_HISTOGRAM_TIMES("Signin.Reconciler.ExternalCcResultTime.NotCompleted",
+ time_to_check_connections);
}
}
diff --git a/chromium/components/signin/core/browser/signin_metrics.h b/chromium/components/signin/public/base/signin_metrics.h
index b63c45b997b..77fe702a4e5 100644
--- a/chromium/components/signin/core/browser/signin_metrics.h
+++ b/chromium/components/signin/public/base/signin_metrics.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_METRICS_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_METRICS_H_
+#ifndef COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_METRICS_H_
+#define COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_METRICS_H_
#include <limits.h>
@@ -28,7 +28,7 @@ enum DifferentPrimaryAccounts {
// Track all the ways a profile can become signed out as a histogram.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.signin
// GENERATED_JAVA_CLASS_NAME_OVERRIDE: SignoutReason
-enum ProfileSignout {
+enum ProfileSignout : int {
// The value used within unit tests.
SIGNOUT_TEST = 0,
// The preference or policy controlling if signin is valid has changed.
@@ -296,8 +296,8 @@ enum class SourceForRefreshTokenOperation {
kTokenService_LoadCredentials,
kSupervisedUser_InitSync,
kInlineLoginHandler_Signin,
- kSigninManager_ClearPrimaryAccount,
- kSigninManager_LegacyPreDiceSigninFlow,
+ kPrimaryAccountManager_ClearAccount,
+ kPrimaryAccountManager_LegacyPreDiceSigninFlow,
kUserMenu_RemoveAccount,
kUserMenu_SignOutAllAccounts,
kSettings_Signout,
@@ -361,12 +361,6 @@ void RecordAccountsPerProfile(int total_number_accounts);
void LogSigninAccountReconciliationDuration(base::TimeDelta duration,
bool successful);
-// Track a successful signin.
-void LogSigninAddAccount();
-
-// Track a successful signin of a profile.
-void LogSigninProfile(bool is_first_run, base::Time install_date);
-
// Track a profile signout.
void LogSignout(ProfileSignout source_metric, SignoutDelete delete_metric);
@@ -435,4 +429,4 @@ void RecordSigninImpressionWithAccountUserActionForAccessPoint(
} // namespace signin_metrics
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_METRICS_H_
+#endif // COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_METRICS_H_
diff --git a/chromium/components/signin/core/browser/signin_metrics_unittest.cc b/chromium/components/signin/public/base/signin_metrics_unittest.cc
index ec4cb749f40..3a56f94ef53 100644
--- a/chromium/components/signin/core/browser/signin_metrics_unittest.cc
+++ b/chromium/components/signin/public/base/signin_metrics_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/signin_metrics.h"
+#include "components/signin/public/base/signin_metrics.h"
#include <string>
#include <vector>
@@ -129,8 +129,8 @@ class SigninMetricsTest : public ::testing::Test {
}
static bool AccessPointSupportsPersonalizedPromo(AccessPoint access_point) {
- return base::ContainsValue(kAccessPointsThatSupportPersonalizedPromos,
- access_point);
+ return base::Contains(kAccessPointsThatSupportPersonalizedPromos,
+ access_point);
}
};
diff --git a/chromium/components/signin/core/browser/signin_pref_names.cc b/chromium/components/signin/public/base/signin_pref_names.cc
index 75a77be466b..d613924ca51 100644
--- a/chromium/components/signin/core/browser/signin_pref_names.cc
+++ b/chromium/components/signin/public/base/signin_pref_names.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/signin_pref_names.h"
+#include "components/signin/public/base/signin_pref_names.h"
namespace prefs {
@@ -90,10 +90,6 @@ const char kGoogleServicesUsernamePattern[] =
const char kReverseAutologinRejectedEmailList[] =
"reverse_autologin.rejected_email_list";
-// Int64 which tracks, as time from epoch, when last time the user signed in
-// to the browser.
-const char kSignedInTime[] = "signin.signedin_time";
-
// Boolean indicating if this profile was signed in with information from a
// credential provider.
const char kSignedInWithCredentialProvider[] =
diff --git a/chromium/components/signin/core/browser/signin_pref_names.h b/chromium/components/signin/public/base/signin_pref_names.h
index 61391ea9f6b..01d8bab7e53 100644
--- a/chromium/components/signin/core/browser/signin_pref_names.h
+++ b/chromium/components/signin/public/base/signin_pref_names.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_PREF_NAMES_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_PREF_NAMES_H_
+#ifndef COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_PREF_NAMES_H_
+#define COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_PREF_NAMES_H_
namespace prefs {
@@ -25,7 +25,6 @@ extern const char kGoogleServicesUserAccountId[];
extern const char kGoogleServicesUsername[];
extern const char kGoogleServicesUsernamePattern[];
extern const char kReverseAutologinRejectedEmailList[];
-extern const char kSignedInTime[];
extern const char kSignedInWithCredentialProvider[];
extern const char kSigninAllowed[];
extern const char kTokenServiceDiceCompatible[];
@@ -34,4 +33,4 @@ extern const char kTokenServiceExcludedSecondaryAccounts[];
} // namespace prefs
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_PREF_NAMES_H_
+#endif // COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_PREF_NAMES_H_
diff --git a/chromium/components/signin/core/browser/signin_switches.cc b/chromium/components/signin/public/base/signin_switches.cc
index 7d99de9b7ea..fb905755f84 100644
--- a/chromium/components/signin/core/browser/signin_switches.cc
+++ b/chromium/components/signin/public/base/signin_switches.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/signin_switches.h"
+#include "components/signin/public/base/signin_switches.h"
namespace switches {
diff --git a/chromium/components/signin/core/browser/signin_switches.h b/chromium/components/signin/public/base/signin_switches.h
index 6c2752ebcaf..1397cbf4a40 100644
--- a/chromium/components/signin/core/browser/signin_switches.h
+++ b/chromium/components/signin/public/base/signin_switches.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_SWITCHES_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_SWITCHES_H_
+#ifndef COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_SWITCHES_H_
+#define COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_SWITCHES_H_
-#include "components/signin/core/browser/signin_buildflags.h"
+#include "components/signin/public/base/signin_buildflags.h"
namespace switches {
@@ -28,4 +28,4 @@ extern const char kAccountConsistencyDice[];
} // namespace switches
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_SWITCHES_H_
+#endif // COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_SWITCHES_H_
diff --git a/chromium/components/signin/core/browser/test_signin_client.cc b/chromium/components/signin/public/base/test_signin_client.cc
index 3a74d1ada5c..cfa57bc209c 100644
--- a/chromium/components/signin/core/browser/test_signin_client.cc
+++ b/chromium/components/signin/public/base/test_signin_client.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/test_signin_client.h"
+#include "components/signin/public/base/test_signin_client.h"
#include <memory>
@@ -68,7 +68,9 @@ void TestSigninClient::OverrideTestUrlLoaderFactory(
test_url_loader_factory_ = factory;
}
-std::string TestSigninClient::GetProductVersion() { return ""; }
+std::string TestSigninClient::GetProductVersion() {
+ return "";
+}
void TestSigninClient::SetNetworkCallsDelayed(bool value) {
network_calls_delayed_ = value;
@@ -80,14 +82,6 @@ void TestSigninClient::SetNetworkCallsDelayed(bool value) {
}
}
-bool TestSigninClient::IsFirstRun() const {
- return false;
-}
-
-base::Time TestSigninClient::GetInstallDate() {
- return base::Time::Now();
-}
-
bool TestSigninClient::AreSigninCookiesAllowed() {
return are_signin_cookies_allowed_;
}
@@ -97,12 +91,10 @@ bool TestSigninClient::AreSigninCookiesDeletedOnExit() {
}
void TestSigninClient::AddContentSettingsObserver(
- content_settings::Observer* observer) {
-}
+ content_settings::Observer* observer) {}
void TestSigninClient::RemoveContentSettingsObserver(
- content_settings::Observer* observer) {
-}
+ content_settings::Observer* observer) {}
void TestSigninClient::DelayNetworkCall(base::OnceClosure callback) {
if (network_calls_delayed_) {
diff --git a/chromium/components/signin/core/browser/test_signin_client.h b/chromium/components/signin/public/base/test_signin_client.h
index 2347b86a978..5ea2deeca75 100644
--- a/chromium/components/signin/core/browser/test_signin_client.h
+++ b/chromium/components/signin/public/base/test_signin_client.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_TEST_SIGNIN_CLIENT_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_TEST_SIGNIN_CLIENT_H_
+#ifndef COMPONENTS_SIGNIN_PUBLIC_BASE_TEST_SIGNIN_CLIENT_H_
+#define COMPONENTS_SIGNIN_PUBLIC_BASE_TEST_SIGNIN_CLIENT_H_
#include <memory>
#include <string>
@@ -14,7 +14,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "components/signin/core/browser/signin_client.h"
+#include "components/signin/public/base/signin_client.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
@@ -36,7 +36,7 @@ class TestSigninClient : public SigninClient {
void DoFinalInit() override;
- // Returns NULL.
+ // Returns nullptr.
// NOTE: This should be changed to return a properly-initalized PrefService
// once there is a unit test that requires it.
PrefService* GetPrefs() override;
@@ -80,9 +80,6 @@ class TestSigninClient : public SigninClient {
// executed immediately.
void SetNetworkCallsDelayed(bool value);
- // SigninClient overrides:
- bool IsFirstRun() const override;
- base::Time GetInstallDate() override;
bool AreSigninCookiesAllowed() override;
bool AreSigninCookiesDeletedOnExit() override;
void AddContentSettingsObserver(
@@ -113,4 +110,4 @@ class TestSigninClient : public SigninClient {
DISALLOW_COPY_AND_ASSIGN(TestSigninClient);
};
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_TEST_SIGNIN_CLIENT_H_
+#endif // COMPONENTS_SIGNIN_PUBLIC_BASE_TEST_SIGNIN_CLIENT_H_
diff --git a/chromium/components/signin/public/identity_manager/BUILD.gn b/chromium/components/signin/public/identity_manager/BUILD.gn
new file mode 100644
index 00000000000..28717d1888c
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/BUILD.gn
@@ -0,0 +1,133 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("identity_manager") {
+ sources = [
+ "access_token_fetcher.cc",
+ "access_token_fetcher.h",
+ "access_token_info.cc",
+ "access_token_info.h",
+ "account_info.cc",
+ "account_info.h",
+ "accounts_cookie_mutator.h",
+ "accounts_in_cookie_jar_info.cc",
+ "accounts_in_cookie_jar_info.h",
+ "accounts_mutator.h",
+ "device_accounts_synchronizer.h",
+ "diagnostics_provider.h",
+ "identity_manager.cc",
+ "identity_manager.h",
+ "identity_manager_builder.cc",
+ "identity_manager_builder.h",
+ "identity_utils.cc",
+ "identity_utils.h",
+ "load_credentials_state.h",
+ "primary_account_access_token_fetcher.cc",
+ "primary_account_access_token_fetcher.h",
+ "primary_account_mutator.h",
+ "set_accounts_in_cookie_result.h",
+ "ubertoken_fetcher.cc",
+ "ubertoken_fetcher.h",
+ ]
+
+ configs += [ "//build/config/compiler:wexit_time_destructors" ]
+
+ public_deps = [
+ "//base",
+ "//components/keyed_service/core",
+ "//components/signin/public/base",
+ "//components/signin/public/base:signin_buildflags",
+ "//google_apis",
+ "//services/identity/public/cpp:cpp_types",
+ "//ui/gfx",
+ ]
+
+ deps = [
+ "//components/image_fetcher/core",
+ "//components/prefs",
+ "//components/signin/internal/identity_manager",
+ "//components/signin/public/webdata",
+ "//services/network/public/cpp",
+ ]
+
+ if (is_chromeos) {
+ deps += [ "//components/user_manager" ]
+ }
+
+ if (is_ios) {
+ deps += [ "ios" ]
+ }
+
+ allow_circular_includes_from = [
+ # This target is a pair with internal/identity_manager. They always go
+ # together and include headers from each other.
+ "//components/signin/internal/identity_manager",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+
+ sources = [
+ "access_token_fetcher_unittest.cc",
+ "account_info_unittest.cc",
+ "accounts_cookie_mutator_unittest.cc",
+ "accounts_mutator_unittest.cc",
+ "diagnostics_provider_unittest.cc",
+ "identity_manager_unittest.cc",
+ "identity_test_environment_unittest.cc",
+ "identity_utils_unittest.cc",
+ "primary_account_access_token_fetcher_unittest.cc",
+ "primary_account_mutator_unittest.cc",
+ ]
+
+ deps = [
+ ":identity_manager",
+ ":test_support",
+ "//base",
+ "//base/test:test_support",
+ "//components/image_fetcher/core:test_support",
+ "//components/prefs",
+ "//components/prefs:test_support",
+ "//components/signin/internal/identity_manager",
+ "//components/signin/internal/identity_manager:test_support",
+ "//components/signin/public/base",
+ "//components/signin/public/base:test_support",
+ "//components/signin/public/identity_manager",
+ "//components/sync_preferences:test_support",
+ "//google_apis",
+ "//services/network:test_support",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+}
+
+source_set("test_support") {
+ testonly = true
+
+ sources = [
+ "identity_test_environment.cc",
+ "identity_test_environment.h",
+ "identity_test_utils.cc",
+ "identity_test_utils.h",
+ "test_identity_manager_observer.cc",
+ "test_identity_manager_observer.h",
+ ]
+
+ public_deps = [
+ "//base",
+ "//components/signin/public/base",
+ "//components/signin/public/identity_manager",
+ "//google_apis",
+ ]
+
+ deps = [
+ "//components/image_fetcher/core:test_support",
+ "//components/signin/internal/identity_manager",
+ "//components/signin/internal/identity_manager:test_support",
+ "//components/signin/public/base:test_support",
+ "//components/sync_preferences:test_support",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/components/signin/public/identity_manager/DEPS b/chromium/components/signin/public/identity_manager/DEPS
new file mode 100644
index 00000000000..eada2e2a7b8
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+components/signin/internal",
+]
diff --git a/chromium/components/signin/public/identity_manager/README.md b/chromium/components/signin/public/identity_manager/README.md
new file mode 100644
index 00000000000..5f68f505c4e
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/README.md
@@ -0,0 +1,38 @@
+IdentityManager is the next-generation C++ API for interacting with Google
+identity.
+
+Documentation on the mapping between usage of legacy signin
+classes (notably PrimaryAccountManager and ProfileOAuth2TokenService) and usage
+of IdentityManager is available here:
+
+https://docs.google.com/document/d/14f3qqkDM9IE4Ff_l6wuXvCMeHfSC9TxKezXTCyeaPUY/edit#
+
+A quick inline cheat sheet for developers migrating from usage of //components/
+signin and //google_apis/gaia:
+
+- "Primary account" in IdentityManager refers to what is called the
+ "authenticated account" in PrimaryAccountManager, i.e., the account that has
+ been blessed for sync by the user.
+- "Unconsented primary account" is intuitively the browsing identity of the user
+ that we display to the user; despite its name, the user may or may not have
+ blessed this account for sync. In particular, whenever a primary account
+ exists, the unconsented primary account equals to the primary account. On
+ desktop platforms (excl. ChromeOS), if no primary account exists and there
+ exist any content-area accounts, it equals to the first signed-in content-area
+ account. In all other cases there is no unconsented primary account.
+- PrimaryAccountTokenFetcher is the primary client-side interface for obtaining
+ access tokens for the primary account. In particular, it can take care of
+ waiting until the primary account is available.
+- AccessTokenFetcher is the client-side interface for obtaining access tokens
+ for arbitrary accounts.
+- IdentityTestEnvironment is the preferred test infrastructure for unittests
+ of production code that interacts with IdentityManager. It is suitable for
+ use in cases where neither the production code nor the unittest is interacting
+ with Profile (e.g., //components-level unittests).
+- identity_test_utils.h provides lower-level test facilities for interacting
+ explicitly with IdentityManager and its dependencies (PrimaryAccountManager,
+ ProfileOAuth2TokenService). These facilities are the way to interact with
+ IdentityManager in unittest contexts where the production code and/or the
+ unittest are interacting with Profile (in particular, where the
+ IdentityManager instance with which the test is interacting must be
+ IdentityManagerFactory::GetForProfile(profile)).
diff --git a/chromium/components/signin/public/identity_manager/access_token_fetcher.cc b/chromium/components/signin/public/identity_manager/access_token_fetcher.cc
new file mode 100644
index 00000000000..200770b2a40
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/access_token_fetcher.cc
@@ -0,0 +1,190 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/access_token_fetcher.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/public/identity_manager/access_token_info.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+namespace signin {
+
+AccessTokenFetcher::AccessTokenFetcher(const CoreAccountId& account_id,
+ const std::string& oauth_consumer_name,
+ ProfileOAuth2TokenService* token_service,
+ const identity::ScopeSet& scopes,
+ TokenCallback callback,
+ Mode mode)
+ : AccessTokenFetcher(account_id,
+ oauth_consumer_name,
+ token_service,
+ /*url_loader_factory=*/nullptr,
+ scopes,
+ std::move(callback),
+ mode) {}
+
+AccessTokenFetcher::AccessTokenFetcher(
+ const CoreAccountId& account_id,
+ const std::string& oauth_consumer_name,
+ ProfileOAuth2TokenService* token_service,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ const identity::ScopeSet& scopes,
+ TokenCallback callback,
+ Mode mode)
+ : AccessTokenFetcher(account_id,
+ /*client_id=*/std::string(),
+ /*client_secret=*/std::string(),
+ oauth_consumer_name,
+ token_service,
+ std::move(url_loader_factory),
+ scopes,
+ std::move(callback),
+ mode) {}
+
+AccessTokenFetcher::AccessTokenFetcher(const CoreAccountId& account_id,
+ const std::string client_id,
+ const std::string client_secret,
+ const std::string& oauth_consumer_name,
+ ProfileOAuth2TokenService* token_service,
+ const identity::ScopeSet& scopes,
+ TokenCallback callback,
+ Mode mode)
+ : AccessTokenFetcher(account_id,
+ client_id,
+ client_secret,
+ oauth_consumer_name,
+ token_service,
+ /*url_loader_factory=*/nullptr,
+ scopes,
+ std::move(callback),
+ mode) {}
+
+AccessTokenFetcher::AccessTokenFetcher(
+ const CoreAccountId& account_id,
+ const std::string client_id,
+ const std::string client_secret,
+ const std::string& oauth_consumer_name,
+ ProfileOAuth2TokenService* token_service,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ const identity::ScopeSet& scopes,
+ TokenCallback callback,
+ Mode mode)
+ : OAuth2AccessTokenManager::Consumer(oauth_consumer_name),
+ account_id_(account_id),
+ client_id_(client_id),
+ client_secret_(client_secret),
+ token_service_(token_service),
+ url_loader_factory_(std::move(url_loader_factory)),
+ scopes_(scopes),
+ mode_(mode),
+ callback_(std::move(callback)),
+ token_service_observer_(this) {
+ DCHECK(client_id_.empty() == client_secret_.empty());
+ DCHECK(client_id_.empty() || !url_loader_factory);
+
+ if (mode_ == Mode::kImmediate || IsRefreshTokenAvailable()) {
+ StartAccessTokenRequest();
+ return;
+ }
+
+ // Start observing the IdentityManager. This observer will be removed either
+ // when a refresh token is obtained and an access token request is started or
+ // when this object is destroyed.
+ token_service_observer_.Add(token_service_);
+}
+
+AccessTokenFetcher::~AccessTokenFetcher() {}
+
+bool AccessTokenFetcher::IsRefreshTokenAvailable() const {
+ DCHECK_EQ(Mode::kWaitUntilRefreshTokenAvailable, mode_);
+
+ return token_service_->RefreshTokenIsAvailable(account_id_);
+}
+
+void AccessTokenFetcher::StartAccessTokenRequest() {
+ DCHECK(mode_ == Mode::kImmediate || IsRefreshTokenAvailable());
+
+ // By the time of starting an access token request, we should no longer be
+ // listening for signin-related events.
+ DCHECK(!token_service_observer_.IsObserving(token_service_));
+
+ // Note: We might get here even in cases where we know that there's no refresh
+ // token. We're requesting an access token anyway, so that the token service
+ // will generate an appropriate error code that we can return to the client.
+ DCHECK(!access_token_request_);
+
+ // TODO(843510): Consider making the request to ProfileOAuth2TokenService
+ // asynchronously once there are no direct clients of PO2TS (i.e., PO2TS is
+ // used only by this class and IdentityManager).
+ if (!client_id_.empty()) {
+ // Setting both the client ID/secret and the URL loader factory is not
+ // currently supported.
+ access_token_request_ = token_service_->StartRequestForClient(
+ account_id_, client_id_, client_secret_, scopes_, this);
+ return;
+ }
+
+ if (url_loader_factory_) {
+ access_token_request_ = token_service_->StartRequestWithContext(
+ account_id_, url_loader_factory_, scopes_, this);
+ return;
+ }
+
+ access_token_request_ =
+ token_service_->StartRequest(account_id_, scopes_, this);
+}
+
+void AccessTokenFetcher::OnRefreshTokenAvailable(
+ const CoreAccountId& account_id) {
+ DCHECK_EQ(Mode::kWaitUntilRefreshTokenAvailable, mode_);
+
+ if (!IsRefreshTokenAvailable())
+ return;
+
+ token_service_observer_.Remove(token_service_);
+
+ StartAccessTokenRequest();
+}
+
+void AccessTokenFetcher::OnGetTokenSuccess(
+ const OAuth2AccessTokenManager::Request* request,
+ const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
+ DCHECK_EQ(request, access_token_request_.get());
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request_deleter(
+ std::move(access_token_request_));
+
+ RunCallbackAndMaybeDie(
+ GoogleServiceAuthError::AuthErrorNone(),
+ AccessTokenInfo(token_response.access_token,
+ token_response.expiration_time, token_response.id_token));
+
+ // Potentially dead after the above invocation; nothing to do except return.
+}
+
+void AccessTokenFetcher::OnGetTokenFailure(
+ const OAuth2AccessTokenManager::Request* request,
+ const GoogleServiceAuthError& error) {
+ DCHECK_EQ(request, access_token_request_.get());
+ std::unique_ptr<OAuth2AccessTokenManager::Request> request_deleter(
+ std::move(access_token_request_));
+
+ RunCallbackAndMaybeDie(error, AccessTokenInfo());
+
+ // Potentially dead after the above invocation; nothing to do except return.
+}
+
+void AccessTokenFetcher::RunCallbackAndMaybeDie(
+ GoogleServiceAuthError error,
+ AccessTokenInfo access_token_info) {
+ // Per the contract of this class, it is allowed for consumers to delete this
+ // object from within the callback that is run below. Hence, it is not safe to
+ // add any code below this call.
+ std::move(callback_).Run(std::move(error), std::move(access_token_info));
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/access_token_fetcher.h b/chromium/components/signin/public/identity_manager/access_token_fetcher.h
new file mode 100644
index 00000000000..0ee97625939
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/access_token_fetcher.h
@@ -0,0 +1,151 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCESS_TOKEN_FETCHER_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCESS_TOKEN_FETCHER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/scoped_observer.h"
+#include "google_apis/gaia/core_account_id.h"
+#include "google_apis/gaia/oauth2_access_token_manager.h"
+#include "google_apis/gaia/oauth2_token_service_observer.h"
+#include "services/identity/public/cpp/scope_set.h"
+
+namespace network {
+class SharedURLLoaderFactory;
+}
+
+class GoogleServiceAuthError;
+class ProfileOAuth2TokenService;
+
+namespace signin {
+struct AccessTokenInfo;
+
+// Helper class to ease the task of obtaining an OAuth2 access token for a
+// given account.
+// May only be used on the UI thread.
+class AccessTokenFetcher : public OAuth2TokenServiceObserver,
+ public OAuth2AccessTokenManager::Consumer {
+ public:
+ // Specifies how this instance should behave:
+ // |kImmediate|: Makes one-shot immediate request.
+ // |kWaitUntilRefreshTokenAvailable|: Waits for the account to have a refresh
+ // token before making the request.
+ // Note that using |kWaitUntilRefreshTokenAvailable| can result in waiting
+ // forever if the user is not signed in and doesn't sign in.
+ enum class Mode { kImmediate, kWaitUntilRefreshTokenAvailable };
+
+ // Callback for when a request completes (successful or not). On successful
+ // requests, |error| is NONE and |access_token_info| contains info of the
+ // obtained OAuth2 access token. On failed requests, |error| contains the
+ // actual error and |access_token_info| is empty.
+ // NOTE: At the time that this method is invoked, it is safe for the client to
+ // destroy the AccessTokenFetcher instance that is invoking this callback.
+ using TokenCallback =
+ base::OnceCallback<void(GoogleServiceAuthError error,
+ AccessTokenInfo access_token_info)>;
+
+ // Instantiates a fetcher and immediately starts the process of obtaining an
+ // OAuth2 access token for |account_id| and |scopes|. The |callback| is called
+ // once the request completes (successful or not). If the AccessTokenFetcher
+ // is destroyed before the process completes, the callback is not called.
+ AccessTokenFetcher(const CoreAccountId& account_id,
+ const std::string& oauth_consumer_name,
+ ProfileOAuth2TokenService* token_service,
+ const identity::ScopeSet& scopes,
+ TokenCallback callback,
+ Mode mode);
+
+ // Instantiates a fetcher and immediately starts the process of obtaining an
+ // OAuth2 access token for |account_id| and |scopes|, allowing clients to pass
+ // a |url_loader_factory| of their choice. The |callback| is called
+ // once the request completes (successful or not). If the AccessTokenFetcher
+ // is destroyed before the process completes, the callback is not called.
+ AccessTokenFetcher(
+ const CoreAccountId& account_id,
+ const std::string& oauth_consumer_name,
+ ProfileOAuth2TokenService* token_service,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ const identity::ScopeSet& scopes,
+ TokenCallback callback,
+ Mode mode);
+
+ // Instantiates a fetcher and immediately starts the process of obtaining an
+ // OAuth2 access token for |account_id| and |scopes| using both the
+ // |client_id| and |client_secret| to identify the OAuth client app.
+ AccessTokenFetcher(const CoreAccountId& account_id,
+ const std::string client_id,
+ const std::string client_secret,
+ const std::string& oauth_consumer_name,
+ ProfileOAuth2TokenService* token_service,
+ const identity::ScopeSet& scopes,
+ TokenCallback callback,
+ Mode mode);
+
+ ~AccessTokenFetcher() override;
+
+ private:
+ AccessTokenFetcher(
+ const CoreAccountId& account_id,
+ const std::string client_id,
+ const std::string client_secret,
+ const std::string& oauth_consumer_name,
+ ProfileOAuth2TokenService* token_service,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ const identity::ScopeSet& scopes,
+ TokenCallback callback,
+ Mode mode);
+
+ // Returns true iff a refresh token is available for |account_id_|. Should
+ // only be called in mode |kWaitUntilAvailable|.
+ bool IsRefreshTokenAvailable() const;
+
+ void StartAccessTokenRequest();
+
+ // OAuth2TokenServiceObserver implementation.
+ void OnRefreshTokenAvailable(const CoreAccountId& account_id) override;
+
+ // OAuth2AccessTokenManager::Consumer implementation.
+ void OnGetTokenSuccess(
+ const OAuth2AccessTokenManager::Request* request,
+ const OAuth2AccessTokenConsumer::TokenResponse& token_response) override;
+ void OnGetTokenFailure(const OAuth2AccessTokenManager::Request* request,
+ const GoogleServiceAuthError& error) override;
+
+ // Invokes |callback_| with (|error|, |access_token_info|). Per the contract
+ // of this class, it is allowed for clients to delete this object as part of
+ // the invocation of |callback_|. Hence, this object must assume that it is
+ // dead after invoking this method and must not run any more code.
+ void RunCallbackAndMaybeDie(GoogleServiceAuthError error,
+ AccessTokenInfo access_token_info);
+
+ const CoreAccountId account_id_;
+ const std::string client_id_;
+ const std::string client_secret_;
+ ProfileOAuth2TokenService* token_service_;
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+ const identity::ScopeSet scopes_;
+ const Mode mode_;
+
+ // NOTE: This callback should only be invoked from |RunCallbackAndMaybeDie|,
+ // as invoking it has the potential to destroy this object per this class's
+ // contract.
+ TokenCallback callback_;
+
+ ScopedObserver<ProfileOAuth2TokenService, AccessTokenFetcher>
+ token_service_observer_;
+
+ std::unique_ptr<OAuth2AccessTokenManager::Request> access_token_request_;
+
+ DISALLOW_COPY_AND_ASSIGN(AccessTokenFetcher);
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCESS_TOKEN_FETCHER_H_
diff --git a/chromium/components/signin/public/identity_manager/access_token_fetcher_unittest.cc b/chromium/components/signin/public/identity_manager/access_token_fetcher_unittest.cc
new file mode 100644
index 00000000000..2de2b66224d
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/access_token_fetcher_unittest.cc
@@ -0,0 +1,612 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/access_token_fetcher.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/test/mock_callback.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
+#include "components/signin/public/base/test_signin_client.h"
+#include "components/signin/public/identity_manager/access_token_info.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "google_apis/gaia/oauth2_access_token_consumer.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::MockCallback;
+using sync_preferences::TestingPrefServiceSyncable;
+using testing::_;
+using testing::StrictMock;
+
+namespace signin {
+
+namespace {
+
+const char kTestGaiaId[] = "dummyId";
+const char kTestGaiaId2[] = "dummyId2";
+const char kTestEmail[] = "me@gmail.com";
+const char kTestEmail2[] = "me2@gmail.com";
+
+// Used just to check that the id_token is passed along.
+const char kIdTokenEmptyServices[] =
+ "dummy-header."
+ "eyAic2VydmljZXMiOiBbXSB9" // payload: { "services": [] }
+ ".dummy-signature";
+} // namespace
+
+class AccessTokenFetcherTest
+ : public testing::Test,
+ public OAuth2AccessTokenManager::DiagnosticsObserver {
+ public:
+ using TestTokenCallback =
+ StrictMock<MockCallback<AccessTokenFetcher::TokenCallback>>;
+
+ AccessTokenFetcherTest()
+ : signin_client_(&pref_service_),
+ token_service_(&pref_service_),
+ access_token_info_("access token",
+ base::Time::Now() + base::TimeDelta::FromHours(1),
+ std::string(kIdTokenEmptyServices)) {
+ AccountTrackerService::RegisterPrefs(pref_service_.registry());
+
+ account_tracker_ = std::make_unique<AccountTrackerService>();
+ account_tracker_->Initialize(&pref_service_, base::FilePath());
+
+ token_service_.AddAccessTokenDiagnosticsObserver(this);
+ }
+
+ ~AccessTokenFetcherTest() override {
+ token_service_.RemoveAccessTokenDiagnosticsObserver(this);
+ }
+
+ std::string AddAccount(const std::string& gaia_id, const std::string& email) {
+ account_tracker()->SeedAccountInfo(gaia_id, email);
+ return account_tracker()->FindAccountInfoByGaiaId(gaia_id).account_id;
+ }
+
+ std::unique_ptr<AccessTokenFetcher> CreateFetcher(
+ const std::string& account_id,
+ AccessTokenFetcher::TokenCallback callback,
+ AccessTokenFetcher::Mode mode) {
+ std::set<std::string> scopes{"scope"};
+ return std::make_unique<AccessTokenFetcher>(account_id, "test_consumer",
+ &token_service_, scopes,
+ std::move(callback), mode);
+ }
+
+ std::unique_ptr<AccessTokenFetcher> CreateFetcherWithURLLoaderFactory(
+ const std::string& account_id,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ AccessTokenFetcher::TokenCallback callback,
+ AccessTokenFetcher::Mode mode) {
+ std::set<std::string> scopes{"scope"};
+ return std::make_unique<AccessTokenFetcher>(
+ account_id, "test_consumer", &token_service_, url_loader_factory,
+ scopes, std::move(callback), mode);
+ }
+
+ AccountTrackerService* account_tracker() { return account_tracker_.get(); }
+
+ FakeProfileOAuth2TokenService* token_service() { return &token_service_; }
+
+ void set_on_access_token_request_callback(base::OnceClosure callback) {
+ on_access_token_request_callback_ = std::move(callback);
+ }
+
+ // Returns an AccessTokenInfo with valid information that can be used for
+ // completing access token requests.
+ AccessTokenInfo access_token_info() { return access_token_info_; }
+
+ private:
+ // OAuth2AccessTokenManager::DiagnosticsObserver:
+ void OnAccessTokenRequested(
+ const CoreAccountId& account_id,
+ const std::string& consumer_id,
+ const OAuth2AccessTokenManager::ScopeSet& scopes) override {
+ if (on_access_token_request_callback_)
+ std::move(on_access_token_request_callback_).Run();
+ }
+
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ TestingPrefServiceSyncable pref_service_;
+ TestSigninClient signin_client_;
+ FakeProfileOAuth2TokenService token_service_;
+ AccessTokenInfo access_token_info_;
+ std::unique_ptr<AccountTrackerService> account_tracker_;
+ base::OnceClosure on_access_token_request_callback_;
+};
+
+TEST_F(AccessTokenFetcherTest, OneShotShouldCallBackOnFulfilledRequest) {
+ TestTokenCallback callback;
+
+ base::RunLoop run_loop;
+ set_on_access_token_request_callback(run_loop.QuitClosure());
+
+ std::string account_id = AddAccount(kTestGaiaId, kTestEmail);
+ token_service()->UpdateCredentials(account_id, "refresh token");
+
+ // This should result in a request for an access token.
+ auto fetcher = CreateFetcher(account_id, callback.Get(),
+ AccessTokenFetcher::Mode::kImmediate);
+
+ run_loop.Run();
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback, Run(GoogleServiceAuthError::AuthErrorNone(),
+ access_token_info()));
+
+ token_service()->IssueAllTokensForAccount(
+ account_id,
+ OAuth2AccessTokenConsumer::TokenResponse(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token));
+}
+
+TEST_F(AccessTokenFetcherTest,
+ WaitUntilAvailableShouldCallBackOnFulfilledRequest) {
+ TestTokenCallback callback;
+
+ base::RunLoop run_loop;
+ set_on_access_token_request_callback(run_loop.QuitClosure());
+
+ std::string account_id = AddAccount(kTestGaiaId, kTestEmail);
+ token_service()->UpdateCredentials(account_id, "refresh token");
+
+ // Since the refresh token is already available, this should result in an
+ // immediate request for an access token.
+ auto fetcher =
+ CreateFetcher(account_id, callback.Get(),
+ AccessTokenFetcher::Mode::kWaitUntilRefreshTokenAvailable);
+
+ run_loop.Run();
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback, Run(GoogleServiceAuthError::AuthErrorNone(),
+ access_token_info()));
+
+ token_service()->IssueAllTokensForAccount(
+ account_id,
+ OAuth2AccessTokenConsumer::TokenResponse(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token));
+}
+
+TEST_F(AccessTokenFetcherTest,
+ WaitUntilAvailableShouldCallBackOnFulfilledRequestAfterTokenAvailable) {
+ TestTokenCallback callback;
+
+ base::RunLoop run_loop;
+ set_on_access_token_request_callback(run_loop.QuitClosure());
+
+ std::string account_id = AddAccount(kTestGaiaId, kTestEmail);
+
+ // Since the refresh token is not available yet, this should just start
+ // waiting for it.
+ auto fetcher =
+ CreateFetcher(account_id, callback.Get(),
+ AccessTokenFetcher::Mode::kWaitUntilRefreshTokenAvailable);
+
+ // Before the refresh token is available, the callback shouldn't get called.
+ EXPECT_CALL(callback, Run(_, _)).Times(0);
+ token_service()->IssueAllTokensForAccount(
+ account_id,
+ OAuth2AccessTokenConsumer::TokenResponse(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token));
+
+ // Once the refresh token becomes available, we should get an access token
+ // request.
+ token_service()->UpdateCredentials(account_id, "refresh token");
+
+ run_loop.Run();
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback, Run(GoogleServiceAuthError::AuthErrorNone(),
+ access_token_info()));
+
+ token_service()->IssueAllTokensForAccount(
+ account_id,
+ OAuth2AccessTokenConsumer::TokenResponse(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token));
+}
+
+TEST_F(AccessTokenFetcherTest,
+ WaitUntilAvailableShouldIgnoreRefreshTokenForDifferentAccount) {
+ TestTokenCallback callback;
+
+ MockCallback<base::OnceClosure> access_token_request_callback;
+ set_on_access_token_request_callback(access_token_request_callback.Get());
+
+ std::string account_id = AddAccount(kTestGaiaId, kTestEmail);
+ std::string other_account_id = AddAccount(kTestGaiaId2, kTestEmail2);
+
+ // Since the refresh token is not available yet, this should just start
+ // waiting for it.
+ auto fetcher =
+ CreateFetcher(account_id, callback.Get(),
+ AccessTokenFetcher::Mode::kWaitUntilRefreshTokenAvailable);
+
+ // A refresh token for a different account should make no difference.
+ EXPECT_CALL(callback, Run(_, _)).Times(0);
+ EXPECT_CALL(access_token_request_callback, Run()).Times(0);
+ token_service()->UpdateCredentials(other_account_id, "refresh token");
+
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldNotReplyIfDestroyed) {
+ TestTokenCallback callback;
+
+ base::RunLoop run_loop;
+ set_on_access_token_request_callback(run_loop.QuitClosure());
+
+ std::string account_id = AddAccount(kTestGaiaId, kTestEmail);
+ token_service()->UpdateCredentials(account_id, "refresh token");
+
+ // This should result in a request for an access token.
+ auto fetcher = CreateFetcher(account_id, callback.Get(),
+ AccessTokenFetcher::Mode::kImmediate);
+
+ run_loop.Run();
+
+ // Destroy the fetcher before the access token request is fulfilled.
+ fetcher.reset();
+
+ // Now fulfilling the access token request should have no effect.
+ token_service()->IssueAllTokensForAccount(
+ account_id,
+ OAuth2AccessTokenConsumer::TokenResponse(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token));
+}
+
+TEST_F(AccessTokenFetcherTest, ReturnsErrorWhenAccountIsUnknown) {
+ TestTokenCallback callback;
+
+ base::RunLoop run_loop;
+
+ // Account not present -> we should get called back.
+ auto fetcher = CreateFetcher("dummy_account_id", callback.Get(),
+ AccessTokenFetcher::Mode::kImmediate);
+
+ EXPECT_CALL(callback,
+ Run(GoogleServiceAuthError(
+ GoogleServiceAuthError::State::USER_NOT_SIGNED_UP),
+ AccessTokenInfo()))
+ .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
+
+ run_loop.Run();
+}
+
+TEST_F(AccessTokenFetcherTest, ReturnsErrorWhenAccountHasNoRefreshToken) {
+ TestTokenCallback callback;
+
+ base::RunLoop run_loop;
+
+ std::string account_id = AddAccount(kTestGaiaId, kTestEmail);
+
+ // Account has no refresh token -> we should get called back.
+ auto fetcher = CreateFetcher(account_id, callback.Get(),
+ AccessTokenFetcher::Mode::kImmediate);
+
+ EXPECT_CALL(callback,
+ Run(GoogleServiceAuthError(
+ GoogleServiceAuthError::State::USER_NOT_SIGNED_UP),
+ AccessTokenInfo()))
+ .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
+
+ run_loop.Run();
+}
+
+TEST_F(AccessTokenFetcherTest, CanceledAccessTokenRequest) {
+ TestTokenCallback callback;
+
+ base::RunLoop run_loop;
+ set_on_access_token_request_callback(run_loop.QuitClosure());
+
+ std::string account_id = AddAccount(kTestGaiaId, kTestEmail);
+ token_service()->UpdateCredentials(account_id, "refresh token");
+
+ // This should result in a request for an access token.
+ auto fetcher = CreateFetcher(account_id, callback.Get(),
+ AccessTokenFetcher::Mode::kImmediate);
+
+ run_loop.Run();
+
+ base::RunLoop run_loop2;
+ EXPECT_CALL(
+ callback,
+ Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
+ AccessTokenInfo()))
+ .WillOnce(testing::InvokeWithoutArgs(&run_loop2, &base::RunLoop::Quit));
+
+ // A canceled access token request should result in a callback.
+ token_service()->IssueErrorForAllPendingRequestsForAccount(
+ account_id,
+ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
+
+ run_loop2.Run();
+}
+
+TEST_F(AccessTokenFetcherTest, RefreshTokenRevoked) {
+ base::RunLoop run_loop;
+ set_on_access_token_request_callback(run_loop.QuitClosure());
+
+ TestTokenCallback callback;
+
+ std::string account_id = AddAccount(kTestGaiaId, kTestEmail);
+ token_service()->UpdateCredentials(account_id, "refresh token");
+
+ // This should result in a request for an access token.
+ auto fetcher = CreateFetcher(account_id, callback.Get(),
+ AccessTokenFetcher::Mode::kImmediate);
+
+ run_loop.Run();
+
+ // Revoke the refresh token, which should cancel all pending requests. The
+ // fetcher should *not* retry.
+ EXPECT_CALL(
+ callback,
+ Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
+ AccessTokenInfo()));
+ token_service()->RevokeCredentials(account_id);
+}
+
+TEST_F(AccessTokenFetcherTest, FailedAccessTokenRequest) {
+ base::RunLoop run_loop;
+ set_on_access_token_request_callback(run_loop.QuitClosure());
+
+ TestTokenCallback callback;
+
+ std::string account_id = AddAccount(kTestGaiaId, kTestEmail);
+ token_service()->UpdateCredentials(account_id, "refresh token");
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(account_id, callback.Get(),
+ AccessTokenFetcher::Mode::kImmediate);
+
+ run_loop.Run();
+
+ // We should immediately get called back with an empty access token.
+ EXPECT_CALL(
+ callback,
+ Run(GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE),
+ AccessTokenInfo()));
+ token_service()->IssueErrorForAllPendingRequestsForAccount(
+ account_id,
+ GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
+}
+
+TEST_F(AccessTokenFetcherTest, MultipleRequestsForSameAccountFulfilled) {
+ TestTokenCallback callback;
+
+ base::RunLoop run_loop;
+ set_on_access_token_request_callback(run_loop.QuitClosure());
+
+ std::string account_id = AddAccount(kTestGaiaId, kTestEmail);
+ token_service()->UpdateCredentials(account_id, "refresh token");
+
+ // This should result in a request for an access token.
+ auto fetcher = CreateFetcher(account_id, callback.Get(),
+ AccessTokenFetcher::Mode::kImmediate);
+
+ run_loop.Run();
+
+ // This should also result in a request for an access token.
+ TestTokenCallback callback2;
+ base::RunLoop run_loop2;
+ set_on_access_token_request_callback(run_loop2.QuitClosure());
+ auto fetcher2 = CreateFetcher(account_id, callback2.Get(),
+ AccessTokenFetcher::Mode::kImmediate);
+ run_loop2.Run();
+
+ // Once the access token request is fulfilled, both requests should get
+ // called back with the access token.
+ EXPECT_CALL(callback, Run(GoogleServiceAuthError::AuthErrorNone(),
+ access_token_info()));
+ EXPECT_CALL(callback2, Run(GoogleServiceAuthError::AuthErrorNone(),
+ access_token_info()));
+ token_service()->IssueAllTokensForAccount(
+ account_id,
+ OAuth2AccessTokenConsumer::TokenResponse(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token));
+}
+
+TEST_F(AccessTokenFetcherTest, MultipleRequestsForDifferentAccountsFulfilled) {
+ TestTokenCallback callback;
+
+ base::RunLoop run_loop;
+ set_on_access_token_request_callback(run_loop.QuitClosure());
+
+ std::string account_id = AddAccount(kTestGaiaId, kTestEmail);
+ token_service()->UpdateCredentials(account_id, "refresh token");
+
+ // This should result in a request for an access token.
+ auto fetcher = CreateFetcher(account_id, callback.Get(),
+ AccessTokenFetcher::Mode::kImmediate);
+
+ run_loop.Run();
+
+ // Add a second account and request an access token for it.
+ std::string account_id2 = AddAccount(kTestGaiaId2, kTestEmail2);
+ token_service()->UpdateCredentials(account_id2, "refresh token");
+ TestTokenCallback callback2;
+ base::RunLoop run_loop2;
+ set_on_access_token_request_callback(run_loop2.QuitClosure());
+ auto fetcher2 = CreateFetcher(account_id2, callback2.Get(),
+ AccessTokenFetcher::Mode::kImmediate);
+ run_loop2.Run();
+
+ // Once the first access token request is fulfilled, it should get
+ // called back with the access token.
+ EXPECT_CALL(callback, Run(GoogleServiceAuthError::AuthErrorNone(),
+ access_token_info()));
+ token_service()->IssueAllTokensForAccount(
+ account_id,
+ OAuth2AccessTokenConsumer::TokenResponse(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token));
+
+ // Once the second access token request is fulfilled, it should get
+ // called back with the access token.
+ EXPECT_CALL(callback2, Run(GoogleServiceAuthError::AuthErrorNone(),
+ access_token_info()));
+ token_service()->IssueAllTokensForAccount(
+ account_id2,
+ OAuth2AccessTokenConsumer::TokenResponse(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token));
+}
+
+TEST_F(AccessTokenFetcherTest,
+ MultipleRequestsForDifferentAccountsCanceledAndFulfilled) {
+ TestTokenCallback callback;
+
+ base::RunLoop run_loop;
+ set_on_access_token_request_callback(run_loop.QuitClosure());
+
+ std::string account_id = AddAccount(kTestGaiaId, kTestEmail);
+ token_service()->UpdateCredentials(account_id, "refresh token");
+
+ // This should result in a request for an access token.
+ auto fetcher = CreateFetcher(account_id, callback.Get(),
+ AccessTokenFetcher::Mode::kImmediate);
+ run_loop.Run();
+
+ // Add a second account and request an access token for it.
+ std::string account_id2 = AddAccount(kTestGaiaId2, kTestEmail2);
+ token_service()->UpdateCredentials(account_id2, "refresh token");
+
+ base::RunLoop run_loop2;
+ set_on_access_token_request_callback(run_loop2.QuitClosure());
+
+ TestTokenCallback callback2;
+ auto fetcher2 = CreateFetcher(account_id2, callback2.Get(),
+ AccessTokenFetcher::Mode::kImmediate);
+ run_loop2.Run();
+
+ // Cancel the first access token request: This should result in a callback
+ // for the first fetcher.
+ base::RunLoop run_loop3;
+ EXPECT_CALL(
+ callback,
+ Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
+ AccessTokenInfo()))
+ .WillOnce(testing::InvokeWithoutArgs(&run_loop3, &base::RunLoop::Quit));
+
+ token_service()->IssueErrorForAllPendingRequestsForAccount(
+ account_id,
+ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
+
+ run_loop3.Run();
+
+ // Once the second access token request is fulfilled, it should get
+ // called back with the access token.
+ base::RunLoop run_loop4;
+ EXPECT_CALL(callback2,
+ Run(GoogleServiceAuthError::AuthErrorNone(), access_token_info()))
+ .WillOnce(testing::InvokeWithoutArgs(&run_loop4, &base::RunLoop::Quit));
+ token_service()->IssueAllTokensForAccount(
+ account_id2,
+ OAuth2AccessTokenConsumer::TokenResponse(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token));
+
+ run_loop4.Run();
+}
+
+TEST_F(AccessTokenFetcherTest, FetcherWithCustomURLLoaderFactory) {
+ base::RunLoop run_loop;
+ set_on_access_token_request_callback(run_loop.QuitClosure());
+
+ std::string account_id = AddAccount(kTestGaiaId, kTestEmail);
+ token_service()->UpdateCredentials(account_id, "refresh token");
+
+ network::TestURLLoaderFactory test_url_loader_factory;
+ scoped_refptr<network::SharedURLLoaderFactory> test_shared_url_loader_factory(
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ &test_url_loader_factory));
+
+ // This should result in a request for an access token.
+ TestTokenCallback callback;
+ auto fetcher = CreateFetcherWithURLLoaderFactory(
+ account_id, test_shared_url_loader_factory, callback.Get(),
+ AccessTokenFetcher::Mode::kImmediate);
+
+ run_loop.Run();
+
+ // The URLLoaderFactory present in the pending request should match
+ // the one we specified when creating the AccessTokenFetcher.
+ std::vector<FakeOAuth2AccessTokenManager::PendingRequest> pending_requests =
+ token_service()->GetPendingRequests();
+
+ EXPECT_EQ(pending_requests.size(), 1U);
+ EXPECT_EQ(pending_requests[0].url_loader_factory,
+ test_shared_url_loader_factory);
+
+ // Once the access token request is fulfilled, we should get called back
+ // with the access token.
+ EXPECT_CALL(callback, Run(GoogleServiceAuthError::AuthErrorNone(),
+ access_token_info()));
+
+ token_service()->IssueAllTokensForAccount(
+ account_id,
+ OAuth2AccessTokenConsumer::TokenResponse(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token));
+
+ // Now add a second account and request an access token for it to test
+ // that the default URLLoaderFactory is used if none is specified.
+ base::RunLoop run_loop2;
+ TestTokenCallback callback2;
+
+ set_on_access_token_request_callback(run_loop2.QuitClosure());
+ std::string account_id2 = AddAccount(kTestGaiaId2, kTestEmail2);
+ token_service()->UpdateCredentials(account_id2, "refresh token");
+
+ // CreateFetcher will create an AccessTokenFetcher without specifying
+ // any URLLoaderFactory, so that the default one will be used.
+ auto fetcher2 = CreateFetcher(account_id2, callback2.Get(),
+ AccessTokenFetcher::Mode::kImmediate);
+
+ run_loop2.Run();
+
+ // There should be one pending request in this case too.
+ std::vector<FakeOAuth2AccessTokenManager::PendingRequest> pending_requests2 =
+ token_service()->GetPendingRequests();
+ EXPECT_EQ(pending_requests2.size(), 1U);
+
+ // The URLLoaderFactory present in the pending request should match
+ // the one created by default for the token service's delegate.
+ ProfileOAuth2TokenServiceDelegate* service_delegate =
+ token_service()->GetDelegate();
+ EXPECT_EQ(pending_requests2[0].url_loader_factory,
+ service_delegate->GetURLLoaderFactory());
+
+ // Check that everything worked as expected in this case as well.
+ EXPECT_CALL(callback2, Run(GoogleServiceAuthError::AuthErrorNone(),
+ access_token_info()));
+ token_service()->IssueAllTokensForAccount(
+ account_id2,
+ OAuth2AccessTokenConsumer::TokenResponse(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token));
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/access_token_info.cc b/chromium/components/signin/public/identity_manager/access_token_info.cc
new file mode 100644
index 00000000000..8b377ad28b4
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/access_token_info.cc
@@ -0,0 +1,15 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/access_token_info.h"
+
+namespace signin {
+
+bool operator==(const AccessTokenInfo& lhs, const AccessTokenInfo& rhs) {
+ return (lhs.token == rhs.token) &&
+ (lhs.expiration_time == rhs.expiration_time) &&
+ (lhs.id_token == rhs.id_token);
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/access_token_info.h b/chromium/components/signin/public/identity_manager/access_token_info.h
new file mode 100644
index 00000000000..974a15fd97a
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/access_token_info.h
@@ -0,0 +1,42 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCESS_TOKEN_INFO_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCESS_TOKEN_INFO_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/time/time.h"
+
+namespace signin {
+
+// Container for a valid access token plus associated metadata.
+struct AccessTokenInfo {
+ // The access token itself.
+ std::string token;
+
+ // The time at which this access token will expire.
+ base::Time expiration_time;
+
+ // Contains extra information regarding the user's currently registered
+ // services. It is uncommon for consumers to need to interact with this field.
+ // To interact with it, first parse it via gaia::ParseServiceFlags().
+ std::string id_token;
+
+ AccessTokenInfo() = default;
+ AccessTokenInfo(const std::string& token_param,
+ const base::Time& expiration_time_param,
+ const std::string& id_token)
+ : token(token_param),
+ expiration_time(expiration_time_param),
+ id_token(id_token) {}
+};
+
+// Defined for testing purposes only.
+bool operator==(const AccessTokenInfo& lhs, const AccessTokenInfo& rhs);
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCESS_TOKEN_INFO_H_
diff --git a/chromium/components/signin/core/browser/account_info.cc b/chromium/components/signin/public/identity_manager/account_info.cc
index 3c164ea34ab..afe459f9f91 100644
--- a/chromium/components/signin/core/browser/account_info.cc
+++ b/chromium/components/signin/public/identity_manager/account_info.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/account_info.h"
+#include "components/signin/public/identity_manager/account_info.h"
#include "google_apis/gaia/gaia_auth_util.h"
namespace {
@@ -119,10 +119,3 @@ std::ostream& operator<<(std::ostream& os, const CoreAccountInfo& account) {
<< account.is_under_advanced_protection;
return os;
}
-
-AccountId AccountIdFromAccountInfo(const CoreAccountInfo& account_info) {
- if (account_info.email.empty() || account_info.gaia.empty())
- return EmptyAccountId();
-
- return AccountId::FromUserEmailGaiaId(account_info.email, account_info.gaia);
-}
diff --git a/chromium/components/signin/core/browser/account_info.h b/chromium/components/signin/public/identity_manager/account_info.h
index ca47ac7fd82..e8d5a61a74e 100644
--- a/chromium/components/signin/core/browser/account_info.h
+++ b/chromium/components/signin/public/identity_manager/account_info.h
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_INFO_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_INFO_H_
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNT_INFO_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNT_INFO_H_
#include <string>
-#include "components/account_id/account_id.h"
#include "google_apis/gaia/core_account_id.h"
#include "ui/gfx/image/image.h"
@@ -75,7 +74,4 @@ bool operator==(const CoreAccountInfo& l, const CoreAccountInfo& r);
bool operator!=(const CoreAccountInfo& l, const CoreAccountInfo& r);
std::ostream& operator<<(std::ostream& os, const CoreAccountInfo& account);
-// Returns AccountID populated from |account_info|.
-AccountId AccountIdFromAccountInfo(const CoreAccountInfo& account_info);
-
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_INFO_H_
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNT_INFO_H_
diff --git a/chromium/components/signin/core/browser/account_info_unittest.cc b/chromium/components/signin/public/identity_manager/account_info_unittest.cc
index 2329095b45a..b265a5d2ade 100644
--- a/chromium/components/signin/core/browser/account_info_unittest.cc
+++ b/chromium/components/signin/public/identity_manager/account_info_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/account_info.h"
+#include "components/signin/public/identity_manager/account_info.h"
#include "testing/gtest/include/gtest/gtest.h"
class AccountInfoTest : public testing::Test {};
diff --git a/chromium/components/signin/public/identity_manager/accounts_cookie_mutator.h b/chromium/components/signin/public/identity_manager/accounts_cookie_mutator.h
new file mode 100644
index 00000000000..af5dd83e6f7
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/accounts_cookie_mutator.h
@@ -0,0 +1,75 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNTS_COOKIE_MUTATOR_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNTS_COOKIE_MUTATOR_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
+
+struct CoreAccountId;
+class GoogleServiceAuthError;
+
+namespace signin {
+
+enum class SetAccountsInCookieResult;
+
+// AccountsCookieMutator is the interface to support merging known local Google
+// accounts into the cookie jar tracking the list of logged-in Google sessions.
+class AccountsCookieMutator {
+ public:
+ AccountsCookieMutator() = default;
+ virtual ~AccountsCookieMutator() = default;
+
+ typedef base::OnceCallback<void(const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error)>
+ AddAccountToCookieCompletedCallback;
+
+ // Adds an account identified by |account_id| to the cookie responsible for
+ // tracking the list of logged-in Google sessions across the web.
+ virtual void AddAccountToCookie(
+ const CoreAccountId& account_id,
+ gaia::GaiaSource source,
+ AddAccountToCookieCompletedCallback completion_callback) = 0;
+
+ // Adds an account identified by |account_id| and with |access_token| to the
+ // cookie responsible for tracking the list of logged-in Google sessions
+ // across the web.
+ virtual void AddAccountToCookieWithToken(
+ const CoreAccountId& account_id,
+ const std::string& access_token,
+ gaia::GaiaSource source,
+ AddAccountToCookieCompletedCallback completion_callback) = 0;
+
+ // Updates the state of the Gaia cookie to contain |account_ids|, including
+ // removal of any accounts that are currently present in the cookie but not
+ // contained in |account_ids|. |set_accounts_in_cookies_completed_callback|
+ // will be invoked with the result of the operation: if the error is equal to
+ // GoogleServiceAuthError::AuthErrorNone() then the operation succeeded.
+ // Notably, if there are accounts being added for which IdentityManager does
+ // not have refresh tokens, the operation will fail with a
+ // GoogleServiceAuthError::USER_NOT_SIGNED_UP error.
+ virtual void SetAccountsInCookie(
+ const std::vector<CoreAccountId>& account_ids,
+ gaia::GaiaSource source,
+ base::OnceCallback<void(SetAccountsInCookieResult)>
+ set_accounts_in_cookies_completed_callback) = 0;
+
+ // Triggers a ListAccounts fetch. Can be used in circumstances where clients
+ // know that the contents of the Gaia cookie might have changed.
+ virtual void TriggerCookieJarUpdate() = 0;
+
+ // Remove all accounts from the Gaia cookie.
+ virtual void LogOutAllAccounts(gaia::GaiaSource source) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AccountsCookieMutator);
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNTS_COOKIE_MUTATOR_H_
diff --git a/chromium/components/signin/public/identity_manager/accounts_cookie_mutator_unittest.cc b/chromium/components/signin/public/identity_manager/accounts_cookie_mutator_unittest.cc
new file mode 100644
index 00000000000..add100d356e
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/accounts_cookie_mutator_unittest.cc
@@ -0,0 +1,422 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/accounts_cookie_mutator.h"
+
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/gtest_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/signin/public/base/list_accounts_test_utils.h"
+#include "components/signin/public/base/test_signin_client.h"
+#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h"
+#include "components/signin/public/identity_manager/test_identity_manager_observer.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char kTestUnavailableAccountId[] = "unavailable_account_id";
+const char kTestOtherUnavailableAccountId[] = "other_unavailable_account_id";
+const char kTestAccountEmail[] = "test_user@test.com";
+const char kTestOtherAccountEmail[] = "test_other_user@test.com";
+const char kTestAccountGaiaId[] = "gaia_id_for_test_user_test.com";
+const char kTestAccessToken[] = "access_token";
+const char kTestUberToken[] = "test_uber_token";
+const char kTestOAuthMultiLoginResponse[] = R"(
+ { "status": "OK",
+ "cookies":[
+ {
+ "name":"CookieName",
+ "value":"CookieValue",
+ "domain":".google.com",
+ "path":"/"
+ }
+ ]
+ })";
+
+enum class AccountsCookiesMutatorAction {
+ kAddAccountToCookie,
+ kSetAccountsInCookie,
+ kTriggerCookieJarUpdateNoAccounts,
+ kTriggerCookieJarUpdateOneAccount,
+};
+
+} // namespace
+
+namespace signin {
+class AccountsCookieMutatorTest : public testing::Test {
+ public:
+ AccountsCookieMutatorTest()
+ : test_signin_client_(&prefs_),
+ identity_test_env_(/*test_url_loader_factory=*/nullptr,
+ &prefs_,
+ AccountConsistencyMethod::kDisabled,
+ &test_signin_client_) {}
+
+ ~AccountsCookieMutatorTest() override {}
+
+ // Make an account available and returns the account ID.
+ std::string AddAcountWithRefreshToken(const std::string& email) {
+ return identity_test_env_.MakeAccountAvailable(email).account_id;
+ }
+
+ // Feed the TestURLLoaderFactory with the responses for the requests that will
+ // be created by UberTokenFetcher when mergin accounts into the cookie jar.
+ void PrepareURLLoaderResponsesForAction(AccountsCookiesMutatorAction action) {
+ switch (action) {
+ case AccountsCookiesMutatorAction::kAddAccountToCookie:
+ GetTestURLLoaderFactory()->AddResponse(
+ GaiaUrls::GetInstance()
+ ->oauth1_login_url()
+ .Resolve(base::StringPrintf("?source=%s&issueuberauth=1",
+ GaiaConstants::kChromeSource))
+ .spec(),
+ kTestUberToken, net::HTTP_OK);
+
+ GetTestURLLoaderFactory()->AddResponse(
+ GaiaUrls::GetInstance()
+ ->GetCheckConnectionInfoURLWithSource(
+ GaiaConstants::kChromeSource)
+ .spec(),
+ std::string(), net::HTTP_OK);
+
+ GetTestURLLoaderFactory()->AddResponse(
+ GaiaUrls::GetInstance()
+ ->merge_session_url()
+ .Resolve(base::StringPrintf(
+ "?uberauth=%s&continue=http://www.google.com&source=%s",
+ kTestUberToken, GaiaConstants::kChromeSource))
+ .spec(),
+ std::string(), net::HTTP_OK);
+ break;
+ case AccountsCookiesMutatorAction::kSetAccountsInCookie:
+ GetTestURLLoaderFactory()->AddResponse(
+ GaiaUrls::GetInstance()
+ ->oauth_multilogin_url()
+ .Resolve(base::StringPrintf("?source=%s",
+ GaiaConstants::kChromeSource))
+ .spec(),
+ std::string(kTestOAuthMultiLoginResponse), net::HTTP_OK);
+ break;
+ case AccountsCookiesMutatorAction::kTriggerCookieJarUpdateNoAccounts:
+ SetListAccountsResponseNoAccounts(GetTestURLLoaderFactory());
+ break;
+ case AccountsCookiesMutatorAction::kTriggerCookieJarUpdateOneAccount:
+ SetListAccountsResponseOneAccount(kTestAccountEmail, kTestAccountGaiaId,
+ GetTestURLLoaderFactory());
+ break;
+ }
+ }
+
+ IdentityTestEnvironment* identity_test_env() { return &identity_test_env_; }
+
+ TestIdentityManagerObserver* identity_manager_observer() {
+ return identity_test_env_.identity_manager_observer();
+ }
+
+ AccountsCookieMutator* accounts_cookie_mutator() {
+ return identity_test_env_.identity_manager()->GetAccountsCookieMutator();
+ }
+
+ network::TestURLLoaderFactory* GetTestURLLoaderFactory() {
+ return test_signin_client_.GetTestURLLoaderFactory();
+ }
+
+ private:
+ base::test::ScopedTaskEnvironment task_environment_;
+ sync_preferences::TestingPrefServiceSyncable prefs_;
+ TestSigninClient test_signin_client_;
+ IdentityTestEnvironment identity_test_env_;
+
+ DISALLOW_COPY_AND_ASSIGN(AccountsCookieMutatorTest);
+};
+
+// Test that adding a non existing account without providing an access token
+// results in an error due to such account not being available.
+TEST_F(AccountsCookieMutatorTest, AddAccountToCookie_NonExistingAccount) {
+ base::RunLoop run_loop;
+ std::string account_id_from_add_account_to_cookie_completed_callback;
+ GoogleServiceAuthError error_from_add_account_to_cookie_completed_callback;
+ auto completion_callback =
+ base::BindLambdaForTesting([&](const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error) {
+ account_id_from_add_account_to_cookie_completed_callback = account_id;
+ error_from_add_account_to_cookie_completed_callback = error;
+ run_loop.Quit();
+ });
+
+ accounts_cookie_mutator()->AddAccountToCookie(kTestUnavailableAccountId,
+ gaia::GaiaSource::kChrome,
+ std::move(completion_callback));
+ run_loop.Run();
+
+ EXPECT_EQ(account_id_from_add_account_to_cookie_completed_callback,
+ kTestUnavailableAccountId);
+ EXPECT_EQ(error_from_add_account_to_cookie_completed_callback.state(),
+ GoogleServiceAuthError::USER_NOT_SIGNED_UP);
+}
+
+// Test that adding an already available account without providing an access
+// token results in such account being successfully merged into the cookie jar.
+TEST_F(AccountsCookieMutatorTest, AddAccountToCookie_ExistingAccount) {
+ PrepareURLLoaderResponsesForAction(
+ AccountsCookiesMutatorAction::kAddAccountToCookie);
+ // Adding an account with refresh token will trigger a cookie jar update.
+ PrepareURLLoaderResponsesForAction(
+ AccountsCookiesMutatorAction::kTriggerCookieJarUpdateNoAccounts);
+
+ std::string account_id = AddAcountWithRefreshToken(kTestAccountEmail);
+ base::RunLoop run_loop;
+ std::string account_id_from_add_account_to_cookie_completed_callback;
+ GoogleServiceAuthError error_from_add_account_to_cookie_completed_callback;
+ auto completion_callback =
+ base::BindLambdaForTesting([&](const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error) {
+ account_id_from_add_account_to_cookie_completed_callback = account_id;
+ error_from_add_account_to_cookie_completed_callback = error;
+ run_loop.Quit();
+ });
+
+ accounts_cookie_mutator()->AddAccountToCookie(
+ account_id, gaia::GaiaSource::kChrome, std::move(completion_callback));
+
+ identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ account_id, kTestAccessToken,
+ base::Time::Now() + base::TimeDelta::FromHours(1));
+ run_loop.Run();
+
+ EXPECT_EQ(account_id_from_add_account_to_cookie_completed_callback,
+ account_id);
+ EXPECT_EQ(error_from_add_account_to_cookie_completed_callback.state(),
+ GoogleServiceAuthError::NONE);
+}
+
+// Test that adding a non existing account along with an access token, results
+// on such account being successfully merged into the cookie jar.
+TEST_F(AccountsCookieMutatorTest,
+ AddAccountToCookieWithAccessToken_NonExistingAccount) {
+ PrepareURLLoaderResponsesForAction(
+ AccountsCookiesMutatorAction::kAddAccountToCookie);
+
+ base::RunLoop run_loop;
+ std::string account_id_from_add_account_to_cookie_completed_callback;
+ GoogleServiceAuthError error_from_add_account_to_cookie_completed_callback;
+ auto completion_callback =
+ base::BindLambdaForTesting([&](const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error) {
+ account_id_from_add_account_to_cookie_completed_callback = account_id;
+ error_from_add_account_to_cookie_completed_callback = error;
+ run_loop.Quit();
+ });
+
+ accounts_cookie_mutator()->AddAccountToCookieWithToken(
+ kTestUnavailableAccountId, kTestAccessToken, gaia::GaiaSource::kChrome,
+ std::move(completion_callback));
+ run_loop.Run();
+
+ EXPECT_EQ(account_id_from_add_account_to_cookie_completed_callback,
+ kTestUnavailableAccountId);
+ EXPECT_EQ(error_from_add_account_to_cookie_completed_callback.state(),
+ GoogleServiceAuthError::NONE);
+}
+
+// Test that adding an already available account along with an access token,
+// results in such account being successfully merged into the cookie jar.
+TEST_F(AccountsCookieMutatorTest,
+ AddAccountToCookieWithAccessToken_ExistingAccount) {
+ PrepareURLLoaderResponsesForAction(
+ AccountsCookiesMutatorAction::kAddAccountToCookie);
+ // Adding an account with refresh token will trigger a cookie jar update.
+ PrepareURLLoaderResponsesForAction(
+ AccountsCookiesMutatorAction::kTriggerCookieJarUpdateNoAccounts);
+
+ std::string account_id = AddAcountWithRefreshToken(kTestAccountEmail);
+ base::RunLoop run_loop;
+ std::string account_id_from_add_account_to_cookie_completed_callback;
+ GoogleServiceAuthError error_from_add_account_to_cookie_completed_callback;
+ auto completion_callback =
+ base::BindLambdaForTesting([&](const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error) {
+ account_id_from_add_account_to_cookie_completed_callback = account_id;
+ error_from_add_account_to_cookie_completed_callback = error;
+ run_loop.Quit();
+ });
+
+ accounts_cookie_mutator()->AddAccountToCookieWithToken(
+ account_id, kTestAccessToken, gaia::GaiaSource::kChrome,
+ std::move(completion_callback));
+
+ run_loop.Run();
+
+ EXPECT_EQ(account_id_from_add_account_to_cookie_completed_callback,
+ account_id);
+ EXPECT_EQ(error_from_add_account_to_cookie_completed_callback.state(),
+ GoogleServiceAuthError::NONE);
+}
+
+// Test that trying to set a list of accounts in the cookie jar where none of
+// those accounts have refresh tokens in IdentityManager results in an error.
+TEST_F(AccountsCookieMutatorTest, SetAccountsInCookie_AllNonExistingAccounts) {
+ PrepareURLLoaderResponsesForAction(
+ AccountsCookiesMutatorAction::kSetAccountsInCookie);
+
+ base::RunLoop run_loop;
+ std::vector<CoreAccountId> accounts_ids = {kTestUnavailableAccountId,
+ kTestOtherUnavailableAccountId};
+ accounts_cookie_mutator()->SetAccountsInCookie(
+ accounts_ids, gaia::GaiaSource::kChrome,
+ base::BindOnce(
+ [](base::OnceClosure quit_closure, SetAccountsInCookieResult result) {
+ EXPECT_EQ(result, SetAccountsInCookieResult::kPersistentError);
+ std::move(quit_closure).Run();
+ },
+ run_loop.QuitClosure()));
+
+ run_loop.Run();
+}
+
+// Test that trying to set a list of accounts in the cookie jar where some of
+// those accounts have no refresh tokens in IdentityManager results in an error.
+TEST_F(AccountsCookieMutatorTest, SetAccountsInCookie_SomeNonExistingAccounts) {
+ PrepareURLLoaderResponsesForAction(
+ AccountsCookiesMutatorAction::kSetAccountsInCookie);
+ // Adding an account with refresh token will trigger a cookie jar update.
+ PrepareURLLoaderResponsesForAction(
+ AccountsCookiesMutatorAction::kTriggerCookieJarUpdateNoAccounts);
+
+ std::string account_id = AddAcountWithRefreshToken(kTestAccountEmail);
+ base::RunLoop run_loop;
+ std::vector<CoreAccountId> accounts_ids = {account_id,
+ kTestUnavailableAccountId};
+ accounts_cookie_mutator()->SetAccountsInCookie(
+ accounts_ids, gaia::GaiaSource::kChrome,
+ base::BindOnce(
+ [](base::OnceClosure quit_closure, SetAccountsInCookieResult result) {
+ EXPECT_EQ(result, SetAccountsInCookieResult::kPersistentError);
+ std::move(quit_closure).Run();
+ },
+ run_loop.QuitClosure()));
+ run_loop.Run();
+}
+
+// Test that trying to set a list of accounts in the cookie jar where all of
+// those accounts have refresh tokens in IdentityManager results in them being
+// successfully set.
+TEST_F(AccountsCookieMutatorTest, SetAccountsInCookie_AllExistingAccounts) {
+ PrepareURLLoaderResponsesForAction(
+ AccountsCookiesMutatorAction::kSetAccountsInCookie);
+ // Adding an account with refresh token will trigger a cookie jar update.
+ PrepareURLLoaderResponsesForAction(
+ AccountsCookiesMutatorAction::kTriggerCookieJarUpdateNoAccounts);
+
+ std::string account_id = AddAcountWithRefreshToken(kTestAccountEmail);
+ std::string other_account_id =
+ AddAcountWithRefreshToken(kTestOtherAccountEmail);
+ base::RunLoop run_loop;
+ std::vector<CoreAccountId> accounts_ids = {account_id, other_account_id};
+ accounts_cookie_mutator()->SetAccountsInCookie(
+ accounts_ids, gaia::GaiaSource::kChrome,
+ base::BindOnce(
+ [](base::OnceClosure quit_closure, SetAccountsInCookieResult result) {
+ EXPECT_EQ(result, SetAccountsInCookieResult::kSuccess);
+ std::move(quit_closure).Run();
+ },
+ run_loop.QuitClosure()));
+
+ identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ account_id, kTestAccessToken,
+ base::Time::Now() + base::TimeDelta::FromHours(1));
+ identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ other_account_id, kTestAccessToken,
+ base::Time::Now() + base::TimeDelta::FromHours(1));
+
+ run_loop.Run();
+}
+
+// Test triggering the update of a cookie jar with no accounts works.
+TEST_F(AccountsCookieMutatorTest, TriggerCookieJarUpdate_NoListedAccounts) {
+ PrepareURLLoaderResponsesForAction(
+ AccountsCookiesMutatorAction::kTriggerCookieJarUpdateNoAccounts);
+
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnAccountsInCookieUpdatedCallback(
+ run_loop.QuitClosure());
+ accounts_cookie_mutator()->TriggerCookieJarUpdate();
+ run_loop.Run();
+
+ const AccountsInCookieJarInfo& accounts_in_jar_info =
+ identity_manager_observer()
+ ->AccountsInfoFromAccountsInCookieUpdatedCallback();
+ EXPECT_EQ(accounts_in_jar_info.signed_in_accounts.size(), 0U);
+ EXPECT_EQ(accounts_in_jar_info.signed_out_accounts.size(), 0U);
+ EXPECT_TRUE(accounts_in_jar_info.accounts_are_fresh);
+
+ EXPECT_EQ(identity_manager_observer()
+ ->ErrorFromAccountsInCookieUpdatedCallback()
+ .state(),
+ GoogleServiceAuthError::NONE);
+}
+
+// Test triggering the update of a cookie jar with one accounts works and that
+// the received accounts match the data injected via the TestURLLoaderFactory.
+TEST_F(AccountsCookieMutatorTest, TriggerCookieJarUpdate_OneListedAccounts) {
+ PrepareURLLoaderResponsesForAction(
+ AccountsCookiesMutatorAction::kTriggerCookieJarUpdateOneAccount);
+
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnAccountsInCookieUpdatedCallback(
+ run_loop.QuitClosure());
+ accounts_cookie_mutator()->TriggerCookieJarUpdate();
+ run_loop.Run();
+
+ const AccountsInCookieJarInfo& accounts_in_jar_info =
+ identity_manager_observer()
+ ->AccountsInfoFromAccountsInCookieUpdatedCallback();
+ EXPECT_EQ(accounts_in_jar_info.signed_in_accounts.size(), 1U);
+ EXPECT_EQ(accounts_in_jar_info.signed_in_accounts[0].gaia_id,
+ kTestAccountGaiaId);
+ EXPECT_EQ(accounts_in_jar_info.signed_in_accounts[0].email,
+ kTestAccountEmail);
+
+ EXPECT_EQ(accounts_in_jar_info.signed_out_accounts.size(), 0U);
+ EXPECT_TRUE(accounts_in_jar_info.accounts_are_fresh);
+
+ EXPECT_EQ(identity_manager_observer()
+ ->ErrorFromAccountsInCookieUpdatedCallback()
+ .state(),
+ GoogleServiceAuthError::NONE);
+}
+
+// Test that trying to log out all sessions generates the right network request.
+TEST_F(AccountsCookieMutatorTest, LogOutAllAccounts) {
+ base::RunLoop run_loop;
+ GetTestURLLoaderFactory()->SetInterceptor(base::BindRepeating(
+ [](base::OnceClosure quit_closure,
+ const network::ResourceRequest& request) {
+ EXPECT_EQ(request.url.spec(),
+ GaiaUrls::GetInstance()
+ ->LogOutURLWithSource(GaiaConstants::kChromeSource)
+ .spec());
+ std::move(quit_closure).Run();
+ },
+ run_loop.QuitClosure()));
+
+ accounts_cookie_mutator()->LogOutAllAccounts(gaia::GaiaSource::kChrome);
+ run_loop.Run();
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/accounts_in_cookie_jar_info.cc b/chromium/components/signin/public/identity_manager/accounts_in_cookie_jar_info.cc
new file mode 100644
index 00000000000..840c204c5da
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/accounts_in_cookie_jar_info.cc
@@ -0,0 +1,30 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
+
+namespace signin {
+
+AccountsInCookieJarInfo::AccountsInCookieJarInfo() = default;
+
+AccountsInCookieJarInfo::AccountsInCookieJarInfo(
+ bool accounts_are_fresh_param,
+ const std::vector<gaia::ListedAccount>& signed_in_accounts_param,
+ const std::vector<gaia::ListedAccount>& signed_out_accounts_param)
+ : accounts_are_fresh(accounts_are_fresh_param),
+ signed_in_accounts(signed_in_accounts_param),
+ signed_out_accounts(signed_out_accounts_param) {}
+
+AccountsInCookieJarInfo::AccountsInCookieJarInfo(
+ const AccountsInCookieJarInfo& other) {
+ if (this == &other)
+ return;
+ accounts_are_fresh = other.accounts_are_fresh;
+ signed_in_accounts = other.signed_in_accounts;
+ signed_out_accounts = other.signed_out_accounts;
+}
+
+AccountsInCookieJarInfo::~AccountsInCookieJarInfo() = default;
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/accounts_in_cookie_jar_info.h b/chromium/components/signin/public/identity_manager/accounts_in_cookie_jar_info.h
new file mode 100644
index 00000000000..1b54539d1b7
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/accounts_in_cookie_jar_info.h
@@ -0,0 +1,37 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNTS_IN_COOKIE_JAR_INFO_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNTS_IN_COOKIE_JAR_INFO_H_
+
+#include <vector>
+
+#include "google_apis/gaia/gaia_auth_util.h"
+
+namespace signin {
+
+// Container for a response to get the accounts in the cookie jar.
+struct AccountsInCookieJarInfo {
+ // True if the accounts info from cookie is fresh and does not need to be
+ // updated.
+ bool accounts_are_fresh;
+
+ // The current list of signed in accounts from the cookie jar.
+ std::vector<gaia::ListedAccount> signed_in_accounts;
+
+ // The current list of signed out accounts from the cookie jar.
+ std::vector<gaia::ListedAccount> signed_out_accounts;
+
+ AccountsInCookieJarInfo();
+ AccountsInCookieJarInfo(
+ bool accounts_are_fresh_param,
+ const std::vector<gaia::ListedAccount>& signed_in_accounts_param,
+ const std::vector<gaia::ListedAccount>& signed_out_accounts_param);
+ AccountsInCookieJarInfo(const AccountsInCookieJarInfo& other);
+ ~AccountsInCookieJarInfo();
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNTS_IN_COOKIE_JAR_INFO_H_
diff --git a/chromium/components/signin/public/identity_manager/accounts_mutator.h b/chromium/components/signin/public/identity_manager/accounts_mutator.h
new file mode 100644
index 00000000000..eb55698778a
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/accounts_mutator.h
@@ -0,0 +1,82 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNTS_MUTATOR_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNTS_MUTATOR_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "components/signin/public/base/signin_buildflags.h"
+
+namespace signin_metrics {
+enum class SourceForRefreshTokenOperation;
+}
+
+struct CoreAccountId;
+
+namespace signin {
+
+// AccountsMutator is the interface to support seeding of account info and
+// mutation of refresh tokens for the user's Gaia accounts.
+class AccountsMutator {
+ public:
+ AccountsMutator() = default;
+ virtual ~AccountsMutator() = default;
+
+ // Updates the information of the account associated with |gaia_id|, first
+ // adding that account to the system if it is not known.
+ virtual CoreAccountId AddOrUpdateAccount(
+ const std::string& gaia_id,
+ const std::string& email,
+ const std::string& refresh_token,
+ bool is_under_advanced_protection,
+ signin_metrics::SourceForRefreshTokenOperation source) = 0;
+
+ // Updates the information about account identified by |account_id|.
+ virtual void UpdateAccountInfo(
+ const CoreAccountId& account_id,
+ base::Optional<bool> is_child_account,
+ base::Optional<bool> is_under_advanced_protection) = 0;
+
+ // Removes the account given by |account_id|. Also revokes the token
+ // server-side if needed.
+ virtual void RemoveAccount(
+ const CoreAccountId& account_id,
+ signin_metrics::SourceForRefreshTokenOperation source) = 0;
+
+ // Removes all accounts.
+ virtual void RemoveAllAccounts(
+ signin_metrics::SourceForRefreshTokenOperation source) = 0;
+
+ // Invalidates the refresh token of the primary account.
+ // The primary account must necessarily be set by the time this method
+ // is invoked.
+ virtual void InvalidateRefreshTokenForPrimaryAccount(
+ signin_metrics::SourceForRefreshTokenOperation source) = 0;
+
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+ // Removes the credentials associated to account_id from the internal storage,
+ // and moves them to |target|. The credentials are not revoked on the server,
+ // but the IdentityManager::Observer::OnRefreshTokenRemovedForAccount()
+ // notification is sent to the observers. Also recreates a new device ID for
+ // this mutator. The device ID of the current mutator is not moved to the
+ // target mutator.
+ virtual void MoveAccount(AccountsMutator* target,
+ const CoreAccountId& account_id) = 0;
+#endif
+
+ // Updates the refresh token for the supervised user.
+ // TODO(860492): Remove this once supervised user support is removed.
+ virtual void LegacySetRefreshTokenForSupervisedUser(
+ const std::string& refresh_token) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AccountsMutator);
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNTS_MUTATOR_H_
diff --git a/chromium/components/signin/public/identity_manager/accounts_mutator_unittest.cc b/chromium/components/signin/public/identity_manager/accounts_mutator_unittest.cc
new file mode 100644
index 00000000000..98669f6dc8c
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/accounts_mutator_unittest.cc
@@ -0,0 +1,683 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/internal/identity_manager/accounts_mutator_impl.h"
+
+#include "base/bind.h"
+#include "base/optional.h"
+#include "base/test/gtest_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/signin/public/base/device_id_helper.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "components/signin/public/identity_manager/identity_test_utils.h"
+#include "components/signin/public/identity_manager/test_identity_manager_observer.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char kTestGaiaId[] = "gaia-id-test_user@test.com";
+const char kTestGaiaId2[] = "gaia-id-test_user-2@test.com";
+const char kTestEmail[] = "test_user@test.com";
+const char kTestEmail2[] = "test_user@test-2.com";
+const char kRefreshToken[] = "refresh_token";
+const char kRefreshToken2[] = "refresh_token_2";
+const char kSupervisedUserPseudoEmail[] = "managed_user@localhost";
+
+// Class that observes diagnostics updates from signin::IdentityManager.
+class TestIdentityManagerDiagnosticsObserver
+ : public signin::IdentityManager::DiagnosticsObserver {
+ public:
+ explicit TestIdentityManagerDiagnosticsObserver(
+ signin::IdentityManager* identity_manager)
+ : identity_manager_(identity_manager) {
+ identity_manager_->AddDiagnosticsObserver(this);
+ }
+ ~TestIdentityManagerDiagnosticsObserver() override {
+ identity_manager_->RemoveDiagnosticsObserver(this);
+ }
+
+ const std::string& token_updator_account_id() {
+ return token_updator_account_id_;
+ }
+ const std::string& token_updator_source() { return token_updator_source_; }
+ bool is_token_updator_refresh_token_valid() {
+ return is_token_updator_refresh_token_valid_;
+ }
+ const std::string& token_remover_account_id() {
+ return token_remover_account_id_;
+ }
+ const std::string& token_remover_source() { return token_remover_source_; }
+
+ private:
+ // signin::IdentityManager::DiagnosticsObserver:
+ void OnRefreshTokenUpdatedForAccountFromSource(
+ const CoreAccountId& account_id,
+ bool is_refresh_token_valid,
+ const std::string& source) override {
+ token_updator_account_id_ = account_id;
+ is_token_updator_refresh_token_valid_ = is_refresh_token_valid;
+ token_updator_source_ = source;
+ }
+
+ void OnRefreshTokenRemovedForAccountFromSource(
+ const CoreAccountId& account_id,
+ const std::string& source) override {
+ token_remover_account_id_ = account_id;
+ token_remover_source_ = source;
+ }
+
+ signin::IdentityManager* identity_manager_;
+ std::string token_updator_account_id_;
+ std::string token_updator_source_;
+ std::string token_remover_account_id_;
+ std::string token_remover_source_;
+ bool is_token_updator_refresh_token_valid_;
+};
+
+} // namespace
+
+namespace signin {
+class AccountsMutatorTest : public testing::Test {
+ public:
+ AccountsMutatorTest()
+ : identity_test_env_(&test_url_loader_factory_, &prefs_),
+ identity_manager_diagnostics_observer_(identity_manager()) {}
+
+ ~AccountsMutatorTest() override {}
+
+ PrefService* pref_service() { return &prefs_; }
+
+ IdentityManager* identity_manager() {
+ return identity_test_env_.identity_manager();
+ }
+
+ TestIdentityManagerObserver* identity_manager_observer() {
+ return identity_test_env_.identity_manager_observer();
+ }
+
+ TestIdentityManagerDiagnosticsObserver*
+ identity_manager_diagnostics_observer() {
+ return &identity_manager_diagnostics_observer_;
+ }
+
+ AccountsMutator* accounts_mutator() {
+ return identity_manager()->GetAccountsMutator();
+ }
+
+ private:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ sync_preferences::TestingPrefServiceSyncable prefs_;
+ network::TestURLLoaderFactory test_url_loader_factory_;
+ IdentityTestEnvironment identity_test_env_;
+ TestIdentityManagerDiagnosticsObserver identity_manager_diagnostics_observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(AccountsMutatorTest);
+};
+
+TEST_F(AccountsMutatorTest, Basic) {
+ // Should not crash.
+}
+
+// Test that a new account gets added to the AccountTrackerService when calling
+// AddOrUpdateAccount() and that a new refresh token becomes available for the
+// passed account_id when adding an account for the first time.
+TEST_F(AccountsMutatorTest, AddOrUpdateAccount_AddNewAccount) {
+ // Abort the test if the current platform does not support accounts mutation.
+ if (!accounts_mutator())
+ return;
+
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnRefreshTokenUpdatedCallback(
+ run_loop.QuitClosure());
+
+ std::string account_id = accounts_mutator()->AddOrUpdateAccount(
+ kTestGaiaId, kTestEmail, kRefreshToken,
+ /*is_under_advanced_protection=*/false,
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+ run_loop.Run();
+
+ EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_id));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ account_id));
+
+ AccountInfo account_info =
+ identity_manager()
+ ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ .value();
+ EXPECT_EQ(account_info.account_id, account_id);
+ EXPECT_EQ(account_info.email, kTestEmail);
+ EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 1U);
+}
+
+// Test that no account gets added to the AccountTrackerService when calling
+// AddOrUpdateAccount() if there's an account already tracked for a given id,
+// and that its refresh token gets updated if a different one is passed.
+TEST_F(AccountsMutatorTest, AddOrUpdateAccount_UpdateExistingAccount) {
+ // Abort the test if the current platform does not support accounts mutation.
+ if (!accounts_mutator())
+ return;
+
+ // First of all add the account to the account tracker service.
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnRefreshTokenUpdatedCallback(
+ run_loop.QuitClosure());
+
+ std::string account_id = accounts_mutator()->AddOrUpdateAccount(
+ kTestGaiaId, kTestEmail, kRefreshToken,
+ /*is_under_advanced_protection=*/false,
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+ run_loop.Run();
+
+ EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_id));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ account_id));
+ AccountInfo account_info =
+ identity_manager()
+ ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ .value();
+ EXPECT_EQ(account_info.account_id, account_id);
+ EXPECT_EQ(account_info.email, kTestEmail);
+ EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 1U);
+
+ // Now try adding the account again with the same account id but with
+ // different information, and check that the account gets updated.
+ base::RunLoop run_loop2;
+ identity_manager_observer()->SetOnRefreshTokenUpdatedCallback(
+ run_loop2.QuitClosure());
+
+ // The internals of IdentityService is migrating from email to gaia id
+ // as the account id. Detect whether the current plaform has completed
+ // the migration.
+ const bool use_gaia_as_account_id = account_id == account_info.gaia;
+
+ // If the system uses gaia id as account_id, then change the email and
+ // the |is_under_advanced_protection| field. Otherwise only change the
+ // latter. In all case, no new account should be created.
+ const char* const maybe_updated_email =
+ use_gaia_as_account_id ? kTestEmail2 : kTestEmail;
+
+ accounts_mutator()->AddOrUpdateAccount(
+ kTestGaiaId, maybe_updated_email, kRefreshToken,
+ /*is_under_advanced_protection=*/true,
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+ run_loop2.Run();
+
+ EXPECT_EQ(identity_manager_observer()
+ ->AccountFromRefreshTokenUpdatedCallback()
+ .account_id,
+ account_id);
+
+ // No new accounts should be created, just the information should be updated.
+ EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 1U);
+ AccountInfo updated_account_info =
+ identity_manager()
+ ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ .value();
+ EXPECT_EQ(account_info.account_id, updated_account_info.account_id);
+ EXPECT_EQ(account_info.gaia, updated_account_info.gaia);
+ EXPECT_EQ(updated_account_info.email, maybe_updated_email);
+ if (use_gaia_as_account_id) {
+ EXPECT_NE(updated_account_info.email, account_info.email);
+ EXPECT_EQ(updated_account_info.email, kTestEmail2);
+ }
+ EXPECT_NE(account_info.is_under_advanced_protection,
+ updated_account_info.is_under_advanced_protection);
+}
+
+// Test that the information of an existing account for a given ID gets updated.
+TEST_F(AccountsMutatorTest, UpdateAccountInfo) {
+ // Abort the test if the current platform does not support accounts mutation.
+ if (!accounts_mutator())
+ return;
+
+ // First of all add the account to the account tracker service.
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnRefreshTokenUpdatedCallback(
+ run_loop.QuitClosure());
+
+ std::string account_id = accounts_mutator()->AddOrUpdateAccount(
+ kTestGaiaId, kTestEmail, kRefreshToken,
+ /*is_under_advanced_protection=*/false,
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+ run_loop.Run();
+
+ EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 1U);
+
+ AccountInfo original_account_info =
+ identity_manager()
+ ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ .value();
+ EXPECT_EQ(original_account_info.account_id, account_id);
+ EXPECT_EQ(original_account_info.email, kTestEmail);
+ EXPECT_FALSE(original_account_info.is_child_account);
+ EXPECT_FALSE(original_account_info.is_under_advanced_protection);
+
+ accounts_mutator()->UpdateAccountInfo(
+ account_id,
+ /*is_child_account=*/true,
+ /*is_under_advanced_protection=*/base::nullopt);
+ AccountInfo updated_account_info_1 =
+ identity_manager()
+ ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ .value();
+
+ // Only |is_child_account| changed so far, everything else remains the same.
+ EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 1U);
+ EXPECT_EQ(updated_account_info_1.account_id,
+ original_account_info.account_id);
+ EXPECT_EQ(updated_account_info_1.email, original_account_info.email);
+ EXPECT_NE(updated_account_info_1.is_child_account,
+ original_account_info.is_child_account);
+ EXPECT_EQ(updated_account_info_1.is_under_advanced_protection,
+ original_account_info.is_under_advanced_protection);
+
+ accounts_mutator()->UpdateAccountInfo(account_id,
+ /*is_child_account=*/base::nullopt,
+ /*is_under_advanced_protection=*/true);
+ AccountInfo updated_account_info_2 =
+ identity_manager()
+ ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ .value();
+
+ // |is_under_advanced_protection| has changed now, but |is_child_account|
+ // remains the same since we previously set it to |true| in the previous step.
+ EXPECT_NE(updated_account_info_2.is_under_advanced_protection,
+ original_account_info.is_under_advanced_protection);
+ EXPECT_EQ(updated_account_info_2.is_child_account,
+ updated_account_info_1.is_child_account);
+
+ // Last, reset |is_child_account| and |is_under_advanced_protection| together
+ // to its initial |false| value, which is no longer the case.
+ EXPECT_TRUE(updated_account_info_2.is_child_account);
+ EXPECT_TRUE(updated_account_info_2.is_under_advanced_protection);
+
+ accounts_mutator()->UpdateAccountInfo(account_id,
+ /*is_child_account=*/false,
+ /*is_under_advanced_protection=*/false);
+ AccountInfo reset_account_info =
+ identity_manager()
+ ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ .value();
+
+ // Everything is back to its original state now.
+ EXPECT_EQ(reset_account_info.is_child_account,
+ original_account_info.is_child_account);
+ EXPECT_EQ(reset_account_info.is_under_advanced_protection,
+ original_account_info.is_under_advanced_protection);
+ EXPECT_FALSE(reset_account_info.is_child_account);
+ EXPECT_FALSE(reset_account_info.is_under_advanced_protection);
+}
+
+TEST_F(AccountsMutatorTest,
+ InvalidateRefreshTokenForPrimaryAccount_WithPrimaryAccount) {
+ // Abort the test if the current platform does not support accounts mutation.
+ if (!accounts_mutator())
+ return;
+
+ // Set up the primary account.
+ std::string primary_account_email("primary.account@example.com");
+ AccountInfo primary_account_info =
+ MakePrimaryAccountAvailable(identity_manager(), primary_account_email);
+
+ // Now try invalidating the primary account, and check that it gets updated.
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnRefreshTokenUpdatedCallback(
+ run_loop.QuitClosure());
+
+ accounts_mutator()->InvalidateRefreshTokenForPrimaryAccount(
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+ run_loop.Run();
+
+ EXPECT_EQ(identity_manager_observer()
+ ->AccountFromRefreshTokenUpdatedCallback()
+ .account_id,
+ primary_account_info.account_id);
+ EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(
+ primary_account_info.account_id));
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ primary_account_info.account_id));
+ auto error = identity_manager()->GetErrorStateOfRefreshTokenForAccount(
+ primary_account_info.account_id);
+ EXPECT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, error.state());
+ EXPECT_EQ(GoogleServiceAuthError::InvalidGaiaCredentialsReason::
+ CREDENTIALS_REJECTED_BY_CLIENT,
+ error.GetInvalidGaiaCredentialsReason());
+}
+
+TEST_F(
+ AccountsMutatorTest,
+ InvalidateRefreshTokenForPrimaryAccount_WithPrimaryAndSecondaryAccounts) {
+ // Abort the test if the current platform does not support accounts mutation.
+ if (!accounts_mutator())
+ return;
+
+ // Set up the primary account.
+ std::string primary_account_email("primary.account@example.com");
+ AccountInfo primary_account_info =
+ MakePrimaryAccountAvailable(identity_manager(), primary_account_email);
+
+ // Next, add a secondary account.
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnRefreshTokenUpdatedCallback(
+ run_loop.QuitClosure());
+
+ std::string account_id = accounts_mutator()->AddOrUpdateAccount(
+ kTestGaiaId, kTestEmail, kRefreshToken,
+ /*is_under_advanced_protection=*/false,
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+ run_loop.Run();
+
+ AccountInfo secondary_account_info =
+ identity_manager()
+ ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ .value();
+ EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 2U);
+
+ // Now try invalidating the primary account, and check that it gets updated.
+ base::RunLoop run_loop2;
+ identity_manager_observer()->SetOnRefreshTokenUpdatedCallback(
+ run_loop2.QuitClosure());
+
+ accounts_mutator()->InvalidateRefreshTokenForPrimaryAccount(
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+ run_loop2.Run();
+
+ EXPECT_EQ(identity_manager_observer()
+ ->AccountFromRefreshTokenUpdatedCallback()
+ .account_id,
+ primary_account_info.account_id);
+
+ // Check whether the primary account refresh token got invalidated.
+ EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(
+ primary_account_info.account_id));
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ primary_account_info.account_id));
+ auto error = identity_manager()->GetErrorStateOfRefreshTokenForAccount(
+ primary_account_info.account_id);
+ EXPECT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, error.state());
+ EXPECT_EQ(GoogleServiceAuthError::InvalidGaiaCredentialsReason::
+ CREDENTIALS_REJECTED_BY_CLIENT,
+ error.GetInvalidGaiaCredentialsReason());
+
+ // Last, check whether the secondary account credentials remain untouched.
+ EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_id));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ account_id));
+ EXPECT_EQ(secondary_account_info.account_id, account_id);
+ EXPECT_EQ(secondary_account_info.email, kTestEmail);
+ EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 2U);
+}
+
+TEST_F(AccountsMutatorTest,
+ InvalidateRefreshTokenForPrimaryAccount_WithoutPrimaryAccount) {
+ // Abort the test if the current platform does not support accounts mutation.
+ if (!accounts_mutator())
+ return;
+
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccount());
+
+ // Now try invalidating the primary account, and make sure the test
+ // expectedly fails, since the primary account is not set.
+ EXPECT_DCHECK_DEATH(
+ accounts_mutator()->InvalidateRefreshTokenForPrimaryAccount(
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown));
+
+ base::RunLoop().RunUntilIdle();
+}
+
+// Test that attempting to remove a non-existing account should not result in
+// firing any callback from AccountTrackerService or ProfileOAuth2TokenService.
+TEST_F(AccountsMutatorTest, RemoveAccount_NonExistingAccount) {
+ // Abort the test if the current platform does not support accounts mutation.
+ if (!accounts_mutator())
+ return;
+
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnRefreshTokenUpdatedCallback(
+ base::BindOnce([]() {
+ // This callback should not be invoked now.
+ EXPECT_TRUE(false);
+ }));
+
+ accounts_mutator()->RemoveAccount(
+ kTestGaiaId, signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+ run_loop.RunUntilIdle();
+
+ EXPECT_FALSE(identity_manager()->HasAccountWithRefreshToken(kTestGaiaId));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ kTestGaiaId));
+ EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 0U);
+}
+
+// Test that attempting to remove an existing account should result in firing
+// the right callbacks from AccountTrackerService or ProfileOAuth2TokenService.
+TEST_F(AccountsMutatorTest, RemoveAccount_ExistingAccount) {
+ // Abort the test if the current platform does not support accounts mutation.
+ if (!accounts_mutator())
+ return;
+
+ // First of all add the account to the account tracker service.
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnRefreshTokenUpdatedCallback(
+ run_loop.QuitClosure());
+
+ std::string account_id = accounts_mutator()->AddOrUpdateAccount(
+ kTestGaiaId, kTestEmail, kRefreshToken,
+ /*is_under_advanced_protection=*/false,
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+ run_loop.Run();
+
+ EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_id));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ account_id));
+ EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 1U);
+
+ // Now remove the account that we just added.
+ base::RunLoop run_loop2;
+ identity_manager_observer()->SetOnRefreshTokenRemovedCallback(
+ run_loop2.QuitClosure());
+
+ accounts_mutator()->RemoveAccount(
+ account_id, signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+ run_loop2.Run();
+
+ EXPECT_EQ(
+ identity_manager_observer()->AccountIdFromRefreshTokenRemovedCallback(),
+ account_id);
+
+ EXPECT_FALSE(identity_manager()->HasAccountWithRefreshToken(account_id));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ account_id));
+ EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 0U);
+}
+
+// Test that attempting to remove all accounts removes all the tokens from the
+// PO2TS and every account from the AccountTrackerService.
+TEST_F(AccountsMutatorTest, RemoveAllAccounts) {
+ // Abort the test if the current platform does not support accounts mutation.
+ if (!accounts_mutator())
+ return;
+
+ // First of all the first account to the account tracker service.
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnRefreshTokenUpdatedCallback(
+ run_loop.QuitClosure());
+
+ std::string account_id = accounts_mutator()->AddOrUpdateAccount(
+ kTestGaiaId, kTestEmail, kRefreshToken,
+ /*is_under_advanced_protection=*/false,
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+ run_loop.Run();
+
+ EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_id));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ account_id));
+ EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 1U);
+
+ // Now add the second account.
+ base::RunLoop run_loop2;
+ identity_manager_observer()->SetOnRefreshTokenUpdatedCallback(
+ run_loop2.QuitClosure());
+
+ std::string account_id2 = accounts_mutator()->AddOrUpdateAccount(
+ kTestGaiaId2, kTestEmail2, kRefreshToken2,
+ /*is_under_advanced_protection=*/false,
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+ run_loop2.Run();
+
+ EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_id2));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ account_id2));
+ EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 2U);
+
+ // Now remove everything and check that there are no lingering accounts, nor
+ // refresh tokens associated to |kTestGaiaId| and |kTestGaiaId2| afterwards.
+ base::RunLoop run_loop3;
+ accounts_mutator()->RemoveAllAccounts(
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+ run_loop3.RunUntilIdle();
+
+ EXPECT_FALSE(identity_manager()->HasAccountWithRefreshToken(kTestGaiaId));
+ EXPECT_FALSE(identity_manager()->HasAccountWithRefreshToken(kTestGaiaId2));
+ EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 0U);
+}
+
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+TEST_F(AccountsMutatorTest, MoveAccount) {
+ // All platforms that support DICE also support account mutation.
+ DCHECK(accounts_mutator());
+
+ AccountInfo account_info =
+ MakeAccountAvailable(identity_manager(), kTestEmail);
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ account_info.account_id));
+ EXPECT_EQ(1U, identity_manager()->GetAccountsWithRefreshTokens().size());
+
+ IdentityTestEnvironment other_identity_test_env;
+ auto* other_accounts_mutator =
+ other_identity_test_env.identity_manager()->GetAccountsMutator();
+
+ std::string device_id_1 = GetOrCreateScopedDeviceId(pref_service());
+ EXPECT_FALSE(device_id_1.empty());
+
+ accounts_mutator()->MoveAccount(other_accounts_mutator,
+ account_info.account_id);
+ EXPECT_EQ(0U, identity_manager()->GetAccountsWithRefreshTokens().size());
+
+ std::string device_id_2 = GetOrCreateScopedDeviceId(pref_service());
+ EXPECT_FALSE(device_id_2.empty());
+ // |device_id_1| and |device_id_2| should be different as the divice ID is
+ // recreated in MoveAccount().
+ EXPECT_NE(device_id_1, device_id_2);
+
+ auto other_accounts_with_refresh_token =
+ other_identity_test_env.identity_manager()
+ ->GetAccountsWithRefreshTokens();
+ EXPECT_EQ(1U, other_accounts_with_refresh_token.size());
+ EXPECT_TRUE(
+ other_identity_test_env.identity_manager()->HasAccountWithRefreshToken(
+ other_accounts_with_refresh_token[0].account_id));
+ EXPECT_FALSE(other_identity_test_env.identity_manager()
+ ->HasAccountWithRefreshTokenInPersistentErrorState(
+ other_accounts_with_refresh_token[0].account_id));
+}
+#endif // BUILDFLAG(ENABLE_DICE_SUPPORT)
+
+TEST_F(AccountsMutatorTest, LegacySetRefreshTokenForSupervisedUser) {
+ // Abort the test if the current platform does not support accounts mutation.
+ if (!accounts_mutator())
+ return;
+
+ EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 0U);
+
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnRefreshTokenUpdatedCallback(
+ run_loop.QuitClosure());
+
+ accounts_mutator()->LegacySetRefreshTokenForSupervisedUser(kRefreshToken);
+ run_loop.Run();
+
+ // In the context of supervised users, the ProfileOAuth2TokenService is used
+ // without the AccountTrackerService being used, so we can't use any of the
+ // IdentityManager::FindAccountInfoForAccountWithRefreshTokenBy*() methods
+ // since they won't find any account. Use GetAccountsWithRefreshTokens() and
+ // HasAccountWithRefreshToken*() instead, that only relies in the PO2TS.
+ std::vector<CoreAccountInfo> accounts =
+ identity_manager()->GetAccountsWithRefreshTokens();
+ EXPECT_EQ(accounts.size(), 1U);
+ EXPECT_EQ(accounts[0].account_id, kSupervisedUserPseudoEmail);
+ EXPECT_EQ(accounts[0].email, kSupervisedUserPseudoEmail);
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshToken(accounts[0].account_id));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ accounts[0].account_id));
+}
+
+TEST_F(AccountsMutatorTest, UpdateAccessTokenFromSource) {
+ // Abort the test if the current platform does not support accounts mutation.
+ if (!accounts_mutator())
+ return;
+
+ // Add a default account.
+ std::string account_id = accounts_mutator()->AddOrUpdateAccount(
+ kTestGaiaId, kTestEmail, "refresh_token", false,
+ signin_metrics::SourceForRefreshTokenOperation::kUnknown);
+ EXPECT_EQ(
+ account_id,
+ identity_manager_diagnostics_observer()->token_updator_account_id());
+ EXPECT_TRUE(identity_manager_diagnostics_observer()
+ ->is_token_updator_refresh_token_valid());
+ EXPECT_EQ("Unknown",
+ identity_manager_diagnostics_observer()->token_updator_source());
+
+ // Update the default account with different source.
+ accounts_mutator()->AddOrUpdateAccount(
+ kTestGaiaId, kTestEmail, "refresh_token2", true,
+ signin_metrics::SourceForRefreshTokenOperation::kSettings_Signout);
+ EXPECT_EQ(
+ account_id,
+ identity_manager_diagnostics_observer()->token_updator_account_id());
+ EXPECT_TRUE(identity_manager_diagnostics_observer()
+ ->is_token_updator_refresh_token_valid());
+ EXPECT_EQ("Settings::Signout",
+ identity_manager_diagnostics_observer()->token_updator_source());
+}
+
+TEST_F(AccountsMutatorTest, RemoveRefreshTokenFromSource) {
+ // Abort the test if the current platform does not support accounts mutation.
+ if (!accounts_mutator())
+ return;
+
+ // Add a default account.
+ std::string account_id = accounts_mutator()->AddOrUpdateAccount(
+ kTestGaiaId, kTestEmail, "refresh_token", false,
+ signin_metrics::SourceForRefreshTokenOperation::kSettings_Signout);
+
+ // Remove the default account.
+ accounts_mutator()->RemoveAccount(
+ kTestGaiaId,
+ signin_metrics::SourceForRefreshTokenOperation::kSettings_Signout);
+ EXPECT_EQ("Settings::Signout",
+ identity_manager_diagnostics_observer()->token_remover_source());
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/device_accounts_synchronizer.h b/chromium/components/signin/public/identity_manager/device_accounts_synchronizer.h
new file mode 100644
index 00000000000..bf99d7cb3cd
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/device_accounts_synchronizer.h
@@ -0,0 +1,41 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_DEVICE_ACCOUNTS_SYNCHRONIZER_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_DEVICE_ACCOUNTS_SYNCHRONIZER_H_
+
+#include "google_apis/gaia/core_account_id.h"
+
+namespace signin {
+
+// DeviceAccountsSynchronizer is the interface to support seeding the accounts
+// information from a device-level store.
+class DeviceAccountsSynchronizer {
+ public:
+ DeviceAccountsSynchronizer() = default;
+ virtual ~DeviceAccountsSynchronizer() = default;
+
+ // Reloads the information of all device-level accounts. All device-level
+ // accounts will be visible in IdentityManager::GetAccountsWithRefreshTokens()
+ // with any persistent errors cleared after this method is called.
+ virtual void ReloadAllAccountsFromSystem() = 0;
+
+ // Reloads the information of the device-level account with |account_id|. The
+ // account will be visible in IdentityManager::GetAccountsWithRefreshTokens()
+ // with any persistent error cleared after this method is called.
+ virtual void ReloadAccountFromSystem(const CoreAccountId& account_id) = 0;
+
+ // Class is non-copyable, non-moveable.
+ DeviceAccountsSynchronizer(const DeviceAccountsSynchronizer&) = delete;
+ DeviceAccountsSynchronizer& operator=(const DeviceAccountsSynchronizer&) =
+ delete;
+
+ DeviceAccountsSynchronizer(DeviceAccountsSynchronizer&&) noexcept = delete;
+ DeviceAccountsSynchronizer& operator=(DeviceAccountsSynchronizer&&) noexcept =
+ delete;
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_DEVICE_ACCOUNTS_SYNCHRONIZER_H_
diff --git a/chromium/components/signin/public/identity_manager/diagnostics_provider.h b/chromium/components/signin/public/identity_manager/diagnostics_provider.h
new file mode 100644
index 00000000000..37d0c09031b
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/diagnostics_provider.h
@@ -0,0 +1,39 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_DIAGNOSTICS_PROVIDER_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_DIAGNOSTICS_PROVIDER_H_
+
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "components/signin/public/identity_manager/load_credentials_state.h"
+
+namespace signin {
+
+// DiagnosticsProvider is the interface to obtain diagnostics about
+// IdentityManager internals.
+class DiagnosticsProvider {
+ public:
+ DiagnosticsProvider() = default;
+ virtual ~DiagnosticsProvider() = default;
+
+ // Returns the state of the load credentials operation.
+ virtual signin::LoadCredentialsState
+ GetDetailedStateOfLoadingOfRefreshTokens() const = 0;
+
+ // Returns the time until a access token request can be sent (will be zero if
+ // the release time is in the past).
+ virtual base::TimeDelta GetDelayBeforeMakingAccessTokenRequests() const = 0;
+
+ // Returns the time until a cookie request can be sent (will be zero if the
+ // release time is in the past).
+ virtual base::TimeDelta GetDelayBeforeMakingCookieRequests() const = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DiagnosticsProvider);
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_DIAGNOSTICS_PROVIDER_H_
diff --git a/chromium/components/signin/public/identity_manager/diagnostics_provider_unittest.cc b/chromium/components/signin/public/identity_manager/diagnostics_provider_unittest.cc
new file mode 100644
index 00000000000..87fb50f9310
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/diagnostics_provider_unittest.cc
@@ -0,0 +1,80 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/internal/identity_manager/diagnostics_provider_impl.h"
+
+#include "base/bind_helpers.h"
+#include "base/macros.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/signin/public/identity_manager/accounts_cookie_mutator.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "components/signin/public/identity_manager/load_credentials_state.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+const char kAccountId[] = "user@gmail.com";
+
+namespace {
+
+class DiagnosticsProviderTest : public testing::Test {
+ public:
+ DiagnosticsProviderTest() = default;
+
+ signin::IdentityTestEnvironment* identity_test_env() {
+ return &identity_test_env_;
+ }
+
+ signin::DiagnosticsProvider* diagnostics_provider() {
+ return identity_test_env_.identity_manager()->GetDiagnosticsProvider();
+ }
+
+ protected:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+ private:
+ signin::IdentityTestEnvironment identity_test_env_;
+
+ DISALLOW_COPY_AND_ASSIGN(DiagnosticsProviderTest);
+};
+
+} // namespace
+
+TEST_F(DiagnosticsProviderTest, Basic) {
+ // Accessing the DiagnosticProvider should not crash.
+ ASSERT_TRUE(identity_test_env()->identity_manager());
+ EXPECT_TRUE(
+ identity_test_env()->identity_manager()->GetDiagnosticsProvider());
+}
+
+TEST_F(DiagnosticsProviderTest, GetDetailedStateOfLoadingOfRefreshTokens) {
+ EXPECT_EQ(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ diagnostics_provider()->GetDetailedStateOfLoadingOfRefreshTokens());
+}
+
+TEST_F(DiagnosticsProviderTest, GetDelayBeforeMakingAccessTokenRequests) {
+ base::TimeDelta zero;
+ EXPECT_EQ(diagnostics_provider()->GetDelayBeforeMakingAccessTokenRequests(),
+ zero);
+ std::string account_id =
+ identity_test_env()->MakeAccountAvailable(kAccountId).account_id;
+ identity_test_env()->UpdatePersistentErrorOfRefreshTokenForAccount(
+ account_id, GoogleServiceAuthError(
+ GoogleServiceAuthError::State::SERVICE_UNAVAILABLE));
+ EXPECT_GT(diagnostics_provider()->GetDelayBeforeMakingAccessTokenRequests(),
+ zero);
+}
+
+TEST_F(DiagnosticsProviderTest, GetDelayBeforeMakingCookieRequests) {
+ base::TimeDelta zero;
+ identity_test_env()
+ ->identity_manager()
+ ->GetAccountsCookieMutator()
+ ->AddAccountToCookie(kAccountId, gaia::GaiaSource::kChrome,
+ base::DoNothing());
+ EXPECT_EQ(diagnostics_provider()->GetDelayBeforeMakingCookieRequests(), zero);
+
+ identity_test_env()->SimulateMergeSessionFailure(
+ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
+ EXPECT_GT(diagnostics_provider()->GetDelayBeforeMakingCookieRequests(), zero);
+}
diff --git a/chromium/components/signin/public/identity_manager/identity_manager.cc b/chromium/components/signin/public/identity_manager/identity_manager.cc
new file mode 100644
index 00000000000..de180ab04ae
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/identity_manager.cc
@@ -0,0 +1,705 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/identity_manager.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "build/build_config.h"
+#include "components/signin/internal/identity_manager/account_fetcher_service.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h"
+#include "components/signin/internal/identity_manager/primary_account_manager.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/internal/identity_manager/ubertoken_fetcher_impl.h"
+#include "components/signin/public/identity_manager/accounts_cookie_mutator.h"
+#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
+#include "components/signin/public/identity_manager/accounts_mutator.h"
+#include "components/signin/public/identity_manager/device_accounts_synchronizer.h"
+#include "components/signin/public/identity_manager/diagnostics_provider.h"
+#include "components/signin/public/identity_manager/primary_account_mutator.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+#if defined(OS_ANDROID)
+#include "components/signin/internal/identity_manager/oauth2_token_service_delegate_android.h"
+#elif !defined(OS_IOS)
+#include "components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.h"
+#endif
+
+namespace signin {
+
+namespace {
+
+// Local copy of the account ID used for supervised users (defined in //chrome
+// as supervised_users::kSupervisedUserPseudoEmail). Simply copied to avoid
+// plumbing it from //chrome all the way down through the Identity Service just
+// to handle the corner cases below.
+// TODO(860492): Remove this once supervised user support is removed.
+const char kSupervisedUserPseudoEmail[] = "managed_user@localhost";
+
+// A made-up Gaia ID to populate the supervised user's AccountInfo with in order
+// to maintain the invariant that the AccountInfos passed out by IdentityManager
+// always have an account ID, Gaia ID, and email set.
+// TODO(860492): Remove this once supervised user support is removed.
+const char kSupervisedUserPseudoGaiaID[] = "managed_user_gaia_id";
+
+} // namespace
+
+IdentityManager::IdentityManager(
+ std::unique_ptr<AccountTrackerService> account_tracker_service,
+ std::unique_ptr<ProfileOAuth2TokenService> token_service,
+ std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service,
+ std::unique_ptr<PrimaryAccountManager> primary_account_manager,
+ std::unique_ptr<AccountFetcherService> account_fetcher_service,
+ std::unique_ptr<PrimaryAccountMutator> primary_account_mutator,
+ std::unique_ptr<AccountsMutator> accounts_mutator,
+ std::unique_ptr<AccountsCookieMutator> accounts_cookie_mutator,
+ std::unique_ptr<DiagnosticsProvider> diagnostics_provider,
+ std::unique_ptr<DeviceAccountsSynchronizer> device_accounts_synchronizer)
+ : account_tracker_service_(std::move(account_tracker_service)),
+ token_service_(std::move(token_service)),
+ gaia_cookie_manager_service_(std::move(gaia_cookie_manager_service)),
+ primary_account_manager_(std::move(primary_account_manager)),
+ account_fetcher_service_(std::move(account_fetcher_service)),
+ primary_account_mutator_(std::move(primary_account_mutator)),
+ accounts_mutator_(std::move(accounts_mutator)),
+ accounts_cookie_mutator_(std::move(accounts_cookie_mutator)),
+ diagnostics_provider_(std::move(diagnostics_provider)),
+ device_accounts_synchronizer_(std::move(device_accounts_synchronizer)) {
+ DCHECK(account_fetcher_service_);
+ DCHECK(accounts_cookie_mutator_);
+ DCHECK(diagnostics_provider_);
+
+ DCHECK(!accounts_mutator_ || !device_accounts_synchronizer_)
+ << "Cannot have both an AccountsMutator and a DeviceAccountsSynchronizer";
+
+ // IdentityManager will outlive the PrimaryAccountManager, so base::Unretained
+ // is safe.
+ primary_account_manager_->SetGoogleSigninSucceededCallback(
+ base::BindRepeating(&IdentityManager::GoogleSigninSucceeded,
+ base::Unretained(this)));
+ primary_account_manager_->SetAuthenticatedAccountSetCallback(
+ base::BindRepeating(&IdentityManager::AuthenticatedAccountSet,
+ base::Unretained(this)));
+ primary_account_manager_->SetAuthenticatedAccountClearedCallback(
+ base::BindRepeating(&IdentityManager::AuthenticatedAccountCleared,
+ base::Unretained(this)));
+#if !defined(OS_CHROMEOS)
+ primary_account_manager_->SetGoogleSignedOutCallback(base::BindRepeating(
+ &IdentityManager::GoogleSignedOut, base::Unretained(this)));
+#endif
+
+ token_service_->AddObserver(this);
+ token_service_->AddAccessTokenDiagnosticsObserver(this);
+
+ // IdentityManager owns the ATS, GCMS and PO2TS instances and will outlive
+ // them, so base::Unretained is safe.
+ account_tracker_service_->SetOnAccountUpdatedCallback(base::BindRepeating(
+ &IdentityManager::OnAccountUpdated, base::Unretained(this)));
+ account_tracker_service_->SetOnAccountRemovedCallback(base::BindRepeating(
+ &IdentityManager::OnAccountRemoved, base::Unretained(this)));
+ gaia_cookie_manager_service_->SetGaiaAccountsInCookieUpdatedCallback(
+ base::BindRepeating(&IdentityManager::OnGaiaAccountsInCookieUpdated,
+ base::Unretained(this)));
+ gaia_cookie_manager_service_->SetGaiaCookieDeletedByUserActionCallback(
+ base::BindRepeating(&IdentityManager::OnGaiaCookieDeletedByUserAction,
+ base::Unretained(this)));
+ token_service_->SetRefreshTokenAvailableFromSourceCallback(
+ base::BindRepeating(&IdentityManager::OnRefreshTokenAvailableFromSource,
+ base::Unretained(this)));
+ token_service_->SetRefreshTokenRevokedFromSourceCallback(
+ base::BindRepeating(&IdentityManager::OnRefreshTokenRevokedFromSource,
+ base::Unretained(this)));
+
+ // Seed the primary account with any state that |primary_account_manager_|
+ // loaded from prefs.
+ if (primary_account_manager_->IsAuthenticated()) {
+ CoreAccountInfo account =
+ primary_account_manager_->GetAuthenticatedAccountInfo();
+ DCHECK(!account.account_id.empty());
+ SetPrimaryAccountInternal(std::move(account));
+ }
+}
+
+IdentityManager::~IdentityManager() {
+ account_fetcher_service_->Shutdown();
+ gaia_cookie_manager_service_->Shutdown();
+ token_service_->Shutdown();
+ account_tracker_service_->Shutdown();
+
+ token_service_->RemoveObserver(this);
+ token_service_->RemoveAccessTokenDiagnosticsObserver(this);
+}
+
+void IdentityManager::AddObserver(Observer* observer) {
+ observer_list_.AddObserver(observer);
+}
+
+void IdentityManager::RemoveObserver(Observer* observer) {
+ observer_list_.RemoveObserver(observer);
+}
+
+// TODO(862619) change return type to base::Optional<CoreAccountInfo>
+CoreAccountInfo IdentityManager::GetPrimaryAccountInfo() const {
+ DCHECK_EQ(primary_account_.has_value(),
+ primary_account_manager_->IsAuthenticated());
+ auto result = primary_account_.value_or(CoreAccountInfo());
+ DCHECK_EQ(result.account_id,
+ primary_account_manager_->GetAuthenticatedAccountId());
+#if DCHECK_IS_ON()
+ CoreAccountInfo primary_account_manager_account =
+ primary_account_manager_->GetAuthenticatedAccountInfo();
+ if (!primary_account_manager_account.account_id.empty()) {
+ DCHECK_EQ(primary_account_manager_account, result)
+ << "If primary_account_manager_'s account is set (account has a "
+ "refresh token), primary_account_ must have the same value.";
+ }
+#endif
+ return result;
+}
+
+CoreAccountId IdentityManager::GetPrimaryAccountId() const {
+ return GetPrimaryAccountInfo().account_id;
+}
+
+bool IdentityManager::HasPrimaryAccount() const {
+ DCHECK_EQ(primary_account_.has_value(),
+ primary_account_manager_->IsAuthenticated());
+ return primary_account_.has_value();
+}
+
+CoreAccountId IdentityManager::GetUnconsentedPrimaryAccountId() const {
+ return GetUnconsentedPrimaryAccountInfo().account_id;
+}
+
+CoreAccountInfo IdentityManager::GetUnconsentedPrimaryAccountInfo() const {
+ return unconsented_primary_account_.value_or(CoreAccountInfo());
+}
+
+bool IdentityManager::HasUnconsentedPrimaryAccount() const {
+ return unconsented_primary_account_.has_value();
+}
+
+std::unique_ptr<AccessTokenFetcher>
+IdentityManager::CreateAccessTokenFetcherForAccount(
+ const CoreAccountId& account_id,
+ const std::string& oauth_consumer_name,
+ const identity::ScopeSet& scopes,
+ AccessTokenFetcher::TokenCallback callback,
+ AccessTokenFetcher::Mode mode) {
+ return std::make_unique<AccessTokenFetcher>(account_id, oauth_consumer_name,
+ token_service_.get(), scopes,
+ std::move(callback), mode);
+}
+
+std::unique_ptr<AccessTokenFetcher>
+IdentityManager::CreateAccessTokenFetcherForAccount(
+ const CoreAccountId& account_id,
+ const std::string& oauth_consumer_name,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ const identity::ScopeSet& scopes,
+ AccessTokenFetcher::TokenCallback callback,
+ AccessTokenFetcher::Mode mode) {
+ return std::make_unique<AccessTokenFetcher>(
+ account_id, oauth_consumer_name, token_service_.get(), url_loader_factory,
+ scopes, std::move(callback), mode);
+}
+
+std::unique_ptr<AccessTokenFetcher>
+IdentityManager::CreateAccessTokenFetcherForClient(
+ const CoreAccountId& account_id,
+ const std::string& client_id,
+ const std::string& client_secret,
+ const std::string& oauth_consumer_name,
+ const identity::ScopeSet& scopes,
+ AccessTokenFetcher::TokenCallback callback,
+ AccessTokenFetcher::Mode mode) {
+ return std::make_unique<AccessTokenFetcher>(
+ account_id, client_id, client_secret, oauth_consumer_name,
+ token_service_.get(), scopes, std::move(callback), mode);
+}
+
+void IdentityManager::RemoveAccessTokenFromCache(
+ const CoreAccountId& account_id,
+ const identity::ScopeSet& scopes,
+ const std::string& access_token) {
+ token_service_->InvalidateAccessToken(account_id, scopes, access_token);
+}
+
+std::vector<CoreAccountInfo> IdentityManager::GetAccountsWithRefreshTokens()
+ const {
+ std::vector<CoreAccountId> account_ids_with_tokens =
+ token_service_->GetAccounts();
+
+ std::vector<CoreAccountInfo> accounts;
+ accounts.reserve(account_ids_with_tokens.size());
+
+ for (const CoreAccountId& account_id : account_ids_with_tokens) {
+ accounts.push_back(GetAccountInfoForAccountWithRefreshToken(account_id));
+ }
+
+ return accounts;
+}
+
+std::vector<AccountInfo>
+IdentityManager::GetExtendedAccountInfoForAccountsWithRefreshToken() const {
+ std::vector<CoreAccountId> account_ids_with_tokens =
+ token_service_->GetAccounts();
+
+ std::vector<AccountInfo> accounts;
+ accounts.reserve(account_ids_with_tokens.size());
+
+ for (const CoreAccountId& account_id : account_ids_with_tokens) {
+ accounts.push_back(GetAccountInfoForAccountWithRefreshToken(account_id));
+ }
+
+ return accounts;
+}
+
+bool IdentityManager::HasPrimaryAccountWithRefreshToken() const {
+ return HasAccountWithRefreshToken(GetPrimaryAccountId());
+}
+
+bool IdentityManager::HasAccountWithRefreshToken(
+ const CoreAccountId& account_id) const {
+ return token_service_->RefreshTokenIsAvailable(account_id);
+}
+
+bool IdentityManager::AreRefreshTokensLoaded() const {
+ return token_service_->AreAllCredentialsLoaded();
+}
+
+bool IdentityManager::HasAccountWithRefreshTokenInPersistentErrorState(
+ const CoreAccountId& account_id) const {
+ return GetErrorStateOfRefreshTokenForAccount(account_id).IsPersistentError();
+}
+
+GoogleServiceAuthError IdentityManager::GetErrorStateOfRefreshTokenForAccount(
+ const CoreAccountId& account_id) const {
+ return token_service_->GetAuthError(account_id);
+}
+
+base::Optional<AccountInfo> IdentityManager::FindExtendedAccountInfoForAccount(
+ const CoreAccountInfo& account_info) const {
+ AccountInfo extended_account_info =
+ account_tracker_service_->GetAccountInfo(account_info.account_id);
+
+ // AccountTrackerService always returns an AccountInfo, even on failure. In
+ // case of failure, the AccountInfo will be unpopulated, thus we should not
+ // be able to find a valid refresh token.
+ if (!HasAccountWithRefreshToken(extended_account_info.account_id))
+ return base::nullopt;
+
+ return GetAccountInfoForAccountWithRefreshToken(account_info.account_id);
+}
+
+base::Optional<AccountInfo>
+IdentityManager::FindAccountInfoForAccountWithRefreshTokenByAccountId(
+ const CoreAccountId& account_id) const {
+ AccountInfo account_info =
+ account_tracker_service_->GetAccountInfo(account_id);
+
+ // AccountTrackerService always returns an AccountInfo, even on failure. In
+ // case of failure, the AccountInfo will be unpopulated, thus we should not
+ // be able to find a valid refresh token.
+ if (!HasAccountWithRefreshToken(account_info.account_id))
+ return base::nullopt;
+
+ return GetAccountInfoForAccountWithRefreshToken(account_info.account_id);
+}
+
+base::Optional<AccountInfo>
+IdentityManager::FindAccountInfoForAccountWithRefreshTokenByEmailAddress(
+ const std::string& email_address) const {
+ AccountInfo account_info =
+ account_tracker_service_->FindAccountInfoByEmail(email_address);
+
+ // AccountTrackerService always returns an AccountInfo, even on failure. In
+ // case of failure, the AccountInfo will be unpopulated, thus we should not
+ // be able to find a valid refresh token.
+ if (!HasAccountWithRefreshToken(account_info.account_id))
+ return base::nullopt;
+
+ return GetAccountInfoForAccountWithRefreshToken(account_info.account_id);
+}
+
+base::Optional<AccountInfo>
+IdentityManager::FindAccountInfoForAccountWithRefreshTokenByGaiaId(
+ const std::string& gaia_id) const {
+ AccountInfo account_info =
+ account_tracker_service_->FindAccountInfoByGaiaId(gaia_id);
+
+ // AccountTrackerService always returns an AccountInfo, even on failure. In
+ // case of failure, the AccountInfo will be unpopulated, thus we should not
+ // be able to find a valid refresh token.
+ if (!HasAccountWithRefreshToken(account_info.account_id))
+ return base::nullopt;
+
+ return GetAccountInfoForAccountWithRefreshToken(account_info.account_id);
+}
+
+std::unique_ptr<UbertokenFetcher>
+IdentityManager::CreateUbertokenFetcherForAccount(
+ const CoreAccountId& account_id,
+ UbertokenFetcher::CompletionCallback callback,
+ gaia::GaiaSource source,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ bool bount_to_channel_id) {
+ return std::make_unique<UbertokenFetcherImpl>(
+ account_id, token_service_.get(), std::move(callback), source,
+ url_loader_factory, bount_to_channel_id);
+}
+
+AccountsInCookieJarInfo IdentityManager::GetAccountsInCookieJar() const {
+ std::vector<gaia::ListedAccount> signed_in_accounts;
+ std::vector<gaia::ListedAccount> signed_out_accounts;
+ bool accounts_are_fresh = gaia_cookie_manager_service_->ListAccounts(
+ &signed_in_accounts, &signed_out_accounts);
+
+ return AccountsInCookieJarInfo(accounts_are_fresh, signed_in_accounts,
+ signed_out_accounts);
+}
+
+PrimaryAccountMutator* IdentityManager::GetPrimaryAccountMutator() {
+ return primary_account_mutator_.get();
+}
+
+AccountsMutator* IdentityManager::GetAccountsMutator() {
+ return accounts_mutator_.get();
+}
+
+AccountsCookieMutator* IdentityManager::GetAccountsCookieMutator() {
+ return accounts_cookie_mutator_.get();
+}
+
+DeviceAccountsSynchronizer* IdentityManager::GetDeviceAccountsSynchronizer() {
+ return device_accounts_synchronizer_.get();
+}
+
+void IdentityManager::AddDiagnosticsObserver(DiagnosticsObserver* observer) {
+ diagnostics_observer_list_.AddObserver(observer);
+}
+
+void IdentityManager::RemoveDiagnosticsObserver(DiagnosticsObserver* observer) {
+ diagnostics_observer_list_.RemoveObserver(observer);
+}
+
+void IdentityManager::OnNetworkInitialized() {
+ gaia_cookie_manager_service_->InitCookieListener();
+ account_fetcher_service_->OnNetworkInitialized();
+}
+
+// static
+bool IdentityManager::IsAccountIdMigrationSupported() {
+ return AccountTrackerService::IsMigrationSupported();
+}
+
+// static
+void IdentityManager::RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
+ PrimaryAccountManager::RegisterPrefs(registry);
+}
+
+// static
+void IdentityManager::RegisterProfilePrefs(PrefRegistrySimple* registry) {
+ ProfileOAuth2TokenService::RegisterProfilePrefs(registry);
+ PrimaryAccountManager::RegisterProfilePrefs(registry);
+ AccountFetcherService::RegisterPrefs(registry);
+ AccountTrackerService::RegisterPrefs(registry);
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ MutableProfileOAuth2TokenServiceDelegate::RegisterProfilePrefs(registry);
+#endif
+}
+
+CoreAccountId IdentityManager::PickAccountIdForAccount(
+ const std::string& gaia,
+ const std::string& email) const {
+ // TODO(triploblastic@): Remove explicit conversion once
+ // primary_account_manager has been fixed to use CoreAccountId.
+ return CoreAccountId(
+ account_tracker_service_->PickAccountIdForAccount(gaia, email));
+}
+
+IdentityManager::AccountIdMigrationState
+IdentityManager::GetAccountIdMigrationState() const {
+ return static_cast<IdentityManager::AccountIdMigrationState>(
+ account_tracker_service_->GetMigrationState());
+}
+
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+void IdentityManager::DeprecatedLoadCredentialsForSupervisedUser(
+ const CoreAccountId& primary_account_id) {
+ token_service_->LoadCredentials(primary_account_id);
+}
+#endif
+
+DiagnosticsProvider* IdentityManager::GetDiagnosticsProvider() {
+ return diagnostics_provider_.get();
+}
+
+#if defined(OS_IOS)
+void IdentityManager::ForceTriggerOnCookieChange() {
+ gaia_cookie_manager_service_->ForceOnCookieChangeProcessing();
+}
+#endif
+
+#if defined(OS_ANDROID)
+void IdentityManager::LegacyReloadAccountsFromSystem() {
+ token_service_->GetDelegate()->ReloadAccountsFromSystem(
+ GetPrimaryAccountId());
+}
+
+base::android::ScopedJavaLocalRef<jobject>
+IdentityManager::LegacyGetAccountTrackerServiceJavaObject() {
+ return account_tracker_service_->GetJavaObject();
+}
+
+base::android::ScopedJavaLocalRef<jobject>
+IdentityManager::LegacyGetOAuth2TokenServiceJavaObject() {
+ OAuth2TokenServiceDelegateAndroid* delegate =
+ static_cast<OAuth2TokenServiceDelegateAndroid*>(
+ token_service_->GetDelegate());
+ return delegate->GetJavaObject();
+}
+
+void IdentityManager::ForceRefreshOfExtendedAccountInfo(
+ const CoreAccountId& account_id) {
+ DCHECK(HasAccountWithRefreshToken(account_id));
+ account_fetcher_service_->ForceRefreshOfAccountInfo(account_id);
+}
+#endif
+
+PrimaryAccountManager* IdentityManager::GetPrimaryAccountManager() {
+ return primary_account_manager_.get();
+}
+
+ProfileOAuth2TokenService* IdentityManager::GetTokenService() {
+ return token_service_.get();
+}
+
+AccountTrackerService* IdentityManager::GetAccountTrackerService() {
+ return account_tracker_service_.get();
+}
+
+AccountFetcherService* IdentityManager::GetAccountFetcherService() {
+ return account_fetcher_service_.get();
+}
+
+GaiaCookieManagerService* IdentityManager::GetGaiaCookieManagerService() {
+ return gaia_cookie_manager_service_.get();
+}
+
+AccountInfo IdentityManager::GetAccountInfoForAccountWithRefreshToken(
+ const CoreAccountId& account_id) const {
+ // TODO(https://crbug.com/919793): This invariant is not currently possible to
+ // enforce on Android due to the underlying relationship between
+ // O2TS::GetAccounts(), O2TS::RefreshTokenIsAvailable(), and
+ // O2TS::Observer::OnRefreshTokenAvailable().
+#if !defined(OS_ANDROID)
+ DCHECK(HasAccountWithRefreshToken(account_id));
+#endif
+
+ AccountInfo account_info =
+ account_tracker_service_->GetAccountInfo(account_id);
+
+ // In the context of supervised users, the ProfileOAuth2TokenService is used
+ // without the AccountTrackerService being used. This is the only case in
+ // which the AccountTrackerService will potentially not know about the
+ // account. In this context, |account_id| is always set to
+ // kSupervisedUserPseudoEmail. Populate the information manually in this case
+ // to maintain the invariant that the account ID, gaia ID, and email are
+ // always set.
+ // TODO(860492): Remove this special case once supervised user support is
+ // removed.
+ DCHECK(!account_info.IsEmpty() ||
+ account_id.id == kSupervisedUserPseudoEmail);
+ if (account_id.id == kSupervisedUserPseudoEmail && account_info.IsEmpty()) {
+ account_info.account_id = account_id;
+ account_info.email = kSupervisedUserPseudoEmail;
+ account_info.gaia = kSupervisedUserPseudoGaiaID;
+ }
+
+ return account_info;
+}
+
+void IdentityManager::SetPrimaryAccountInternal(
+ base::Optional<CoreAccountInfo> account_info) {
+ primary_account_ = std::move(account_info);
+ UpdateUnconsentedPrimaryAccount();
+}
+
+void IdentityManager::UpdateUnconsentedPrimaryAccount() {
+ base::Optional<CoreAccountInfo> new_unconsented_primary_account =
+ ComputeUnconsentedPrimaryAccountInfo();
+ if (unconsented_primary_account_ != new_unconsented_primary_account) {
+ unconsented_primary_account_ = std::move(new_unconsented_primary_account);
+ for (auto& observer : observer_list_) {
+ observer.OnUnconsentedPrimaryAccountChanged(
+ unconsented_primary_account_.value_or(CoreAccountInfo()));
+ }
+ }
+}
+
+base::Optional<CoreAccountInfo>
+IdentityManager::ComputeUnconsentedPrimaryAccountInfo() const {
+ if (HasPrimaryAccount())
+ return GetPrimaryAccountInfo();
+
+#if defined(OS_CHROMEOS) || defined(OS_IOS) || defined(OS_ANDROID)
+ // On ChromeOS and on mobile platforms, we support only the primary account as
+ // the unconsented primary account. By this early return, we avoid an extra
+ // request to GAIA that lists cookie accounts.
+ return base::nullopt;
+#else
+ std::vector<gaia::ListedAccount> cookie_accounts =
+ GetAccountsInCookieJar().signed_in_accounts;
+ if (cookie_accounts.empty())
+ return base::nullopt;
+
+ const CoreAccountId first_account_id = cookie_accounts[0].id;
+ if (!HasAccountWithRefreshToken(first_account_id))
+ return base::nullopt;
+
+ return GetAccountInfoForAccountWithRefreshToken(first_account_id);
+#endif
+}
+
+void IdentityManager::GoogleSigninSucceeded(const AccountInfo& account_info) {
+ for (auto& observer : observer_list_) {
+ observer.OnPrimaryAccountSet(account_info);
+ }
+}
+
+void IdentityManager::GoogleSignedOut(const AccountInfo& account_info) {
+ DCHECK(!HasPrimaryAccount());
+ for (auto& observer : observer_list_) {
+ observer.OnPrimaryAccountCleared(account_info);
+ }
+}
+void IdentityManager::AuthenticatedAccountSet(const AccountInfo& account_info) {
+ DCHECK(primary_account_manager_->IsAuthenticated());
+ SetPrimaryAccountInternal(account_info);
+}
+void IdentityManager::AuthenticatedAccountCleared() {
+ DCHECK(!primary_account_manager_->IsAuthenticated());
+ SetPrimaryAccountInternal(base::nullopt);
+}
+
+void IdentityManager::OnRefreshTokenAvailable(const CoreAccountId& account_id) {
+ UpdateUnconsentedPrimaryAccount();
+ CoreAccountInfo account_info =
+ GetAccountInfoForAccountWithRefreshToken(account_id);
+
+ for (auto& observer : observer_list_) {
+ observer.OnRefreshTokenUpdatedForAccount(account_info);
+ }
+}
+
+void IdentityManager::OnRefreshTokenRevoked(const CoreAccountId& account_id) {
+ UpdateUnconsentedPrimaryAccount();
+ for (auto& observer : observer_list_) {
+ observer.OnRefreshTokenRemovedForAccount(account_id);
+ }
+}
+
+void IdentityManager::OnRefreshTokensLoaded() {
+ UpdateUnconsentedPrimaryAccount();
+ for (auto& observer : observer_list_)
+ observer.OnRefreshTokensLoaded();
+}
+
+void IdentityManager::OnEndBatchChanges() {
+ for (auto& observer : observer_list_)
+ observer.OnEndBatchOfRefreshTokenStateChanges();
+}
+
+void IdentityManager::OnAuthErrorChanged(
+ const CoreAccountId& account_id,
+ const GoogleServiceAuthError& auth_error) {
+ CoreAccountInfo account_info =
+ GetAccountInfoForAccountWithRefreshToken(account_id);
+
+ for (auto& observer : observer_list_)
+ observer.OnErrorStateOfRefreshTokenUpdatedForAccount(account_info,
+ auth_error);
+}
+
+void IdentityManager::OnGaiaAccountsInCookieUpdated(
+ const std::vector<gaia::ListedAccount>& signed_in_accounts,
+ const std::vector<gaia::ListedAccount>& signed_out_accounts,
+ const GoogleServiceAuthError& error) {
+ UpdateUnconsentedPrimaryAccount();
+ AccountsInCookieJarInfo accounts_in_cookie_jar_info(
+ error == GoogleServiceAuthError::AuthErrorNone(), signed_in_accounts,
+ signed_out_accounts);
+
+ for (auto& observer : observer_list_) {
+ observer.OnAccountsInCookieUpdated(accounts_in_cookie_jar_info, error);
+ }
+}
+
+void IdentityManager::OnGaiaCookieDeletedByUserAction() {
+ UpdateUnconsentedPrimaryAccount();
+ for (auto& observer : observer_list_) {
+ observer.OnAccountsCookieDeletedByUserAction();
+ }
+}
+
+void IdentityManager::OnAccessTokenRequested(const CoreAccountId& account_id,
+ const std::string& consumer_id,
+ const identity::ScopeSet& scopes) {
+ for (auto& observer : diagnostics_observer_list_) {
+ observer.OnAccessTokenRequested(account_id, consumer_id, scopes);
+ }
+}
+
+void IdentityManager::OnFetchAccessTokenComplete(
+ const CoreAccountId& account_id,
+ const std::string& consumer_id,
+ const identity::ScopeSet& scopes,
+ GoogleServiceAuthError error,
+ base::Time expiration_time) {
+ for (auto& observer : diagnostics_observer_list_)
+ observer.OnAccessTokenRequestCompleted(account_id, consumer_id, scopes,
+ error, expiration_time);
+}
+
+void IdentityManager::OnAccessTokenRemoved(const CoreAccountId& account_id,
+ const identity::ScopeSet& scopes) {
+ for (auto& observer : diagnostics_observer_list_)
+ observer.OnAccessTokenRemovedFromCache(account_id, scopes);
+}
+
+void IdentityManager::OnRefreshTokenAvailableFromSource(
+ const CoreAccountId& account_id,
+ bool is_refresh_token_valid,
+ const std::string& source) {
+ for (auto& observer : diagnostics_observer_list_)
+ observer.OnRefreshTokenUpdatedForAccountFromSource(
+ account_id, is_refresh_token_valid, source);
+}
+
+void IdentityManager::OnRefreshTokenRevokedFromSource(
+ const CoreAccountId& account_id,
+ const std::string& source) {
+ for (auto& observer : diagnostics_observer_list_)
+ observer.OnRefreshTokenRemovedForAccountFromSource(account_id, source);
+}
+
+void IdentityManager::OnAccountUpdated(const AccountInfo& info) {
+ if (primary_account_ && primary_account_->account_id == info.account_id) {
+ SetPrimaryAccountInternal(info);
+ }
+ for (auto& observer : observer_list_) {
+ observer.OnExtendedAccountInfoUpdated(info);
+ }
+}
+
+void IdentityManager::OnAccountRemoved(const AccountInfo& info) {
+ for (auto& observer : observer_list_)
+ observer.OnExtendedAccountInfoRemoved(info);
+ UpdateUnconsentedPrimaryAccount();
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/identity_manager.h b/chromium/components/signin/public/identity_manager/identity_manager.h
new file mode 100644
index 00000000000..00ad7000e59
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/identity_manager.h
@@ -0,0 +1,703 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_MANAGER_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_MANAGER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "base/observer_list.h"
+#include "build/build_config.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "components/signin/public/identity_manager/access_token_fetcher.h"
+#include "components/signin/public/identity_manager/account_info.h"
+#include "components/signin/public/identity_manager/ubertoken_fetcher.h"
+#include "google_apis/gaia/oauth2_access_token_manager.h"
+#include "google_apis/gaia/oauth2_token_service_observer.h"
+#include "services/identity/public/cpp/scope_set.h"
+
+#if defined(OS_ANDROID)
+#include "base/android/jni_android.h"
+#endif
+
+namespace gaia {
+class GaiaSource;
+struct ListedAccount;
+} // namespace gaia
+
+namespace network {
+class SharedURLLoaderFactory;
+class TestURLLoaderFactory;
+} // namespace network
+
+// Necessary to declare these classes as friends.
+class PrefRegistrySimple;
+class SigninManagerAndroid;
+
+class AccountFetcherService;
+class AccountTrackerService;
+class GaiaCookieManagerService;
+class PrimaryAccountManager;
+class ProfileOAuth2TokenService;
+
+namespace signin {
+
+class AccountsMutator;
+class AccountsCookieMutator;
+struct AccountsInCookieJarInfo;
+class IdentityManagerTest;
+class IdentityTestEnvironment;
+class DeviceAccountsSynchronizer;
+class DiagnosticsProvider;
+class PrimaryAccountMutator;
+enum class ClearPrimaryAccountPolicy;
+struct CookieParamsForTest;
+
+// Gives access to information about the user's Google identities. See
+// ./README.md for detailed documentation.
+class IdentityManager : public KeyedService,
+ public OAuth2AccessTokenManager::DiagnosticsObserver,
+ public OAuth2TokenServiceObserver {
+ public:
+ class Observer {
+ public:
+ Observer() = default;
+ virtual ~Observer() = default;
+
+ Observer(const Observer&) = delete;
+ Observer& operator=(const Observer&) = delete;
+
+ // Called when an account becomes the user's primary account.
+ // This method is not called during a reauth.
+ virtual void OnPrimaryAccountSet(
+ const CoreAccountInfo& primary_account_info) {}
+
+ // Called when the user moves from having a primary account to no longer
+ // having a primary account (note that the user may still have an
+ // *unconsented* primary account after this event; see./README.md).
+ virtual void OnPrimaryAccountCleared(
+ const CoreAccountInfo& previous_primary_account_info) {}
+
+ // When the unconsented primary account (see ./README.md) of the user
+ // changes, this callback gets called with the new account as
+ // |unconsented_primary_account_info|. If after the change, there is no
+ // unconsented primary account, |unconsented_primary_account_info| is empty.
+ // This does not get called when the unconsented account becomes consented
+ // (as the same account was unconsented before so there is no change). In
+ // all other changes (the unconsented primary account gets added, changed or
+ // removed), this notification is called only once. Note: we do not use the
+ // {Set, Cleared} notifications like for the primary account above because
+ // the identity manager does not have clear guarantees that that account
+ // cannot change in one atomic operation (without getting cleared in the
+ // mean-time).
+ virtual void OnUnconsentedPrimaryAccountChanged(
+ const CoreAccountInfo& unconsented_primary_account_info) {}
+
+ // Called when a new refresh token is associated with |account_info|.
+ // NOTE: On a signin event, the ordering of this callback wrt the
+ // OnPrimaryAccountSet() callback is undefined. If you as a client are
+ // interested in both callbacks, PrimaryAccountAccessTokenFetcher will
+ // likely meet your needs. Otherwise, if this lack of ordering is
+ // problematic for your use case, please contact blundell@chromium.org.
+ virtual void OnRefreshTokenUpdatedForAccount(
+ const CoreAccountInfo& account_info) {}
+
+ // Called when the refresh token previously associated with |account_id|
+ // has been removed. At the time that this callback is invoked, there is
+ // no longer guaranteed to be any AccountInfo associated with
+ // |account_id|.
+ // NOTE: It is not guaranteed that a call to
+ // OnRefreshTokenUpdatedForAccount() has previously occurred for this
+ // account due to corner cases.
+ // TODO(https://crbug.com/884731): Eliminate these corner cases.
+ // NOTE: On a signout event, the ordering of this callback wrt the
+ // OnPrimaryAccountCleared() callback is undefined.If this lack of ordering
+ // is problematic for your use case, please contact blundell@chromium.org.
+ virtual void OnRefreshTokenRemovedForAccount(
+ const CoreAccountId& account_id) {}
+
+ // Called when the error state of the refresh token for |account_id| has
+ // changed. Note: It is always called after
+ // |OnRefreshTokenUpdatedForAccount| when the refresh token is updated. It
+ // is not called when the refresh token is removed.
+ virtual void OnErrorStateOfRefreshTokenUpdatedForAccount(
+ const CoreAccountInfo& account_info,
+ const GoogleServiceAuthError& error) {}
+
+ // Called after refresh tokens are loaded.
+ virtual void OnRefreshTokensLoaded() {}
+
+ // Called whenever the list of Gaia accounts in the cookie jar has changed.
+ // |accounts_in_cookie_jar_info.accounts| is ordered by the order of the
+ // accounts in the cookie.
+ //
+ // This observer method is also called when fetching the list of accounts
+ // in Gaia cookies fails after a number of internal retries. In this case:
+ // * |error| hold the last error to fetch the list of accounts;
+ // * |accounts_in_cookie_jar_info.accounts_are_fresh| is set to false as
+ // the accounts information is considered stale;
+ // * |accounts_in_cookie_jar_info.accounts| holds the last list of known
+ // accounts in the cookie jar.
+ virtual void OnAccountsInCookieUpdated(
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+ const GoogleServiceAuthError& error) {}
+
+ // Called when the Gaia cookie has been deleted explicitly by a user
+ // action, e.g. from the settings or by an extension.
+ virtual void OnAccountsCookieDeletedByUserAction() {}
+
+ // Called after a batch of refresh token state chagnes is completed.
+ virtual void OnEndBatchOfRefreshTokenStateChanges() {}
+
+ // Called after an account is updated.
+ virtual void OnExtendedAccountInfoUpdated(const AccountInfo& info) {}
+
+ // Called after removing an account info.
+ virtual void OnExtendedAccountInfoRemoved(const AccountInfo& info) {}
+ };
+
+ // Methods to register or remove observers.
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
+ // Provides access to the core information of the user's primary account.
+ // Returns an empty struct if no such info is available, either because there
+ // is no primary account yet or because the user signed out.
+ CoreAccountInfo GetPrimaryAccountInfo() const;
+
+ // Provides access to the account ID of the user's primary account. Simple
+ // convenience wrapper over GetPrimaryAccountInfo().account_id.
+ CoreAccountId GetPrimaryAccountId() const;
+
+ // Returns whether the user's primary account is available.
+ bool HasPrimaryAccount() const;
+
+ // Provides access to the core information of the user's unconsented primary
+ // account (see ./README.md). Returns an empty info, if there is no such
+ // account.
+ CoreAccountInfo GetUnconsentedPrimaryAccountInfo() const;
+
+ // Provides access to the account ID of the user's unconsented primary
+ // account (see ./README.md). Returns an empty id if there is no such account.
+ CoreAccountId GetUnconsentedPrimaryAccountId() const;
+
+ // Returns whether the user's unconsented primary account (see ./README.md) is
+ // available.
+ bool HasUnconsentedPrimaryAccount() const;
+
+ // Creates an AccessTokenFetcher given the passed-in information.
+ std::unique_ptr<AccessTokenFetcher> CreateAccessTokenFetcherForAccount(
+ const CoreAccountId& account_id,
+ const std::string& oauth_consumer_name,
+ const identity::ScopeSet& scopes,
+ AccessTokenFetcher::TokenCallback callback,
+ AccessTokenFetcher::Mode mode) WARN_UNUSED_RESULT;
+
+ // Creates an AccessTokenFetcher given the passed-in information, allowing
+ // to specify a custom |url_loader_factory| as well.
+ std::unique_ptr<AccessTokenFetcher> CreateAccessTokenFetcherForAccount(
+ const CoreAccountId& account_id,
+ const std::string& oauth_consumer_name,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ const identity::ScopeSet& scopes,
+ AccessTokenFetcher::TokenCallback callback,
+ AccessTokenFetcher::Mode mode) WARN_UNUSED_RESULT;
+
+ // Creates an AccessTokenFetcher given the passed-in information, allowing to
+ // specify custom |client_id| and |client_secret| to identify the OAuth client
+ // app.
+ std::unique_ptr<AccessTokenFetcher> CreateAccessTokenFetcherForClient(
+ const CoreAccountId& account_id,
+ const std::string& client_id,
+ const std::string& client_secret,
+ const std::string& oauth_consumer_name,
+ const identity::ScopeSet& scopes,
+ AccessTokenFetcher::TokenCallback callback,
+ AccessTokenFetcher::Mode mode) WARN_UNUSED_RESULT;
+
+ // If an entry exists in the cache of access tokens corresponding to the
+ // given information, removes that entry; in this case, the next access token
+ // request for |account_id| and |scopes| will fetch a new token from the
+ // network. Otherwise, is a no-op.
+ void RemoveAccessTokenFromCache(const CoreAccountId& account_id,
+ const identity::ScopeSet& scopes,
+ const std::string& access_token);
+
+ // Provides the information of all accounts that have refresh tokens.
+ // NOTE: The accounts should not be assumed to be in any particular order; in
+ // particular, they are not guaranteed to be in the order in which the
+ // refresh tokens were added.
+ std::vector<CoreAccountInfo> GetAccountsWithRefreshTokens() const;
+
+ // Same functionality as GetAccountsWithRefreshTokens() but returning the
+ // extended account information.
+ std::vector<AccountInfo> GetExtendedAccountInfoForAccountsWithRefreshToken()
+ const;
+
+ // Returns true if (a) the primary account exists, and (b) a refresh token
+ // exists for the primary account.
+ bool HasPrimaryAccountWithRefreshToken() const;
+
+ // Returns true if a refresh token exists for |account_id|.
+ bool HasAccountWithRefreshToken(const CoreAccountId& account_id) const;
+
+ // Returns true if all refresh tokens have been loaded from disk.
+ bool AreRefreshTokensLoaded() const;
+
+ // Returns true if (a) a refresh token exists for |account_id|, and (b) the
+ // refresh token is in a persistent error state (defined as
+ // GoogleServiceAuthError::IsPersistentError() returning true for the error
+ // returned by GetErrorStateOfRefreshTokenForAccount(account_id)).
+ bool HasAccountWithRefreshTokenInPersistentErrorState(
+ const CoreAccountId& account_id) const;
+
+ // Returns the error state of the refresh token associated with |account_id|.
+ // In particular: Returns GoogleServiceAuthError::AuthErrorNone() if either
+ // (a) no refresh token exists for |account_id|, or (b) the refresh token is
+ // not in a persistent error state. Otherwise, returns the last persistent
+ // error that was detected when using the refresh token.
+ GoogleServiceAuthError GetErrorStateOfRefreshTokenForAccount(
+ const CoreAccountId& account_id) const;
+
+ // Returns extended information for account identified by |account_info|.
+ // The information will be returned if the information is available and
+ // refresh token is available for account.
+ base::Optional<AccountInfo> FindExtendedAccountInfoForAccount(
+ const CoreAccountInfo& account_info) const;
+
+ // Looks up and returns information for account with given |account_id|. If
+ // the account cannot be found, return an empty optional. This is equivalent
+ // to searching on the vector returned by GetAccountsWithRefreshTokens() but
+ // without allocating memory for the vector.
+ base::Optional<AccountInfo>
+ FindAccountInfoForAccountWithRefreshTokenByAccountId(
+ const CoreAccountId& account_id) const;
+
+ // Looks up and returns information for account with given |email_address|. If
+ // the account cannot be found, return an empty optional. This is equivalent
+ // to searching on the vector returned by GetAccountsWithRefreshTokens() but
+ // without allocating memory for the vector.
+ base::Optional<AccountInfo>
+ FindAccountInfoForAccountWithRefreshTokenByEmailAddress(
+ const std::string& email_address) const;
+
+ // Looks up and returns information for account with given |gaia_id|. If the
+ // account cannot be found, return an empty optional. This is equivalent to
+ // searching on the vector returned by GetAccountsWithRefreshTokens() but
+ // without allocating memory for the vector.
+ base::Optional<AccountInfo> FindAccountInfoForAccountWithRefreshTokenByGaiaId(
+ const std::string& gaia_id) const;
+
+ // Creates an UbertokenFetcher given the passed-in information, allowing
+ // to specify a custom |url_loader_factory| as well.
+ std::unique_ptr<UbertokenFetcher> CreateUbertokenFetcherForAccount(
+ const CoreAccountId& account_id,
+ UbertokenFetcher::CompletionCallback callback,
+ gaia::GaiaSource source,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ bool bound_to_channel_id = true);
+
+ // Provides the information of all accounts that are present in the Gaia
+ // cookie in the cookie jar, ordered by their order in the cookie.
+ // If the returned accounts are not fresh, an internal update will be
+ // triggered and there will be a subsequent invocation of
+ // IdentityManager::Observer::OnAccountsInCookieJarChanged().
+ AccountsInCookieJarInfo GetAccountsInCookieJar() const;
+
+ // Returns pointer to the object used to change the signed-in state of the
+ // primary account, if supported on the current platform. Otherwise, returns
+ // null.
+ PrimaryAccountMutator* GetPrimaryAccountMutator();
+
+ // Returns pointer to the object used to seed accounts and mutate state of
+ // accounts' refresh tokens, if supported on the current platform. Otherwise,
+ // returns null.
+ AccountsMutator* GetAccountsMutator();
+
+ // Returns pointer to the object used to manipulate the cookies stored and the
+ // accounts associated with them. Guaranteed to be non-null.
+ AccountsCookieMutator* GetAccountsCookieMutator();
+
+ // Returns pointer to the object used to seed accounts information from the
+ // device-level accounts. May be null if the system has no such notion.
+ DeviceAccountsSynchronizer* GetDeviceAccountsSynchronizer();
+
+ // Observer interface for classes that want to monitor status of various
+ // requests. Mostly useful in tests and debugging contexts (e.g., WebUI).
+ class DiagnosticsObserver {
+ public:
+ DiagnosticsObserver() = default;
+ virtual ~DiagnosticsObserver() = default;
+
+ DiagnosticsObserver(const DiagnosticsObserver&) = delete;
+ DiagnosticsObserver& operator=(const DiagnosticsObserver&) = delete;
+
+ // Called when receiving request for access token.
+ virtual void OnAccessTokenRequested(const CoreAccountId& account_id,
+ const std::string& consumer_id,
+ const identity::ScopeSet& scopes) {}
+
+ // Called when an access token request is completed. Contains diagnostic
+ // information about the access token request.
+ virtual void OnAccessTokenRequestCompleted(const CoreAccountId& account_id,
+ const std::string& consumer_id,
+ const identity::ScopeSet& scopes,
+ GoogleServiceAuthError error,
+ base::Time expiration_time) {}
+
+ // Called when an access token was removed.
+ virtual void OnAccessTokenRemovedFromCache(
+ const CoreAccountId& account_id,
+ const identity::ScopeSet& scopes) {}
+
+ // Called when a new refresh token is available. Contains diagnostic
+ // information about the source of the operation.
+ virtual void OnRefreshTokenUpdatedForAccountFromSource(
+ const CoreAccountId& account_id,
+ bool is_refresh_token_valid,
+ const std::string& source) {}
+
+ // Called when a refresh token is removed. Contains diagnostic information
+ // about the source that initiated the revokation operation.
+ virtual void OnRefreshTokenRemovedForAccountFromSource(
+ const CoreAccountId& account_id,
+ const std::string& source) {}
+ };
+
+ void AddDiagnosticsObserver(DiagnosticsObserver* observer);
+ void RemoveDiagnosticsObserver(DiagnosticsObserver* observer);
+
+ // **************************************************************************
+ // NOTE: All public methods methods below are either intended to be used only
+ // by signin code, or are slated for deletion. Most IdentityManager consumers
+ // should not need to interact with any methods below this line.
+ // **************************************************************************
+
+ IdentityManager(
+ std::unique_ptr<AccountTrackerService> account_tracker_service,
+ std::unique_ptr<ProfileOAuth2TokenService> token_service,
+ std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service,
+ std::unique_ptr<PrimaryAccountManager> primary_account_manager,
+ std::unique_ptr<AccountFetcherService> account_fetcher_service,
+ std::unique_ptr<PrimaryAccountMutator> primary_account_mutator,
+ std::unique_ptr<AccountsMutator> accounts_mutator,
+ std::unique_ptr<AccountsCookieMutator> accounts_cookie_mutator,
+ std::unique_ptr<DiagnosticsProvider> diagnostics_provider,
+ std::unique_ptr<DeviceAccountsSynchronizer> device_accounts_synchronizer);
+ ~IdentityManager() override;
+
+ // Performs initialization that is dependent on the network being
+ // initialized.
+ void OnNetworkInitialized();
+
+ // Returns |true| if migration of the account ID from normalized email is
+ // supported for the current platform.
+ static bool IsAccountIdMigrationSupported();
+
+ // Registers per-install prefs used by this class.
+ static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
+
+ // Registers per-profile prefs used by this class.
+ static void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
+ // Picks the correct account_id for the specified account depending on the
+ // migration state.
+ // TODO(https://crbug.com/883272): Remove once all platform have migrated to
+ // the new account_id based on gaia (currently, only Chrome OS remains).
+ CoreAccountId PickAccountIdForAccount(const std::string& gaia,
+ const std::string& email) const;
+
+ // Possible values for the account ID migration state, needs to be kept in
+ // sync with AccountTrackerService::AccountIdMigrationState.
+ enum AccountIdMigrationState {
+ MIGRATION_NOT_STARTED = 0,
+ MIGRATION_IN_PROGRESS = 1,
+ MIGRATION_DONE = 2,
+ NUM_MIGRATION_STATES
+ };
+
+ // Returns the currently saved state for the migration of accounts IDs.
+ AccountIdMigrationState GetAccountIdMigrationState() const;
+
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+ // Explicitly triggers the loading of accounts in the context of supervised
+ // users.
+ // TODO(https://crbug.com/860492): Remove this method when supervised users
+ // support is eliminated.
+ void DeprecatedLoadCredentialsForSupervisedUser(
+ const CoreAccountId& primary_account_id);
+#endif
+
+ // Returns pointer to the object used to obtain diagnostics about the internal
+ // state of IdentityManager.
+ DiagnosticsProvider* GetDiagnosticsProvider();
+
+#if defined(OS_IOS)
+ // Forces the processing of GaiaCookieManagerService::OnCookieChange. On
+ // iOS, it's necessary to force-trigger the processing of cookie changes
+ // from the client as the normal mechanism for internally observing them
+ // is not wired up.
+ // TODO(https://crbug.com/930582) : Remove the need to expose this method
+ // or move it to the network::CookieManager.
+ void ForceTriggerOnCookieChange();
+#endif
+
+#if defined(OS_ANDROID)
+ // Reloads the accounts in the token service from the system accounts. This
+ // API calls ProfileOAuth2TokenServiceDelegate::ReloadAccountsFromSystem and
+ // it triggers platform specific implementation for Android. NOTE: In normal
+ // usage, this method SHOULD NOT be called.
+ // TODO(https://crbug.com/930094): Eliminate the need to expose this.
+ void LegacyReloadAccountsFromSystem();
+
+ // Returns a pointer to the AccountTrackerService Java instance associated
+ // with this object.
+ // TODO(https://crbug.com/934688): Eliminate this method once
+ // AccountTrackerService.java has no more client usage.
+ base::android::ScopedJavaLocalRef<jobject>
+ LegacyGetAccountTrackerServiceJavaObject();
+
+ // Returns a pointer to the OAuth2TokenService Java instance associated
+ // with this object.
+ // TODO(https://crbug.com/934688): Eliminate this method once
+ // OAuth2TokenService.java has no more client usage.
+ base::android::ScopedJavaLocalRef<jobject>
+ LegacyGetOAuth2TokenServiceJavaObject();
+
+ // This method has the contractual assumption that the account is a known
+ // account and has as its semantics that it fetches the account info for the
+ // account, triggering an OnExtendedAccountInfoUpdated() callback if the info
+ // was successfully fetched.
+ void ForceRefreshOfExtendedAccountInfo(const CoreAccountId& account_id);
+#endif
+
+ private:
+ // These test helpers need to use some of the private methods below.
+ friend CoreAccountInfo SetPrimaryAccount(IdentityManager* identity_manager,
+ const std::string& email);
+ friend void SetRefreshTokenForPrimaryAccount(
+ IdentityManager* identity_manager,
+ const std::string& token_value);
+ friend void SetInvalidRefreshTokenForPrimaryAccount(
+ IdentityManager* identity_manager);
+ friend void RemoveRefreshTokenForPrimaryAccount(
+ IdentityManager* identity_manager);
+ friend AccountInfo MakePrimaryAccountAvailable(
+ IdentityManager* identity_manager,
+ const std::string& email);
+ friend void ClearPrimaryAccount(IdentityManager* identity_manager,
+ ClearPrimaryAccountPolicy policy);
+ friend AccountInfo MakeAccountAvailable(IdentityManager* identity_manager,
+ const std::string& email);
+ friend AccountInfo MakeAccountAvailableWithCookies(
+ IdentityManager* identity_manager,
+ network::TestURLLoaderFactory* test_url_loader_factory,
+ const std::string& email,
+ const std::string& gaia_id);
+ friend void SetRefreshTokenForAccount(IdentityManager* identity_manager,
+ const std::string& account_id,
+ const std::string& token_value);
+ friend void SetInvalidRefreshTokenForAccount(
+ IdentityManager* identity_manager,
+ const std::string& account_id);
+ friend void RemoveRefreshTokenForAccount(IdentityManager* identity_manager,
+ const std::string& account_id);
+ friend void UpdateAccountInfoForAccount(IdentityManager* identity_manager,
+ AccountInfo account_info);
+ friend void SetFreshnessOfAccountsInGaiaCookie(
+ IdentityManager* identity_manager,
+ bool accounts_are_fresh);
+ friend void UpdatePersistentErrorOfRefreshTokenForAccount(
+ IdentityManager* identity_manager,
+ const std::string& account_id,
+ const GoogleServiceAuthError& auth_error);
+
+ friend void DisableAccessTokenFetchRetries(IdentityManager* identity_manager);
+
+ friend void CancelAllOngoingGaiaCookieOperations(
+ IdentityManager* identity_manager);
+
+ friend void SetCookieAccounts(
+ IdentityManager* identity_manager,
+ network::TestURLLoaderFactory* test_url_loader_factory,
+ const std::vector<CookieParamsForTest>& cookie_accounts);
+
+ friend void SimulateSuccessfulFetchOfAccountInfo(
+ IdentityManager* identity_manager,
+ const std::string& account_id,
+ const std::string& email,
+ const std::string& gaia,
+ const std::string& hosted_domain,
+ const std::string& full_name,
+ const std::string& given_name,
+ const std::string& locale,
+ const std::string& picture_url);
+
+ // These friends are temporary during the conversion process.
+ // TODO(https://crbug.com/889902): Delete this when conversion is done.
+ friend SigninManagerAndroid;
+
+ // Temporary access to getters (e.g. GetTokenService()).
+ // TODO(https://crbug.com/944127): Remove this friendship by
+ // extending identity_test_utils.h as needed.
+ friend IdentityTestEnvironment;
+
+ // IdentityManagerTest reaches into IdentityManager internals in
+ // order to drive its behavior.
+ // TODO(https://crbug.com/943135): Find a better way to accomplish this.
+ friend IdentityManagerTest;
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest,
+ PrimaryAccountInfoAfterSigninAndAccountRemoval);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest,
+ PrimaryAccountInfoAfterSigninAndRefreshTokenRemoval);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest, RemoveAccessTokenFromCache);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest,
+ CreateAccessTokenFetcherWithCustomURLLoaderFactory);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest, ObserveAccessTokenFetch);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest,
+ ObserveAccessTokenRequestCompletionWithRefreshToken);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest,
+ BatchChangeObserversAreNotifiedOnCredentialsUpdate);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest, RemoveAccessTokenFromCache);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest,
+ CreateAccessTokenFetcherWithCustomURLLoaderFactory);
+ FRIEND_TEST_ALL_PREFIXES(
+ IdentityManagerTest,
+ CallbackSentOnUpdateToAccountsInCookieWithNoAccounts);
+ FRIEND_TEST_ALL_PREFIXES(
+ IdentityManagerTest,
+ CallbackSentOnUpdateToAccountsInCookieWithOneAccount);
+ FRIEND_TEST_ALL_PREFIXES(
+ IdentityManagerTest,
+ CallbackSentOnUpdateToAccountsInCookieWithTwoAccounts);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest,
+ CallbackSentOnUpdateToSignOutAccountsInCookie);
+ FRIEND_TEST_ALL_PREFIXES(
+ IdentityManagerTest,
+ CallbackSentOnUpdateToAccountsInCookieWithStaleAccounts);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest,
+ CallbackSentOnSuccessfulAdditionOfAccountToCookie);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest,
+ CallbackSentOnFailureAdditionOfAccountToCookie);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest,
+ CallbackSentOnSetAccountsInCookieCompleted_Success);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest,
+ CallbackSentOnSetAccountsInCookieCompleted_Failure);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest,
+ CallbackSentOnAccountsCookieDeletedByUserAction);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest, OnNetworkInitialized);
+ FRIEND_TEST_ALL_PREFIXES(IdentityManagerTest,
+ ForceRefreshOfExtendedAccountInfo);
+
+ // Private getters used for testing only (i.e. see identity_test_utils.h).
+ PrimaryAccountManager* GetPrimaryAccountManager();
+ ProfileOAuth2TokenService* GetTokenService();
+ AccountTrackerService* GetAccountTrackerService();
+ AccountFetcherService* GetAccountFetcherService();
+ GaiaCookieManagerService* GetGaiaCookieManagerService();
+
+ // Populates and returns an AccountInfo object corresponding to |account_id|,
+ // which must be an account with a refresh token.
+ AccountInfo GetAccountInfoForAccountWithRefreshToken(
+ const CoreAccountId& account_id) const;
+
+ // Sets primary account to |account_info| and updates the unconsented primary
+ // account.
+ void SetPrimaryAccountInternal(base::Optional<CoreAccountInfo> account_info);
+
+ // Updates the cached version of unconsented primary account and notifies the
+ // observers if there is any change.
+ void UpdateUnconsentedPrimaryAccount();
+
+ // Figures out and returns the current unconsented primary account based on
+ // current cookies.
+ base::Optional<CoreAccountInfo> ComputeUnconsentedPrimaryAccountInfo() const;
+
+ // PrimaryAccountManager callbacks:
+ void GoogleSigninSucceeded(const AccountInfo& account_info);
+ void GoogleSignedOut(const AccountInfo& account_info);
+ void AuthenticatedAccountSet(const AccountInfo& account_info);
+ void AuthenticatedAccountCleared();
+
+ // OAuth2TokenServiceObserver:
+ void OnRefreshTokenAvailable(const CoreAccountId& account_id) override;
+ void OnRefreshTokenRevoked(const CoreAccountId& account_id) override;
+ void OnRefreshTokensLoaded() override;
+ void OnEndBatchChanges() override;
+ void OnAuthErrorChanged(const CoreAccountId& account_id,
+ const GoogleServiceAuthError& auth_error) override;
+
+ // GaiaCookieManagerService callbacks:
+ void OnGaiaAccountsInCookieUpdated(
+ const std::vector<gaia::ListedAccount>& signed_in_accounts,
+ const std::vector<gaia::ListedAccount>& signed_out_accounts,
+ const GoogleServiceAuthError& error);
+ void OnGaiaCookieDeletedByUserAction();
+
+ // OAuth2AccessTokenManager::DiagnosticsObserver
+ void OnAccessTokenRequested(const CoreAccountId& account_id,
+ const std::string& consumer_id,
+ const identity::ScopeSet& scopes) override;
+ void OnFetchAccessTokenComplete(const CoreAccountId& account_id,
+ const std::string& consumer_id,
+ const identity::ScopeSet& scopes,
+ GoogleServiceAuthError error,
+ base::Time expiration_time) override;
+ void OnAccessTokenRemoved(const CoreAccountId& account_id,
+ const identity::ScopeSet& scopes) override;
+
+ // ProfileOAuth2TokenService callbacks:
+ void OnRefreshTokenAvailableFromSource(const CoreAccountId& account_id,
+ bool is_refresh_token_valid,
+ const std::string& source);
+ void OnRefreshTokenRevokedFromSource(const CoreAccountId& account_id,
+ const std::string& source);
+
+ // AccountTrackerService callbacks:
+ void OnAccountUpdated(const AccountInfo& info);
+ void OnAccountRemoved(const AccountInfo& info);
+
+ // Backing signin classes.
+ std::unique_ptr<AccountTrackerService> account_tracker_service_;
+ std::unique_ptr<ProfileOAuth2TokenService> token_service_;
+ std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service_;
+ std::unique_ptr<PrimaryAccountManager> primary_account_manager_;
+ std::unique_ptr<AccountFetcherService> account_fetcher_service_;
+
+ // PrimaryAccountMutator instance. May be null if mutation of the primary
+ // account state is not supported on the current platform.
+ std::unique_ptr<PrimaryAccountMutator> primary_account_mutator_;
+
+ // AccountsMutator instance. May be null if mutation of accounts is not
+ // supported on the current platform.
+ std::unique_ptr<AccountsMutator> accounts_mutator_;
+
+ // AccountsCookieMutator instance. Guaranteed to be non-null, as this
+ // functionality is supported on all platforms.
+ std::unique_ptr<AccountsCookieMutator> accounts_cookie_mutator_;
+
+ // DiagnosticsProvider instance.
+ std::unique_ptr<DiagnosticsProvider> diagnostics_provider_;
+
+ // DeviceAccountsSynchronizer instance.
+ std::unique_ptr<DeviceAccountsSynchronizer> device_accounts_synchronizer_;
+
+ // Lists of observers.
+ // Makes sure lists are empty on destruction.
+ base::ObserverList<Observer, true>::Unchecked observer_list_;
+ base::ObserverList<DiagnosticsObserver, true>::Unchecked
+ diagnostics_observer_list_;
+
+ // If |primary_account_| is set, it must equal |unconsented_primary_account_|.
+ base::Optional<CoreAccountInfo> primary_account_;
+ base::Optional<CoreAccountInfo> unconsented_primary_account_;
+
+ DISALLOW_COPY_AND_ASSIGN(IdentityManager);
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_MANAGER_H_
diff --git a/chromium/components/signin/public/identity_manager/identity_manager_builder.cc b/chromium/components/signin/public/identity_manager/identity_manager_builder.cc
new file mode 100644
index 00000000000..7dc60a28104
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/identity_manager_builder.cc
@@ -0,0 +1,173 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/identity_manager_builder.h"
+
+#include <string>
+#include <utility>
+
+#include "components/image_fetcher/core/image_decoder.h"
+#include "components/prefs/pref_service.h"
+#include "components/signin/internal/identity_manager/account_fetcher_service.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h"
+#include "components/signin/internal/identity_manager/diagnostics_provider_impl.h"
+#include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h"
+#include "components/signin/internal/identity_manager/primary_account_manager.h"
+#include "components/signin/internal/identity_manager/primary_account_mutator_impl.h"
+#include "components/signin/internal/identity_manager/primary_account_policy_manager.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_builder.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/base/signin_client.h"
+#include "components/signin/public/identity_manager/accounts_mutator.h"
+#include "components/signin/public/identity_manager/device_accounts_synchronizer.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+
+#if !defined(OS_ANDROID)
+#include "components/signin/public/webdata/token_web_data.h"
+#endif
+
+#if defined(OS_IOS)
+#include "components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h"
+#include "components/signin/public/identity_manager/ios/device_accounts_provider.h"
+#endif
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#include "components/signin/internal/identity_manager/accounts_mutator_impl.h"
+#endif
+
+#if !defined(OS_CHROMEOS)
+#include "components/signin/internal/identity_manager/primary_account_policy_manager_impl.h"
+#endif
+
+namespace signin {
+
+namespace {
+
+std::unique_ptr<AccountTrackerService> BuildAccountTrackerService(
+ PrefService* pref_service,
+ base::FilePath profile_path) {
+ auto account_tracker_service = std::make_unique<AccountTrackerService>();
+ account_tracker_service->Initialize(pref_service, profile_path);
+ return account_tracker_service;
+}
+
+std::unique_ptr<PrimaryAccountManager> BuildPrimaryAccountManager(
+ SigninClient* client,
+ AccountConsistencyMethod account_consistency,
+ AccountTrackerService* account_tracker_service,
+ ProfileOAuth2TokenService* token_service,
+ PrefService* local_state) {
+ std::unique_ptr<PrimaryAccountManager> primary_account_manager;
+ std::unique_ptr<PrimaryAccountPolicyManager> policy_manager;
+#if !defined(OS_CHROMEOS)
+ policy_manager = std::make_unique<PrimaryAccountPolicyManagerImpl>(client);
+#endif
+ primary_account_manager = std::make_unique<PrimaryAccountManager>(
+ client, token_service, account_tracker_service, account_consistency,
+ std::move(policy_manager));
+ primary_account_manager->Initialize(local_state);
+ return primary_account_manager;
+}
+
+std::unique_ptr<AccountsMutator> BuildAccountsMutator(
+ PrefService* prefs,
+ AccountTrackerService* account_tracker_service,
+ ProfileOAuth2TokenService* token_service,
+ PrimaryAccountManager* primary_account_manager) {
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ return std::make_unique<AccountsMutatorImpl>(
+ token_service, account_tracker_service, primary_account_manager, prefs);
+#else
+ return nullptr;
+#endif
+}
+
+std::unique_ptr<AccountFetcherService> BuildAccountFetcherService(
+ SigninClient* signin_client,
+ ProfileOAuth2TokenService* token_service,
+ AccountTrackerService* account_tracker_service,
+ std::unique_ptr<image_fetcher::ImageDecoder> image_decoder) {
+ auto account_fetcher_service = std::make_unique<AccountFetcherService>();
+ account_fetcher_service->Initialize(signin_client, token_service,
+ account_tracker_service,
+ std::move(image_decoder));
+ return account_fetcher_service;
+}
+
+} // anonymous namespace
+
+IdentityManagerBuildParams::IdentityManagerBuildParams() = default;
+
+IdentityManagerBuildParams::~IdentityManagerBuildParams() = default;
+
+std::unique_ptr<IdentityManager> BuildIdentityManager(
+ IdentityManagerBuildParams* params) {
+ std::unique_ptr<AccountTrackerService> account_tracker_service =
+ BuildAccountTrackerService(params->pref_service, params->profile_path);
+
+ std::unique_ptr<ProfileOAuth2TokenService> token_service =
+ BuildProfileOAuth2TokenService(
+ params->pref_service, account_tracker_service.get(),
+ params->network_connection_tracker, params->account_consistency,
+#if defined(OS_CHROMEOS)
+ params->account_manager, params->is_regular_profile,
+#endif
+#if !defined(OS_ANDROID)
+ params->delete_signin_cookies_on_exit, params->token_web_data,
+#endif
+#if defined(OS_IOS)
+ std::move(params->device_accounts_provider),
+#endif
+#if defined(OS_WIN)
+ params->reauth_callback,
+#endif
+ params->signin_client);
+
+ auto gaia_cookie_manager_service = std::make_unique<GaiaCookieManagerService>(
+ token_service.get(), params->signin_client);
+
+ std::unique_ptr<PrimaryAccountManager> primary_account_manager =
+ BuildPrimaryAccountManager(params->signin_client,
+ params->account_consistency,
+ account_tracker_service.get(),
+ token_service.get(), params->local_state);
+
+ auto primary_account_mutator = std::make_unique<PrimaryAccountMutatorImpl>(
+ account_tracker_service.get(), primary_account_manager.get(),
+ params->pref_service);
+
+ std::unique_ptr<AccountsMutator> accounts_mutator =
+ BuildAccountsMutator(params->pref_service, account_tracker_service.get(),
+ token_service.get(), primary_account_manager.get());
+
+ auto accounts_cookie_mutator = std::make_unique<AccountsCookieMutatorImpl>(
+ gaia_cookie_manager_service.get(), account_tracker_service.get());
+
+ auto diagnostics_provider = std::make_unique<DiagnosticsProviderImpl>(
+ token_service.get(), gaia_cookie_manager_service.get());
+
+ std::unique_ptr<AccountFetcherService> account_fetcher_service =
+ BuildAccountFetcherService(params->signin_client, token_service.get(),
+ account_tracker_service.get(),
+ std::move(params->image_decoder));
+
+ std::unique_ptr<DeviceAccountsSynchronizer> device_accounts_synchronizer;
+#if defined(OS_IOS)
+ device_accounts_synchronizer =
+ std::make_unique<DeviceAccountsSynchronizerImpl>(
+ token_service->GetDelegate());
+#endif
+
+ return std::make_unique<IdentityManager>(
+ std::move(account_tracker_service), std::move(token_service),
+ std::move(gaia_cookie_manager_service),
+ std::move(primary_account_manager), std::move(account_fetcher_service),
+ std::move(primary_account_mutator), std::move(accounts_mutator),
+ std::move(accounts_cookie_mutator), std::move(diagnostics_provider),
+ std::move(device_accounts_synchronizer));
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/identity_manager_builder.h b/chromium/components/signin/public/identity_manager/identity_manager_builder.h
new file mode 100644
index 00000000000..e9c6300f3f6
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/identity_manager_builder.h
@@ -0,0 +1,92 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_MANAGER_BUILDER_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_MANAGER_BUILDER_H_
+
+#include <memory>
+
+#include "base/files/file_path.h"
+#include "build/build_config.h"
+
+#if !defined(OS_ANDROID)
+#include "base/memory/scoped_refptr.h"
+#endif
+
+#if defined(OS_WIN)
+#include "base/callback.h"
+#endif
+
+class AccountTrackerService;
+class PrefService;
+class ProfileOAuth2TokenService;
+class SigninClient;
+
+#if !defined(OS_ANDROID)
+class TokenWebData;
+#endif
+
+#if defined(OS_IOS)
+class DeviceAccountsProvider;
+#endif
+
+namespace image_fetcher {
+class ImageDecoder;
+}
+
+namespace network {
+class NetworkConnectionTracker;
+}
+
+#if defined(OS_CHROMEOS)
+namespace chromeos {
+class AccountManager;
+}
+#endif
+
+namespace signin {
+enum class AccountConsistencyMethod;
+class IdentityManager;
+
+struct IdentityManagerBuildParams {
+ IdentityManagerBuildParams();
+ ~IdentityManagerBuildParams();
+
+ AccountConsistencyMethod account_consistency;
+ std::unique_ptr<AccountTrackerService> account_tracker_service;
+ std::unique_ptr<image_fetcher::ImageDecoder> image_decoder;
+ PrefService* local_state;
+ network::NetworkConnectionTracker* network_connection_tracker;
+ PrefService* pref_service;
+ base::FilePath profile_path;
+ SigninClient* signin_client;
+ std::unique_ptr<ProfileOAuth2TokenService> token_service;
+
+#if !defined(OS_ANDROID)
+ bool delete_signin_cookies_on_exit;
+ scoped_refptr<TokenWebData> token_web_data;
+#endif
+
+#if defined(OS_CHROMEOS)
+ chromeos::AccountManager* account_manager;
+ bool is_regular_profile;
+#endif
+
+#if defined(OS_IOS)
+ std::unique_ptr<DeviceAccountsProvider> device_accounts_provider;
+#endif
+
+#if defined(OS_WIN)
+ base::RepeatingCallback<bool()> reauth_callback;
+#endif
+};
+
+// Builds an IdentityManager instance from the supplied embedder-level
+// dependencies.
+std::unique_ptr<IdentityManager> BuildIdentityManager(
+ IdentityManagerBuildParams* params);
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_MANAGER_BUILDER_H_
diff --git a/chromium/components/signin/public/identity_manager/identity_manager_unittest.cc b/chromium/components/signin/public/identity_manager/identity_manager_unittest.cc
new file mode 100644
index 00000000000..6b44b400350
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/identity_manager_unittest.cc
@@ -0,0 +1,2290 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/identity_manager.h"
+
+#include <set>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/containers/flat_set.h"
+#include "base/run_loop.h"
+#include "base/stl_util.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "build/build_config.h"
+#include "components/image_fetcher/core/fake_image_decoder.h"
+#include "components/signin/internal/identity_manager/account_fetcher_service.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h"
+#include "components/signin/internal/identity_manager/diagnostics_provider_impl.h"
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h"
+#include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h"
+#include "components/signin/internal/identity_manager/primary_account_manager.h"
+#include "components/signin/internal/identity_manager/primary_account_policy_manager_impl.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/base/list_accounts_test_utils.h"
+#include "components/signin/public/base/signin_switches.h"
+#include "components/signin/public/base/test_signin_client.h"
+#include "components/signin/public/identity_manager/access_token_info.h"
+#include "components/signin/public/identity_manager/accounts_cookie_mutator.h"
+#include "components/signin/public/identity_manager/accounts_mutator.h"
+#include "components/signin/public/identity_manager/device_accounts_synchronizer.h"
+#include "components/signin/public/identity_manager/identity_test_utils.h"
+#include "components/signin/public/identity_manager/primary_account_mutator.h"
+#include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h"
+#include "components/signin/public/identity_manager/test_identity_manager_observer.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "google_apis/gaia/core_account_id.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_cookie_manager.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(OS_ANDROID)
+#include "components/signin/internal/identity_manager/child_account_info_fetcher_android.h"
+#endif
+
+namespace signin {
+namespace {
+
+const char kTestConsumerId[] = "dummy_consumer";
+const char kTestConsumerId2[] = "dummy_consumer 2";
+const char kTestGaiaId[] = "dummyId";
+const char kTestGaiaId2[] = "dummyId2";
+const char kTestGaiaId3[] = "dummyId3";
+const char kTestEmail[] = "me@gmail.com";
+const char kTestEmail2[] = "me2@gmail.com";
+const char kTestEmail3[] = "me3@gmail.com";
+
+const char kTestHostedDomain[] = "example.com";
+const char kTestFullName[] = "full_name";
+const char kTestGivenName[] = "given_name";
+const char kTestLocale[] = "locale";
+const char kTestPictureUrl[] = "http://picture.example.com/picture.jpg";
+
+#if defined(OS_CHROMEOS)
+const char kTestEmailWithPeriod[] = "m.e@gmail.com";
+#endif
+
+// Subclass of FakeOAuth2AccessTokenManager with bespoke behavior.
+class CustomFakeOAuth2AccessTokenManager : public FakeOAuth2AccessTokenManager {
+ public:
+ CustomFakeOAuth2AccessTokenManager(
+ OAuth2AccessTokenManager::Delegate* delegate)
+ : FakeOAuth2AccessTokenManager(delegate) {}
+
+ void set_on_access_token_invalidated_info(
+ CoreAccountId expected_account_id_to_invalidate,
+ std::set<std::string> expected_scopes_to_invalidate,
+ std::string expected_access_token_to_invalidate,
+ base::OnceClosure callback) {
+ expected_account_id_to_invalidate_ = expected_account_id_to_invalidate;
+ expected_scopes_to_invalidate_ = expected_scopes_to_invalidate;
+ expected_access_token_to_invalidate_ = expected_access_token_to_invalidate;
+ on_access_token_invalidated_callback_ = std::move(callback);
+ }
+
+ private:
+ friend class CustomFakeProfileOAuth2TokenService;
+ // OAuth2AccessTokenManager:
+ void InvalidateAccessTokenImpl(const CoreAccountId& account_id,
+ const std::string& client_id,
+ const identity::ScopeSet& scopes,
+ const std::string& access_token) override {
+ if (on_access_token_invalidated_callback_) {
+ EXPECT_EQ(expected_account_id_to_invalidate_, account_id);
+ EXPECT_EQ(expected_scopes_to_invalidate_, scopes);
+ EXPECT_EQ(expected_access_token_to_invalidate_, access_token);
+
+ // It should trigger OnAccessTokenRemovedFromCache from
+ // IdentityManager::DiagnosticsObserver.
+ for (auto& observer : GetDiagnosticsObserversForTesting())
+ observer.OnAccessTokenRemoved(account_id, scopes);
+
+ std::move(on_access_token_invalidated_callback_).Run();
+ }
+ }
+
+ CoreAccountId expected_account_id_to_invalidate_;
+ std::set<std::string> expected_scopes_to_invalidate_;
+ std::string expected_access_token_to_invalidate_;
+ base::OnceClosure on_access_token_invalidated_callback_;
+};
+
+// Subclass of FakeProfileOAuth2TokenService with bespoke behavior.
+class CustomFakeProfileOAuth2TokenService
+ : public FakeProfileOAuth2TokenService {
+ public:
+ CustomFakeProfileOAuth2TokenService(PrefService* user_prefs)
+ : FakeProfileOAuth2TokenService(user_prefs) {
+ OverrideAccessTokenManagerForTesting(
+ std::make_unique<CustomFakeOAuth2AccessTokenManager>(
+ this /* OAuth2AccessTokenManager::Delegate* */));
+ }
+
+ void set_on_access_token_invalidated_info(
+ CoreAccountId expected_account_id_to_invalidate,
+ std::set<std::string> expected_scopes_to_invalidate,
+ std::string expected_access_token_to_invalidate,
+ base::OnceClosure callback) {
+ GetCustomAccessTokenManager()->set_on_access_token_invalidated_info(
+ expected_account_id_to_invalidate, expected_scopes_to_invalidate,
+ expected_access_token_to_invalidate, std::move(callback));
+ }
+
+ private:
+ CustomFakeOAuth2AccessTokenManager* GetCustomAccessTokenManager() {
+ return static_cast<CustomFakeOAuth2AccessTokenManager*>(
+ GetAccessTokenManager());
+ }
+};
+
+class TestIdentityManagerDiagnosticsObserver
+ : IdentityManager::DiagnosticsObserver {
+ public:
+ explicit TestIdentityManagerDiagnosticsObserver(
+ IdentityManager* identity_manager)
+ : identity_manager_(identity_manager) {
+ identity_manager_->AddDiagnosticsObserver(this);
+ }
+ ~TestIdentityManagerDiagnosticsObserver() override {
+ identity_manager_->RemoveDiagnosticsObserver(this);
+ }
+
+ void set_on_access_token_requested_callback(base::OnceClosure callback) {
+ on_access_token_requested_callback_ = std::move(callback);
+ }
+
+ void set_on_access_token_request_completed_callback(
+ base::OnceClosure callback) {
+ on_access_token_request_completed_callback_ = std::move(callback);
+ }
+
+ const std::string& token_requestor_account_id() {
+ return token_requestor_account_id_;
+ }
+ const std::string& token_requestor_consumer_id() {
+ return token_requestor_consumer_id_;
+ }
+ const identity::ScopeSet& token_requestor_scopes() {
+ return token_requestor_scopes_;
+ }
+ const std::string& token_remover_account_id() {
+ return token_remover_account_id_;
+ }
+ const identity::ScopeSet& token_remover_scopes() {
+ return token_remover_scopes_;
+ }
+ const std::string& on_access_token_request_completed_account_id() {
+ return access_token_request_completed_account_id_;
+ }
+ const std::string& on_access_token_request_completed_consumer_id() {
+ return access_token_request_completed_consumer_id_;
+ }
+ const identity::ScopeSet& on_access_token_request_completed_scopes() {
+ return access_token_request_completed_scopes_;
+ }
+ const GoogleServiceAuthError& on_access_token_request_completed_error() {
+ return access_token_request_completed_error_;
+ }
+
+ private:
+ // IdentityManager::DiagnosticsObserver:
+ void OnAccessTokenRequested(const CoreAccountId& account_id,
+ const std::string& consumer_id,
+ const identity::ScopeSet& scopes) override {
+ token_requestor_account_id_ = account_id;
+ token_requestor_consumer_id_ = consumer_id;
+ token_requestor_scopes_ = scopes;
+
+ if (on_access_token_requested_callback_)
+ std::move(on_access_token_requested_callback_).Run();
+ }
+
+ void OnAccessTokenRemovedFromCache(
+ const CoreAccountId& account_id,
+ const identity::ScopeSet& scopes) override {
+ token_remover_account_id_ = account_id;
+ token_remover_scopes_ = scopes;
+ }
+
+ void OnAccessTokenRequestCompleted(const CoreAccountId& account_id,
+ const std::string& consumer_id,
+ const identity::ScopeSet& scopes,
+ GoogleServiceAuthError error,
+ base::Time expiration_time) override {
+ access_token_request_completed_account_id_ = account_id;
+ access_token_request_completed_consumer_id_ = consumer_id;
+ access_token_request_completed_scopes_ = scopes;
+ access_token_request_completed_error_ = error;
+
+ if (on_access_token_request_completed_callback_)
+ std::move(on_access_token_request_completed_callback_).Run();
+ }
+
+ IdentityManager* identity_manager_;
+ base::OnceClosure on_access_token_requested_callback_;
+ base::OnceClosure on_access_token_request_completed_callback_;
+ std::string token_requestor_account_id_;
+ std::string token_requestor_consumer_id_;
+ std::string token_remover_account_id_;
+ identity::ScopeSet token_requestor_scopes_;
+ identity::ScopeSet token_remover_scopes_;
+ std::string access_token_request_completed_account_id_;
+ std::string access_token_request_completed_consumer_id_;
+ identity::ScopeSet access_token_request_completed_scopes_;
+ GoogleServiceAuthError access_token_request_completed_error_;
+};
+
+} // namespace
+
+class IdentityManagerTest : public testing::Test {
+ protected:
+ IdentityManagerTest()
+ : signin_client_(&pref_service_, &test_url_loader_factory_) {
+ IdentityManager::RegisterProfilePrefs(pref_service_.registry());
+ IdentityManager::RegisterLocalStatePrefs(pref_service_.registry());
+
+ RecreateIdentityManager(
+ AccountConsistencyMethod::kDisabled,
+ PrimaryAccountManagerSetup::kWithAuthenticatedAccout);
+ }
+
+ ~IdentityManagerTest() override { signin_client_.Shutdown(); }
+
+ void SetUp() override {
+ primary_account_id_ =
+ identity_manager_->PickAccountIdForAccount(kTestGaiaId, kTestEmail);
+ }
+
+ IdentityManager* identity_manager() { return identity_manager_.get(); }
+
+ TestIdentityManagerObserver* identity_manager_observer() {
+ return identity_manager_observer_.get();
+ }
+
+ TestIdentityManagerDiagnosticsObserver*
+ identity_manager_diagnostics_observer() {
+ return identity_manager_diagnostics_observer_.get();
+ }
+
+ AccountTrackerService* account_tracker() {
+ return identity_manager()->GetAccountTrackerService();
+ }
+
+ CustomFakeProfileOAuth2TokenService* token_service() {
+ return static_cast<CustomFakeProfileOAuth2TokenService*>(
+ identity_manager()->GetTokenService());
+ }
+
+ // See RecreateIdentityManager.
+ enum class PrimaryAccountManagerSetup {
+ kWithAuthenticatedAccout,
+ kNoAuthenticatedAccount
+ };
+
+ // Used by some tests that need to re-instantiate IdentityManager after
+ // performing some other setup.
+ void RecreateIdentityManager() {
+ RecreateIdentityManager(
+ AccountConsistencyMethod::kDisabled,
+ PrimaryAccountManagerSetup::kNoAuthenticatedAccount);
+ }
+
+ // Recreates IdentityManager with given |account_consistency| and optionally
+ // seeds with an authenticated account depending on
+ // |primary_account_manager_setup|. This process destroys any existing
+ // IdentityManager and its dependencies, then remakes them. Dependencies that
+ // outlive PrimaryAccountManager (e.g. SigninClient) will be reused.
+ void RecreateIdentityManager(
+ AccountConsistencyMethod account_consistency,
+ PrimaryAccountManagerSetup primary_account_manager_setup) {
+ // Remove observers first, otherwise IdentityManager destruction might
+ // trigger a DCHECK because there are still living observers.
+ identity_manager_observer_.reset();
+ identity_manager_diagnostics_observer_.reset();
+ identity_manager_.reset();
+
+ auto token_service =
+ std::make_unique<CustomFakeProfileOAuth2TokenService>(&pref_service_);
+
+ auto gaia_cookie_manager_service =
+ std::make_unique<GaiaCookieManagerService>(token_service.get(),
+ &signin_client_);
+
+ auto account_tracker_service = std::make_unique<AccountTrackerService>();
+ account_tracker_service->Initialize(&pref_service_, base::FilePath());
+
+ auto account_fetcher_service = std::make_unique<AccountFetcherService>();
+ account_fetcher_service->Initialize(
+ &signin_client_, token_service.get(), account_tracker_service.get(),
+ std::make_unique<image_fetcher::FakeImageDecoder>());
+
+ DCHECK_EQ(account_consistency, AccountConsistencyMethod::kDisabled)
+ << "AccountConsistency is not used by PrimaryAccountManager";
+ std::unique_ptr<PrimaryAccountPolicyManager> policy_manager;
+#if !defined(OS_CHROMEOS)
+ policy_manager =
+ std::make_unique<PrimaryAccountPolicyManagerImpl>(&signin_client_);
+#endif
+ auto primary_account_manager = std::make_unique<PrimaryAccountManager>(
+ &signin_client_, token_service.get(), account_tracker_service.get(),
+ account_consistency, std::move(policy_manager));
+
+ // Passing this switch ensures that the new PrimaryAccountManager starts
+ // with a clean slate. Otherwise PrimaryAccountManager::Initialize will use
+ // the account id stored in prefs::kGoogleServicesAccountId.
+ base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+ cmd_line->AppendSwitch(switches::kClearTokenService);
+
+ primary_account_manager->Initialize(&pref_service_);
+
+ if (primary_account_manager_setup ==
+ PrimaryAccountManagerSetup::kWithAuthenticatedAccout) {
+ primary_account_manager->SetAuthenticatedAccountInfo(kTestGaiaId,
+ kTestEmail);
+ }
+
+ auto accounts_cookie_mutator = std::make_unique<AccountsCookieMutatorImpl>(
+ gaia_cookie_manager_service.get(), account_tracker_service.get());
+
+ auto diagnostics_provider = std::make_unique<DiagnosticsProviderImpl>(
+ token_service.get(), gaia_cookie_manager_service.get());
+
+ identity_manager_.reset(new IdentityManager(
+ std::move(account_tracker_service), std::move(token_service),
+ std::move(gaia_cookie_manager_service),
+ std::move(primary_account_manager), std::move(account_fetcher_service),
+ nullptr, nullptr, std::move(accounts_cookie_mutator),
+ std::move(diagnostics_provider), nullptr));
+ identity_manager_observer_.reset(
+ new TestIdentityManagerObserver(identity_manager_.get()));
+ identity_manager_diagnostics_observer_.reset(
+ new TestIdentityManagerDiagnosticsObserver(identity_manager_.get()));
+ }
+
+ void SimulateAdditionOfAccountToCookieSuccess(GaiaAuthConsumer* consumer,
+ const std::string& data) {
+ consumer->OnMergeSessionSuccess(data);
+ }
+
+ void SimulateAdditionOfAccountToCookieSuccessFailure(
+ GaiaAuthConsumer* consumer,
+ const GoogleServiceAuthError& error) {
+ consumer->OnMergeSessionFailure(error);
+ }
+
+ void SimulateCookieDeletedByUser(
+ network::mojom::CookieChangeListener* listener,
+ const net::CanonicalCookie& cookie) {
+ listener->OnCookieChange(cookie,
+ network::mojom::CookieChangeCause::EXPLICIT);
+ }
+
+ void SimulateOAuthMultiloginFinished(GaiaCookieManagerService* manager,
+ SetAccountsInCookieResult error) {
+ manager->OnSetAccountsFinished(error);
+ }
+
+ const CoreAccountId& primary_account_id() const {
+ return primary_account_id_;
+ }
+
+ TestSigninClient* signin_client() { return &signin_client_; }
+
+ network::TestURLLoaderFactory* test_url_loader_factory() {
+ return &test_url_loader_factory_;
+ }
+
+ private:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ sync_preferences::TestingPrefServiceSyncable pref_service_;
+ network::TestURLLoaderFactory test_url_loader_factory_;
+ TestSigninClient signin_client_;
+ std::unique_ptr<IdentityManager> identity_manager_;
+ std::unique_ptr<TestIdentityManagerObserver> identity_manager_observer_;
+ std::unique_ptr<TestIdentityManagerDiagnosticsObserver>
+ identity_manager_diagnostics_observer_;
+ CoreAccountId primary_account_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(IdentityManagerTest);
+};
+
+// Test that IdentityManager starts off with the information in
+// PrimaryAccountManager.
+TEST_F(IdentityManagerTest, PrimaryAccountInfoAtStartup) {
+ CoreAccountInfo primary_account_info =
+ identity_manager()->GetPrimaryAccountInfo();
+ EXPECT_EQ(kTestGaiaId, primary_account_info.gaia);
+ EXPECT_EQ(kTestEmail, primary_account_info.email);
+
+ // Primary account is by definition also unconsented primary account.
+ EXPECT_EQ(primary_account_info,
+ identity_manager()->GetUnconsentedPrimaryAccountInfo());
+ // There is no guarantee that this will be notified via callback on startup.
+}
+
+// Signin/signout tests aren't relevant and cannot build on ChromeOS, which
+// doesn't support signin/signout.
+#if !defined(OS_CHROMEOS)
+// Test that the user signing in results in firing of the IdentityManager
+// observer callback and the IdentityManager's state being updated.
+TEST_F(IdentityManagerTest, PrimaryAccountInfoAfterSignin) {
+ ClearPrimaryAccount(identity_manager(), ClearPrimaryAccountPolicy::DEFAULT);
+
+ SetPrimaryAccount(identity_manager(), kTestEmail);
+
+ CoreAccountInfo primary_account_from_set_callback =
+ identity_manager_observer()->PrimaryAccountFromSetCallback();
+ EXPECT_EQ(kTestGaiaId, primary_account_from_set_callback.gaia);
+ EXPECT_EQ(kTestEmail, primary_account_from_set_callback.email);
+
+ // Primary account is by definition also unconsented primary account.
+ EXPECT_EQ(
+ primary_account_from_set_callback,
+ identity_manager_observer()->UnconsentedPrimaryAccountFromCallback());
+
+ CoreAccountInfo primary_account_info =
+ identity_manager()->GetPrimaryAccountInfo();
+ EXPECT_EQ(kTestGaiaId, primary_account_info.gaia);
+ EXPECT_EQ(kTestEmail, primary_account_info.email);
+
+ EXPECT_EQ(primary_account_info,
+ identity_manager()->GetUnconsentedPrimaryAccountInfo());
+
+ CoreAccountId primary_account_id = identity_manager()->GetPrimaryAccountId();
+ EXPECT_EQ(primary_account_id, kTestGaiaId);
+ EXPECT_EQ(primary_account_id, primary_account_info.account_id);
+
+ EXPECT_EQ(primary_account_id,
+ identity_manager()->GetUnconsentedPrimaryAccountId());
+}
+
+// Test that the user signing out results in firing of the IdentityManager
+// observer callback and the IdentityManager's state being updated.
+TEST_F(IdentityManagerTest, PrimaryAccountInfoAfterSigninAndSignout) {
+ ClearPrimaryAccount(identity_manager(), ClearPrimaryAccountPolicy::DEFAULT);
+ // First ensure that the user is signed in from the POV of the
+ // IdentityManager.
+ SetPrimaryAccount(identity_manager(), kTestEmail);
+
+ // Sign the user out and check that the IdentityManager responds
+ // appropriately.
+ ClearPrimaryAccount(identity_manager(), ClearPrimaryAccountPolicy::DEFAULT);
+
+ CoreAccountInfo primary_account_from_cleared_callback =
+ identity_manager_observer()->PrimaryAccountFromClearedCallback();
+ EXPECT_EQ(kTestGaiaId, primary_account_from_cleared_callback.gaia);
+ EXPECT_EQ(kTestEmail, primary_account_from_cleared_callback.email);
+
+ // After the sign-out, there is no unconsented primary account.
+ EXPECT_TRUE(identity_manager_observer()
+ ->UnconsentedPrimaryAccountFromCallback()
+ .IsEmpty());
+
+ CoreAccountInfo primary_account_info =
+ identity_manager()->GetPrimaryAccountInfo();
+ EXPECT_EQ("", primary_account_info.gaia);
+ EXPECT_EQ("", primary_account_info.email);
+ EXPECT_EQ(primary_account_info,
+ identity_manager()->GetUnconsentedPrimaryAccountInfo());
+
+ CoreAccountId primary_account_id = identity_manager()->GetPrimaryAccountId();
+ EXPECT_EQ("", primary_account_id);
+ EXPECT_EQ(primary_account_id, primary_account_info.account_id);
+ EXPECT_EQ(primary_account_id,
+ identity_manager()->GetUnconsentedPrimaryAccountId());
+}
+
+// Test that the primary account's core info remains tracked by the
+// IdentityManager after signing in even after having removed the refresh token
+// without signing out.
+TEST_F(IdentityManagerTest,
+ PrimaryAccountInfoAfterSigninAndRefreshTokenRemoval) {
+ ClearPrimaryAccount(identity_manager(), ClearPrimaryAccountPolicy::DEFAULT);
+ // First ensure that the user is signed in from the POV of the
+ // IdentityManager.
+ SetPrimaryAccount(identity_manager(), kTestEmail);
+
+ identity_manager()->account_fetcher_service_->EnableAccountRemovalForTest();
+ // Revoke the primary's account credentials from the token service and
+ // check that the returned CoreAccountInfo is still valid since the
+ // identity_manager stores it.
+ token_service()->RevokeCredentials(identity_manager()->GetPrimaryAccountId());
+
+ CoreAccountInfo primary_account_info =
+ identity_manager()->GetPrimaryAccountInfo();
+ EXPECT_EQ(kTestGaiaId, primary_account_info.gaia);
+ EXPECT_EQ(kTestEmail, primary_account_info.email);
+ EXPECT_EQ(kTestGaiaId, primary_account_info.account_id);
+ EXPECT_EQ(primary_account_info,
+ identity_manager()->GetUnconsentedPrimaryAccountInfo());
+
+ CoreAccountId primary_account_id = identity_manager()->GetPrimaryAccountId();
+ EXPECT_EQ(primary_account_id, kTestGaiaId);
+ EXPECT_EQ(primary_account_id,
+ identity_manager()->GetUnconsentedPrimaryAccountId());
+}
+#endif // !defined(OS_CHROMEOS)
+
+TEST_F(IdentityManagerTest, HasPrimaryAccount) {
+ EXPECT_TRUE(identity_manager()->HasPrimaryAccount());
+ EXPECT_TRUE(identity_manager()->HasUnconsentedPrimaryAccount());
+
+ // Removing the account from the AccountTrackerService should not cause
+ // IdentityManager to think that there is no longer a primary account.
+ account_tracker()->RemoveAccount(identity_manager()->GetPrimaryAccountId());
+ EXPECT_TRUE(identity_manager()->HasPrimaryAccount());
+ EXPECT_TRUE(identity_manager()->HasUnconsentedPrimaryAccount());
+
+#if !defined(OS_CHROMEOS)
+ // Signing out should cause IdentityManager to recognize that there is no
+ // longer a primary account.
+ ClearPrimaryAccount(identity_manager(), ClearPrimaryAccountPolicy::DEFAULT);
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccount());
+ EXPECT_FALSE(identity_manager()->HasUnconsentedPrimaryAccount());
+#endif
+}
+
+TEST_F(IdentityManagerTest, GetAccountsInteractionWithPrimaryAccount) {
+ // Should not have any refresh tokens at initialization.
+ EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
+
+ // Add a refresh token for the primary account and check that it shows up in
+ // GetAccountsWithRefreshTokens().
+ SetRefreshTokenForPrimaryAccount(identity_manager());
+
+ std::vector<CoreAccountInfo> accounts_after_update =
+ identity_manager()->GetAccountsWithRefreshTokens();
+
+ EXPECT_EQ(1u, accounts_after_update.size());
+ EXPECT_EQ(accounts_after_update[0].account_id, primary_account_id());
+ EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId);
+ EXPECT_EQ(accounts_after_update[0].email, kTestEmail);
+
+ // Update the token and check that it doesn't change the state (or blow up).
+ SetRefreshTokenForPrimaryAccount(identity_manager());
+
+ std::vector<CoreAccountInfo> accounts_after_second_update =
+ identity_manager()->GetAccountsWithRefreshTokens();
+
+ EXPECT_EQ(1u, accounts_after_second_update.size());
+ EXPECT_EQ(accounts_after_second_update[0].account_id, primary_account_id());
+ EXPECT_EQ(accounts_after_second_update[0].gaia, kTestGaiaId);
+ EXPECT_EQ(accounts_after_second_update[0].email, kTestEmail);
+
+ // Remove the token for the primary account and check that this is likewise
+ // reflected.
+ RemoveRefreshTokenForPrimaryAccount(identity_manager());
+
+ EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
+}
+
+TEST_F(IdentityManagerTest,
+ QueryingOfRefreshTokensInteractionWithPrimaryAccount) {
+ CoreAccountInfo account_info = identity_manager()->GetPrimaryAccountInfo();
+
+ // Should not have a refresh token for the primary account at initialization.
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+
+ // Add a refresh token for the primary account and check that it affects this
+ // state.
+ SetRefreshTokenForPrimaryAccount(identity_manager());
+
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
+ EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+
+ // Update the token and check that it doesn't change the state (or blow up).
+ SetRefreshTokenForPrimaryAccount(identity_manager());
+
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
+ EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+
+ // Remove the token for the primary account and check that this is likewise
+ // reflected.
+ RemoveRefreshTokenForPrimaryAccount(identity_manager());
+
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+}
+
+TEST_F(IdentityManagerTest, QueryingOfRefreshTokensReflectsEmptyInitialState) {
+ CoreAccountInfo account_info = identity_manager()->GetPrimaryAccountInfo();
+ CoreAccountId account_id = account_info.account_id;
+
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+
+ SetRefreshTokenForPrimaryAccount(identity_manager());
+
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
+ EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+}
+
+TEST_F(IdentityManagerTest, GetAccountsInteractionWithSecondaryAccounts) {
+ // Should not have any refresh tokens at initialization.
+ EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
+
+ // Add a refresh token for a secondary account and check that it shows up in
+ // GetAccountsWithRefreshTokens().
+ account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
+ CoreAccountId account_id2 =
+ account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id;
+ SetRefreshTokenForAccount(identity_manager(), account_id2);
+
+ std::vector<CoreAccountInfo> accounts_after_update =
+ identity_manager()->GetAccountsWithRefreshTokens();
+
+ EXPECT_EQ(1u, accounts_after_update.size());
+ EXPECT_EQ(accounts_after_update[0].account_id, account_id2);
+ EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId2);
+ EXPECT_EQ(accounts_after_update[0].email, kTestEmail2);
+
+ // Add a refresh token for a different secondary account and check that it
+ // also shows up in GetAccountsWithRefreshTokens().
+ account_tracker()->SeedAccountInfo(kTestGaiaId3, kTestEmail3);
+ CoreAccountId account_id3 =
+ account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId3).account_id;
+ SetRefreshTokenForAccount(identity_manager(), account_id3);
+
+ std::vector<CoreAccountInfo> accounts_after_second_update =
+ identity_manager()->GetAccountsWithRefreshTokens();
+ EXPECT_EQ(2u, accounts_after_second_update.size());
+
+ for (CoreAccountInfo account_info : accounts_after_second_update) {
+ if (account_info.account_id == account_id2) {
+ EXPECT_EQ(account_info.gaia, kTestGaiaId2);
+ EXPECT_EQ(account_info.email, kTestEmail2);
+ } else {
+ EXPECT_EQ(account_info.gaia, kTestGaiaId3);
+ EXPECT_EQ(account_info.email, kTestEmail3);
+ }
+ }
+
+ // Remove the token for account2 and check that account3 is still present.
+ RemoveRefreshTokenForAccount(identity_manager(), account_id2);
+
+ std::vector<CoreAccountInfo> accounts_after_third_update =
+ identity_manager()->GetAccountsWithRefreshTokens();
+
+ EXPECT_EQ(1u, accounts_after_third_update.size());
+ EXPECT_EQ(accounts_after_third_update[0].account_id, account_id3);
+ EXPECT_EQ(accounts_after_third_update[0].gaia, kTestGaiaId3);
+ EXPECT_EQ(accounts_after_third_update[0].email, kTestEmail3);
+}
+
+TEST_F(IdentityManagerTest,
+ HasPrimaryAccountWithRefreshTokenInteractionWithSecondaryAccounts) {
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+
+ // Adding a refresh token for a secondary account shouldn't change anything
+ // about the primary account
+ account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
+ CoreAccountId account_id2 =
+ account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id;
+ SetRefreshTokenForAccount(identity_manager(), account_id2);
+
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+
+ // Adding a refresh token for a different secondary account should not do so
+ // either.
+ account_tracker()->SeedAccountInfo(kTestGaiaId3, kTestEmail3);
+ CoreAccountId account_id3 =
+ account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId3).account_id;
+ SetRefreshTokenForAccount(identity_manager(), account_id3);
+
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+
+ // Removing the token for account2 should have no effect.
+ RemoveRefreshTokenForAccount(identity_manager(), account_id2);
+
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+}
+
+TEST_F(IdentityManagerTest,
+ HasAccountWithRefreshTokenInteractionWithSecondaryAccounts) {
+ account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
+ AccountInfo account_info2 =
+ account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2);
+ CoreAccountId account_id2 = account_info2.account_id;
+
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
+
+ // Add a refresh token for account_info2 and check that this is reflected by
+ // HasAccountWithRefreshToken(.account_id).
+ SetRefreshTokenForAccount(identity_manager(), account_id2);
+
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
+
+ // Go through the same process for a different secondary account.
+ account_tracker()->SeedAccountInfo(kTestGaiaId3, kTestEmail3);
+ AccountInfo account_info3 =
+ account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId3);
+ CoreAccountId account_id3 = account_info3.account_id;
+
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshToken(account_info3.account_id));
+
+ SetRefreshTokenForAccount(identity_manager(), account_id3);
+
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshToken(account_info3.account_id));
+
+ // Remove the token for account2.
+ RemoveRefreshTokenForAccount(identity_manager(), account_id2);
+
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshToken(account_info3.account_id));
+}
+
+TEST_F(IdentityManagerTest,
+ GetAccountsInteractionBetweenPrimaryAndSecondaryAccounts) {
+ // Should not have any refresh tokens at initialization.
+ EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+
+ // Add a refresh token for a secondary account and check that it shows up in
+ // GetAccountsWithRefreshTokens().
+ account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
+ CoreAccountId account_id2 =
+ account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id;
+ SetRefreshTokenForAccount(identity_manager(), account_id2);
+
+ std::vector<CoreAccountInfo> accounts_after_update =
+ identity_manager()->GetAccountsWithRefreshTokens();
+
+ EXPECT_EQ(1u, accounts_after_update.size());
+ EXPECT_EQ(accounts_after_update[0].account_id, account_id2);
+ EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId2);
+ EXPECT_EQ(accounts_after_update[0].email, kTestEmail2);
+
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+
+ // The user still has a primary account.
+ EXPECT_EQ(identity_manager()->GetPrimaryAccountInfo().email, kTestEmail);
+ EXPECT_EQ(identity_manager()->GetUnconsentedPrimaryAccountInfo().email,
+ kTestEmail);
+
+ // Add a refresh token for the primary account and check that it
+ // also shows up in GetAccountsWithRefreshTokens().
+ SetRefreshTokenForPrimaryAccount(identity_manager());
+
+ std::vector<CoreAccountInfo> accounts_after_second_update =
+ identity_manager()->GetAccountsWithRefreshTokens();
+ EXPECT_EQ(2u, accounts_after_second_update.size());
+
+ for (const CoreAccountInfo& account_info : accounts_after_second_update) {
+ if (account_info.account_id == account_id2) {
+ EXPECT_EQ(account_info.gaia, kTestGaiaId2);
+ EXPECT_EQ(account_info.email, kTestEmail2);
+ } else {
+ EXPECT_EQ(account_info.gaia, kTestGaiaId);
+ EXPECT_EQ(account_info.email, kTestEmail);
+ }
+ }
+
+ EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+ EXPECT_EQ(identity_manager()->GetPrimaryAccountInfo().email, kTestEmail);
+ EXPECT_EQ(identity_manager()->GetUnconsentedPrimaryAccountInfo().email,
+ kTestEmail);
+
+ // Remove the token for the primary account and check that account2 is still
+ // present.
+ RemoveRefreshTokenForPrimaryAccount(identity_manager());
+
+ std::vector<CoreAccountInfo> accounts_after_third_update =
+ identity_manager()->GetAccountsWithRefreshTokens();
+
+ EXPECT_EQ(1u, accounts_after_third_update.size());
+ EXPECT_EQ(accounts_after_update[0].account_id, account_id2);
+ EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId2);
+ EXPECT_EQ(accounts_after_update[0].email, kTestEmail2);
+
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+ // The user still has a primary account.
+ EXPECT_EQ(identity_manager()->GetPrimaryAccountInfo().email, kTestEmail);
+ EXPECT_EQ(identity_manager()->GetUnconsentedPrimaryAccountInfo().email,
+ kTestEmail);
+}
+
+TEST_F(
+ IdentityManagerTest,
+ HasPrimaryAccountWithRefreshTokenInteractionBetweenPrimaryAndSecondaryAccounts) {
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+ EXPECT_TRUE(identity_manager()->HasUnconsentedPrimaryAccount());
+
+ // Add a refresh token for a secondary account and check that it doesn't
+ // impact the above state.
+ account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
+ CoreAccountId account_id2 =
+ account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id;
+ SetRefreshTokenForAccount(identity_manager(), account_id2);
+
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+ EXPECT_TRUE(identity_manager()->HasUnconsentedPrimaryAccount());
+
+ // Add a refresh token for the primary account and check that it
+ // *does* impact the stsate of HasPrimaryAccountWithRefreshToken().
+ SetRefreshTokenForPrimaryAccount(identity_manager());
+
+ EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+ EXPECT_TRUE(identity_manager()->HasUnconsentedPrimaryAccount());
+
+ // Remove the token for the secondary account and check that this doesn't flip
+ // the state.
+ RemoveRefreshTokenForAccount(identity_manager(), account_id2);
+
+ EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+ EXPECT_TRUE(identity_manager()->HasUnconsentedPrimaryAccount());
+
+ // Remove the token for the primary account and check that this flips the
+ // state.
+ RemoveRefreshTokenForPrimaryAccount(identity_manager());
+
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
+ EXPECT_TRUE(identity_manager()->HasUnconsentedPrimaryAccount());
+}
+
+TEST_F(
+ IdentityManagerTest,
+ HasAccountWithRefreshTokenInteractionBetweenPrimaryAndSecondaryAccounts) {
+ CoreAccountInfo primary_account_info =
+ identity_manager()->GetPrimaryAccountInfo();
+ CoreAccountId primary_account_id = primary_account_info.account_id;
+
+ account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
+ AccountInfo account_info2 =
+ account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2);
+ std::string account_id2 = account_info2.account_id;
+
+ EXPECT_FALSE(identity_manager()->HasAccountWithRefreshToken(
+ primary_account_info.account_id));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
+
+ // Add a refresh token for account_info2 and check that this is reflected by
+ // HasAccountWithRefreshToken(.account_id).
+ SetRefreshTokenForAccount(identity_manager(), account_id2);
+
+ EXPECT_FALSE(identity_manager()->HasAccountWithRefreshToken(
+ primary_account_info.account_id));
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
+
+ // Go through the same process for the primary account.
+ SetRefreshTokenForPrimaryAccount(identity_manager());
+
+ EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(
+ primary_account_info.account_id));
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
+
+ // Remove the token for account2.
+ RemoveRefreshTokenForAccount(identity_manager(), account_id2);
+
+ EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(
+ primary_account_info.account_id));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
+}
+
+TEST_F(IdentityManagerTest,
+ CallbackSentOnUpdateToErrorStateOfRefreshTokenForAccount) {
+ CoreAccountInfo primary_account_info =
+ identity_manager()->GetPrimaryAccountInfo();
+ CoreAccountId primary_account_id = primary_account_info.account_id;
+ SetRefreshTokenForPrimaryAccount(identity_manager());
+
+ account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
+ AccountInfo account_info2 =
+ account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2);
+ std::string account_id2 = account_info2.account_id;
+ SetRefreshTokenForAccount(identity_manager(), account_id2);
+
+ GoogleServiceAuthError user_not_signed_up_error =
+ GoogleServiceAuthError(GoogleServiceAuthError::State::USER_NOT_SIGNED_UP);
+ GoogleServiceAuthError invalid_gaia_credentials_error =
+ GoogleServiceAuthError(
+ GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS);
+ GoogleServiceAuthError transient_error = GoogleServiceAuthError(
+ GoogleServiceAuthError::State::SERVICE_UNAVAILABLE);
+
+ // Set a persistent error for |account_id2| and check that it's reflected.
+ token_service()->UpdateAuthErrorForTesting(account_id2,
+ user_not_signed_up_error);
+ EXPECT_EQ(account_id2,
+ identity_manager_observer()
+ ->AccountFromErrorStateOfRefreshTokenUpdatedCallback()
+ .account_id);
+ EXPECT_EQ(user_not_signed_up_error,
+ identity_manager_observer()
+ ->ErrorFromErrorStateOfRefreshTokenUpdatedCallback());
+
+ // A transient error should not cause a callback.
+ token_service()->UpdateAuthErrorForTesting(primary_account_id,
+ transient_error);
+ EXPECT_EQ(account_id2,
+ identity_manager_observer()
+ ->AccountFromErrorStateOfRefreshTokenUpdatedCallback()
+ .account_id);
+ EXPECT_EQ(user_not_signed_up_error,
+ identity_manager_observer()
+ ->ErrorFromErrorStateOfRefreshTokenUpdatedCallback());
+
+ // Set a different persistent error for the primary account and check that
+ // it's reflected.
+ token_service()->UpdateAuthErrorForTesting(primary_account_id,
+ invalid_gaia_credentials_error);
+ EXPECT_EQ(primary_account_id,
+ identity_manager_observer()
+ ->AccountFromErrorStateOfRefreshTokenUpdatedCallback()
+ .account_id);
+ EXPECT_EQ(invalid_gaia_credentials_error,
+ identity_manager_observer()
+ ->ErrorFromErrorStateOfRefreshTokenUpdatedCallback());
+}
+
+TEST_F(IdentityManagerTest, GetErrorStateOfRefreshTokenForAccount) {
+ CoreAccountInfo primary_account_info =
+ identity_manager()->GetPrimaryAccountInfo();
+ CoreAccountId primary_account_id = primary_account_info.account_id;
+
+ // A primary account without a refresh token should not be in an error
+ // state, and setting a refresh token should not affect that.
+ EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
+ identity_manager()->GetErrorStateOfRefreshTokenForAccount(
+ primary_account_id));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ primary_account_id));
+
+ SetRefreshTokenForPrimaryAccount(identity_manager());
+ EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
+ identity_manager()->GetErrorStateOfRefreshTokenForAccount(
+ primary_account_id));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ primary_account_id));
+
+ // A secondary account without a refresh token should not be in an error
+ // state, and setting a refresh token should not affect that.
+ account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
+ AccountInfo account_info2 =
+ account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2);
+ CoreAccountId account_id2 = account_info2.account_id;
+ EXPECT_EQ(
+ GoogleServiceAuthError::AuthErrorNone(),
+ identity_manager()->GetErrorStateOfRefreshTokenForAccount(account_id2));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ account_id2));
+
+ SetRefreshTokenForAccount(identity_manager(), account_id2);
+ EXPECT_EQ(
+ GoogleServiceAuthError::AuthErrorNone(),
+ identity_manager()->GetErrorStateOfRefreshTokenForAccount(account_id2));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ account_id2));
+
+ GoogleServiceAuthError user_not_signed_up_error =
+ GoogleServiceAuthError(GoogleServiceAuthError::State::USER_NOT_SIGNED_UP);
+ GoogleServiceAuthError invalid_gaia_credentials_error =
+ GoogleServiceAuthError(
+ GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS);
+ GoogleServiceAuthError transient_error = GoogleServiceAuthError(
+ GoogleServiceAuthError::State::SERVICE_UNAVAILABLE);
+
+ // Set a persistent error for |account_id2| and check that it's reflected.
+ token_service()->UpdateAuthErrorForTesting(account_id2,
+ user_not_signed_up_error);
+ EXPECT_EQ(
+ user_not_signed_up_error,
+ identity_manager()->GetErrorStateOfRefreshTokenForAccount(account_id2));
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ account_id2));
+ EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
+ identity_manager()->GetErrorStateOfRefreshTokenForAccount(
+ primary_account_id));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ primary_account_id));
+
+ // A transient error should cause no change in the error state.
+ token_service()->UpdateAuthErrorForTesting(primary_account_id,
+ transient_error);
+ EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
+ identity_manager()->GetErrorStateOfRefreshTokenForAccount(
+ primary_account_id));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ primary_account_id));
+
+ // Set a different persistent error for the primary account and check that
+ // it's reflected.
+ token_service()->UpdateAuthErrorForTesting(primary_account_id,
+ invalid_gaia_credentials_error);
+ EXPECT_EQ(
+ user_not_signed_up_error,
+ identity_manager()->GetErrorStateOfRefreshTokenForAccount(account_id2));
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ account_id2));
+ EXPECT_EQ(invalid_gaia_credentials_error,
+ identity_manager()->GetErrorStateOfRefreshTokenForAccount(
+ primary_account_id));
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ primary_account_id));
+
+ // Remove the token for account2 and check that it goes back to having no
+ // error.
+ RemoveRefreshTokenForAccount(identity_manager(), account_id2);
+ EXPECT_EQ(
+ GoogleServiceAuthError::AuthErrorNone(),
+ identity_manager()->GetErrorStateOfRefreshTokenForAccount(account_id2));
+ EXPECT_FALSE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ account_id2));
+ EXPECT_EQ(invalid_gaia_credentials_error,
+ identity_manager()->GetErrorStateOfRefreshTokenForAccount(
+ primary_account_id));
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ primary_account_id));
+}
+
+TEST_F(IdentityManagerTest, RemoveAccessTokenFromCache) {
+ std::set<std::string> scopes{"scope"};
+ std::string access_token = "access_token";
+
+ identity_manager()->GetPrimaryAccountManager()->SetAuthenticatedAccountInfo(
+ kTestGaiaId, kTestEmail);
+ token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
+
+ base::RunLoop run_loop;
+ token_service()->set_on_access_token_invalidated_info(
+ primary_account_id(), scopes, access_token, run_loop.QuitClosure());
+
+ identity_manager()->RemoveAccessTokenFromCache(primary_account_id(), scopes,
+ access_token);
+
+ run_loop.Run();
+
+ // RemoveAccessTokenFromCache should lead to OnAccessTokenRemovedFromCache
+ // from IdentityManager::DiagnosticsObserver.
+ EXPECT_EQ(
+ primary_account_id(),
+ identity_manager_diagnostics_observer()->token_remover_account_id());
+ EXPECT_EQ(scopes,
+ identity_manager_diagnostics_observer()->token_remover_scopes());
+}
+
+TEST_F(IdentityManagerTest, CreateAccessTokenFetcher) {
+ std::set<std::string> scopes{"scope"};
+ AccessTokenFetcher::TokenCallback callback = base::BindOnce(
+ [](GoogleServiceAuthError error, AccessTokenInfo access_token_info) {});
+ std::unique_ptr<AccessTokenFetcher> token_fetcher =
+ identity_manager()->CreateAccessTokenFetcherForAccount(
+ identity_manager()->GetPrimaryAccountId(), kTestConsumerId, scopes,
+ std::move(callback), AccessTokenFetcher::Mode::kImmediate);
+ EXPECT_TRUE(token_fetcher);
+}
+
+TEST_F(IdentityManagerTest,
+ CreateAccessTokenFetcherWithCustomURLLoaderFactory) {
+ base::RunLoop run_loop;
+ identity_manager_diagnostics_observer()
+ ->set_on_access_token_requested_callback(run_loop.QuitClosure());
+
+ identity_manager()->GetPrimaryAccountManager()->SetAuthenticatedAccountInfo(
+ kTestGaiaId, kTestEmail);
+ token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
+
+ std::set<std::string> scopes{"scope"};
+ AccessTokenFetcher::TokenCallback callback = base::BindOnce(
+ [](GoogleServiceAuthError error, AccessTokenInfo access_token_info) {});
+
+ // We first create and AccessTokenFetcher with a custom URLLoaderFactory,
+ // to check that such factory is actually used in the requests generated.
+ network::TestURLLoaderFactory test_url_loader_factory;
+ scoped_refptr<network::SharedURLLoaderFactory> test_shared_url_loader_factory(
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ &test_url_loader_factory));
+ std::unique_ptr<AccessTokenFetcher> token_fetcher =
+ identity_manager()->CreateAccessTokenFetcherForAccount(
+ primary_account_id(), kTestConsumerId, test_shared_url_loader_factory,
+ scopes, std::move(callback), AccessTokenFetcher::Mode::kImmediate);
+
+ run_loop.Run();
+
+ // The URLLoaderFactory present in the pending request should match
+ // the one we specified when creating the AccessTokenFetcher.
+ std::vector<FakeOAuth2AccessTokenManager::PendingRequest> pending_requests =
+ token_service()->GetPendingRequests();
+ EXPECT_EQ(pending_requests.size(), 1U);
+ EXPECT_EQ(pending_requests[0].url_loader_factory,
+ test_shared_url_loader_factory);
+
+ // The account ID and consumer's name should match the data passed as well.
+ EXPECT_EQ(
+ primary_account_id(),
+ identity_manager_diagnostics_observer()->token_requestor_account_id());
+ EXPECT_EQ(
+ kTestConsumerId,
+ identity_manager_diagnostics_observer()->token_requestor_consumer_id());
+
+ // Cancel the pending request in preparation to check that creating an
+ // AccessTokenFetcher without a custom factory works as expected as well.
+ token_service()->IssueErrorForAllPendingRequestsForAccount(
+ primary_account_id(),
+ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
+
+ // Now add a second account and request an access token for it to test
+ // that the default URLLoaderFactory is used if none is specified.
+ base::RunLoop run_loop2;
+ identity_manager_diagnostics_observer()
+ ->set_on_access_token_requested_callback(run_loop2.QuitClosure());
+
+ account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
+ CoreAccountId account_id2 =
+ account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id;
+ token_service()->UpdateCredentials(account_id2, "refresh_token");
+
+ // No changes to the declared scopes and callback, we can reuse them.
+ std::unique_ptr<AccessTokenFetcher> token_fetcher2 =
+ identity_manager()->CreateAccessTokenFetcherForAccount(
+ account_id2, kTestConsumerId2, scopes, std::move(callback),
+ AccessTokenFetcher::Mode::kImmediate);
+
+ run_loop2.Run();
+
+ // There should be one pending request now as well, just like before.
+ std::vector<FakeOAuth2AccessTokenManager::PendingRequest> pending_requests2 =
+ token_service()->GetPendingRequests();
+ EXPECT_EQ(pending_requests2.size(), 1U);
+
+ // The URLLoaderFactory present in the pending request should match
+ // the one created by default for the token service's delegate.
+ ProfileOAuth2TokenServiceDelegate* service_delegate =
+ token_service()->GetDelegate();
+ EXPECT_EQ(pending_requests2[0].url_loader_factory,
+ service_delegate->GetURLLoaderFactory());
+
+ // The account ID and consumer's name should match the data passed again.
+ EXPECT_EQ(
+ account_id2,
+ identity_manager_diagnostics_observer()->token_requestor_account_id());
+ EXPECT_EQ(
+ kTestConsumerId2,
+ identity_manager_diagnostics_observer()->token_requestor_consumer_id());
+}
+
+TEST_F(IdentityManagerTest, ObserveAccessTokenFetch) {
+ base::RunLoop run_loop;
+ identity_manager_diagnostics_observer()
+ ->set_on_access_token_requested_callback(run_loop.QuitClosure());
+
+ identity_manager()->GetPrimaryAccountManager()->SetAuthenticatedAccountInfo(
+ kTestGaiaId, kTestEmail);
+ token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
+
+ std::set<std::string> scopes{"scope"};
+ AccessTokenFetcher::TokenCallback callback = base::BindOnce(
+ [](GoogleServiceAuthError error, AccessTokenInfo access_token_info) {});
+ std::unique_ptr<AccessTokenFetcher> token_fetcher =
+ identity_manager()->CreateAccessTokenFetcherForAccount(
+ identity_manager()->GetPrimaryAccountId(), kTestConsumerId, scopes,
+ std::move(callback), AccessTokenFetcher::Mode::kImmediate);
+
+ run_loop.Run();
+
+ EXPECT_EQ(
+ primary_account_id(),
+ identity_manager_diagnostics_observer()->token_requestor_account_id());
+ EXPECT_EQ(
+ kTestConsumerId,
+ identity_manager_diagnostics_observer()->token_requestor_consumer_id());
+ EXPECT_EQ(scopes,
+ identity_manager_diagnostics_observer()->token_requestor_scopes());
+}
+
+TEST_F(IdentityManagerTest,
+ ObserveAccessTokenRequestCompletionWithoutRefreshToken) {
+ base::RunLoop run_loop;
+ identity_manager_diagnostics_observer()
+ ->set_on_access_token_request_completed_callback(run_loop.QuitClosure());
+
+ std::set<std::string> scopes{"scope"};
+ AccessTokenFetcher::TokenCallback callback = base::BindOnce(
+ [](GoogleServiceAuthError error, AccessTokenInfo access_token_info) {});
+ // Account has no refresh token.
+ std::unique_ptr<AccessTokenFetcher> token_fetcher =
+ identity_manager()->CreateAccessTokenFetcherForAccount(
+ identity_manager()->GetPrimaryAccountId(), kTestConsumerId, scopes,
+ std::move(callback), AccessTokenFetcher::Mode::kImmediate);
+
+ run_loop.Run();
+
+ EXPECT_TRUE(token_fetcher);
+ EXPECT_EQ(GoogleServiceAuthError(GoogleServiceAuthError::USER_NOT_SIGNED_UP),
+ identity_manager_diagnostics_observer()
+ ->on_access_token_request_completed_error());
+}
+
+TEST_F(IdentityManagerTest,
+ ObserveAccessTokenRequestCompletionWithRefreshToken) {
+ base::RunLoop run_loop;
+ identity_manager_diagnostics_observer()
+ ->set_on_access_token_request_completed_callback(run_loop.QuitClosure());
+
+ identity_manager()->GetPrimaryAccountManager()->SetAuthenticatedAccountInfo(
+ kTestGaiaId, kTestEmail);
+ token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
+ token_service()->set_auto_post_fetch_response_on_message_loop(true);
+
+ std::set<std::string> scopes{"scope"};
+ AccessTokenFetcher::TokenCallback callback = base::BindOnce(
+ [](GoogleServiceAuthError error, AccessTokenInfo access_token_info) {});
+ // This should result in a request for an access token without an error.
+ std::unique_ptr<AccessTokenFetcher> token_fetcher =
+ identity_manager()->CreateAccessTokenFetcherForAccount(
+ identity_manager()->GetPrimaryAccountId(), kTestConsumerId, scopes,
+ std::move(callback), AccessTokenFetcher::Mode::kImmediate);
+
+ run_loop.Run();
+
+ EXPECT_TRUE(token_fetcher);
+ EXPECT_EQ(primary_account_id(),
+ identity_manager_diagnostics_observer()
+ ->on_access_token_request_completed_account_id());
+ EXPECT_EQ(kTestConsumerId,
+ identity_manager_diagnostics_observer()
+ ->on_access_token_request_completed_consumer_id());
+ EXPECT_EQ(scopes, identity_manager_diagnostics_observer()
+ ->on_access_token_request_completed_scopes());
+ EXPECT_EQ(GoogleServiceAuthError(GoogleServiceAuthError::NONE),
+ identity_manager_diagnostics_observer()
+ ->on_access_token_request_completed_error());
+}
+
+TEST_F(IdentityManagerTest,
+ ObserveAccessTokenRequestCompletionAfterRevokingRefreshToken) {
+ base::RunLoop run_loop;
+ identity_manager_diagnostics_observer()
+ ->set_on_access_token_request_completed_callback(run_loop.QuitClosure());
+
+ account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
+ CoreAccountId account_id2 =
+ account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id;
+ token_service()->UpdateCredentials(account_id2, "refresh_token");
+
+ std::set<std::string> scopes{"scope"};
+ AccessTokenFetcher::TokenCallback callback = base::BindOnce(
+ [](GoogleServiceAuthError error, AccessTokenInfo access_token_info) {});
+ // This should result in a request for an access token.
+ std::unique_ptr<AccessTokenFetcher> token_fetcher =
+ identity_manager()->CreateAccessTokenFetcherForAccount(
+ account_id2, kTestConsumerId2, scopes, std::move(callback),
+ AccessTokenFetcher::Mode::kImmediate);
+
+ // Revoke the refresh token result cancelling access token request.
+ token_service()->RevokeCredentials(account_id2);
+
+ run_loop.Run();
+
+ EXPECT_TRUE(token_fetcher);
+ EXPECT_EQ(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
+ identity_manager_diagnostics_observer()
+ ->on_access_token_request_completed_error());
+}
+
+TEST_F(IdentityManagerTest, GetAccountsCookieMutator) {
+ AccountsCookieMutator* mutator =
+ identity_manager()->GetAccountsCookieMutator();
+ EXPECT_TRUE(mutator);
+}
+
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+// Tests that requesting a load of accounts results in the notification
+// firing that tokens were loaded.
+TEST_F(IdentityManagerTest, DeprecatedLoadCredentialsForSupervisedUser) {
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnRefreshTokensLoadedCallback(
+ run_loop.QuitClosure());
+
+ // Load the accounts and ensure that we see the resulting notification that
+ // they were loaded.
+ identity_manager()->DeprecatedLoadCredentialsForSupervisedUser("");
+ run_loop.Run();
+}
+#endif
+
+#if defined(OS_IOS)
+TEST_F(IdentityManagerTest, ForceTriggerOnCookieChange) {
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnAccountsInCookieUpdatedCallback(
+ run_loop.QuitClosure());
+
+ SetListAccountsResponseNoAccounts(test_url_loader_factory());
+ // Forces the processing of OnCookieChange and it calls
+ // OnGaiaAccountsInCookieUpdated.
+ identity_manager()->ForceTriggerOnCookieChange();
+ run_loop.Run();
+}
+#endif
+
+#if defined(OS_CHROMEOS)
+// On ChromeOS, AccountTrackerService first receives the normalized email
+// address from GAIA and then later has it updated with the user's
+// originally-specified version of their email address (at the time of that
+// address' creation). This latter will differ if the user's originally-
+// specified address was not in normalized form (e.g., if it contained
+// periods). This test simulates such a flow in order to verify that
+// IdentityManager correctly reflects the updated version. See crbug.com/842041
+// and crbug.com/842670 for further details.
+TEST_F(IdentityManagerTest, IdentityManagerReflectsUpdatedEmailAddress) {
+ CoreAccountInfo primary_account_info =
+ identity_manager()->GetPrimaryAccountInfo();
+ EXPECT_EQ(kTestGaiaId, primary_account_info.gaia);
+ EXPECT_EQ(kTestEmail, primary_account_info.email);
+
+ // Simulate the flow wherein the user's email address was updated
+ // to the originally-created non-normalized version.
+ SimulateSuccessfulFetchOfAccountInfo(
+ identity_manager(), primary_account_info.account_id, kTestEmailWithPeriod,
+ kTestGaiaId, kTestHostedDomain, kTestFullName, kTestGivenName,
+ kTestLocale, kTestPictureUrl);
+ // Verify that IdentityManager reflects the update.
+ primary_account_info = identity_manager()->GetPrimaryAccountInfo();
+ EXPECT_EQ(kTestGaiaId, primary_account_info.gaia);
+ EXPECT_EQ(kTestEmailWithPeriod, primary_account_info.email);
+ EXPECT_EQ(identity_manager()->GetUnconsentedPrimaryAccountInfo(),
+ primary_account_info);
+}
+#endif
+
+TEST_F(IdentityManagerTest,
+ CallbackSentOnPrimaryAccountRefreshTokenUpdateWithValidToken) {
+ SetRefreshTokenForPrimaryAccount(identity_manager());
+
+ CoreAccountInfo account_info =
+ identity_manager_observer()->AccountFromRefreshTokenUpdatedCallback();
+ EXPECT_EQ(kTestGaiaId, account_info.gaia);
+ EXPECT_EQ(kTestEmail, account_info.email);
+}
+
+TEST_F(IdentityManagerTest,
+ CallbackSentOnPrimaryAccountRefreshTokenUpdateWithInvalidToken) {
+ SetInvalidRefreshTokenForPrimaryAccount(identity_manager());
+
+ CoreAccountInfo account_info =
+ identity_manager_observer()->AccountFromRefreshTokenUpdatedCallback();
+ EXPECT_EQ(kTestGaiaId, account_info.gaia);
+ EXPECT_EQ(kTestEmail, account_info.email);
+}
+
+TEST_F(IdentityManagerTest, CallbackSentOnPrimaryAccountRefreshTokenRemoval) {
+ SetRefreshTokenForPrimaryAccount(identity_manager());
+
+ RemoveRefreshTokenForPrimaryAccount(identity_manager());
+
+ EXPECT_EQ(
+ primary_account_id(),
+ identity_manager_observer()->AccountIdFromRefreshTokenRemovedCallback());
+}
+
+TEST_F(IdentityManagerTest,
+ CallbackSentOnSecondaryAccountRefreshTokenUpdateWithValidToken) {
+ AccountInfo expected_account_info =
+ MakeAccountAvailable(identity_manager(), kTestEmail2);
+ EXPECT_EQ(kTestEmail2, expected_account_info.email);
+
+ CoreAccountInfo account_info =
+ identity_manager_observer()->AccountFromRefreshTokenUpdatedCallback();
+ EXPECT_EQ(expected_account_info.account_id, account_info.account_id);
+ EXPECT_EQ(expected_account_info.gaia, account_info.gaia);
+ EXPECT_EQ(expected_account_info.email, account_info.email);
+}
+
+TEST_F(IdentityManagerTest,
+ CallbackSentOnSecondaryAccountRefreshTokenUpdateWithInvalidToken) {
+ AccountInfo expected_account_info =
+ MakeAccountAvailable(identity_manager(), kTestEmail2);
+ EXPECT_EQ(kTestEmail2, expected_account_info.email);
+
+ SetInvalidRefreshTokenForAccount(identity_manager(),
+ expected_account_info.account_id);
+
+ CoreAccountInfo account_info =
+ identity_manager_observer()->AccountFromRefreshTokenUpdatedCallback();
+ EXPECT_EQ(expected_account_info.account_id, account_info.account_id);
+ EXPECT_EQ(expected_account_info.gaia, account_info.gaia);
+ EXPECT_EQ(expected_account_info.email, account_info.email);
+}
+
+TEST_F(IdentityManagerTest, CallbackSentOnSecondaryAccountRefreshTokenRemoval) {
+ AccountInfo expected_account_info =
+ MakeAccountAvailable(identity_manager(), kTestEmail2);
+ EXPECT_EQ(kTestEmail2, expected_account_info.email);
+
+ RemoveRefreshTokenForAccount(identity_manager(),
+ expected_account_info.account_id);
+
+ EXPECT_EQ(
+ expected_account_info.account_id,
+ identity_manager_observer()->AccountIdFromRefreshTokenRemovedCallback());
+}
+
+#if !defined(OS_CHROMEOS)
+TEST_F(
+ IdentityManagerTest,
+ CallbackSentOnSecondaryAccountRefreshTokenUpdateWithValidTokenWhenNoPrimaryAccount) {
+ ClearPrimaryAccount(identity_manager(), ClearPrimaryAccountPolicy::DEFAULT);
+
+ // Add an unconsented primary account, incl. proper cookies.
+ AccountInfo expected_account_info = MakeAccountAvailableWithCookies(
+ identity_manager(), test_url_loader_factory(), kTestEmail2, kTestGaiaId2);
+ EXPECT_EQ(kTestEmail2, expected_account_info.email);
+
+ CoreAccountInfo account_info =
+ identity_manager_observer()->AccountFromRefreshTokenUpdatedCallback();
+ EXPECT_EQ(expected_account_info.account_id, account_info.account_id);
+ EXPECT_EQ(expected_account_info.gaia, account_info.gaia);
+ EXPECT_EQ(expected_account_info.email, account_info.email);
+}
+
+TEST_F(
+ IdentityManagerTest,
+ CallbackSentOnSecondaryAccountRefreshTokenUpdateWithInvalidTokenWhenNoPrimaryAccount) {
+ ClearPrimaryAccount(identity_manager(), ClearPrimaryAccountPolicy::DEFAULT);
+
+ // Add an unconsented primary account, incl. proper cookies.
+ AccountInfo expected_account_info = MakeAccountAvailableWithCookies(
+ identity_manager(), test_url_loader_factory(), kTestEmail2, kTestGaiaId2);
+ EXPECT_EQ(kTestEmail2, expected_account_info.email);
+
+ SetInvalidRefreshTokenForAccount(identity_manager(),
+ expected_account_info.account_id);
+
+ CoreAccountInfo account_info =
+ identity_manager_observer()->AccountFromRefreshTokenUpdatedCallback();
+ EXPECT_EQ(expected_account_info.account_id, account_info.account_id);
+ EXPECT_EQ(expected_account_info.gaia, account_info.gaia);
+ EXPECT_EQ(expected_account_info.email, account_info.email);
+}
+
+TEST_F(IdentityManagerTest,
+ CallbackSentOnSecondaryAccountRefreshTokenRemovalWhenNoPrimaryAccount) {
+ ClearPrimaryAccount(identity_manager(), ClearPrimaryAccountPolicy::DEFAULT);
+
+ // Add an unconsented primary account, incl. proper cookies.
+ AccountInfo expected_account_info = MakeAccountAvailableWithCookies(
+ identity_manager(), test_url_loader_factory(), kTestEmail2, kTestGaiaId2);
+ EXPECT_EQ(kTestEmail2, expected_account_info.email);
+
+ RemoveRefreshTokenForAccount(identity_manager(),
+ expected_account_info.account_id);
+
+ EXPECT_EQ(
+ expected_account_info.account_id,
+ identity_manager_observer()->AccountIdFromRefreshTokenRemovedCallback());
+}
+#endif
+
+#if !defined(OS_CHROMEOS) && !defined(OS_IOS) && !defined(OS_ANDROID)
+TEST_F(
+ IdentityManagerTest,
+ UnconsentedPrimaryAccountCallbackSentOnSecondaryAccountRefreshTokenUpdateWithValidTokenWhenNoPrimaryAccount) {
+ ClearPrimaryAccount(identity_manager(), ClearPrimaryAccountPolicy::DEFAULT);
+
+ // Add an unconsented primary account, incl. proper cookies.
+ AccountInfo expected_account_info = MakeAccountAvailableWithCookies(
+ identity_manager(), test_url_loader_factory(), kTestEmail2, kTestGaiaId2);
+ EXPECT_EQ(kTestEmail2, expected_account_info.email);
+
+ EXPECT_EQ(identity_manager()->GetUnconsentedPrimaryAccountInfo(),
+ expected_account_info);
+ EXPECT_EQ(
+ identity_manager_observer()->UnconsentedPrimaryAccountFromCallback(),
+ expected_account_info);
+}
+
+TEST_F(
+ IdentityManagerTest,
+ UnconsentedPrimaryAccountCallbackSentOnSecondaryAccountRefreshTokenUpdateWithInvalidTokenWhenNoPrimaryAccount) {
+ ClearPrimaryAccount(identity_manager(), ClearPrimaryAccountPolicy::DEFAULT);
+
+ // Add an unconsented primary account, incl. proper cookies.
+ AccountInfo expected_account_info = MakeAccountAvailableWithCookies(
+ identity_manager(), test_url_loader_factory(), kTestEmail2, kTestGaiaId2);
+ EXPECT_EQ(kTestEmail2, expected_account_info.email);
+
+ SetInvalidRefreshTokenForAccount(identity_manager(),
+ expected_account_info.account_id);
+
+ // This is still an unconsented primary account, even with invalid refresh
+ // token.
+ EXPECT_EQ(identity_manager()->GetUnconsentedPrimaryAccountInfo(),
+ expected_account_info);
+ EXPECT_EQ(
+ identity_manager_observer()->UnconsentedPrimaryAccountFromCallback(),
+ expected_account_info);
+}
+
+TEST_F(
+ IdentityManagerTest,
+ UnconsentedPrimaryAccountCallbackSentOnSecondaryAccountRefreshTokenRemovalWhenNoPrimaryAccount) {
+ ClearPrimaryAccount(identity_manager(), ClearPrimaryAccountPolicy::DEFAULT);
+
+ // Add an unconsented primary account, incl. proper cookies.
+ AccountInfo expected_account_info = MakeAccountAvailableWithCookies(
+ identity_manager(), test_url_loader_factory(), kTestEmail2, kTestGaiaId2);
+ EXPECT_EQ(kTestEmail2, expected_account_info.email);
+
+ RemoveRefreshTokenForAccount(identity_manager(),
+ expected_account_info.account_id);
+
+ // With no refresh token, there is no unconsented primary account any more.
+ CoreAccountInfo empty_info;
+ EXPECT_FALSE(identity_manager()->HasUnconsentedPrimaryAccount());
+ EXPECT_EQ(
+ identity_manager_observer()->UnconsentedPrimaryAccountFromCallback(),
+ empty_info);
+ EXPECT_EQ(identity_manager()->GetUnconsentedPrimaryAccountInfo(), empty_info);
+}
+#endif
+
+TEST_F(IdentityManagerTest, CallbackSentOnRefreshTokenRemovalOfUnknownAccount) {
+ // When the token service is still loading credentials, it may send token
+ // revoked callbacks for accounts that it has never sent a token available
+ // callback. Our common test setup actually completes this loading, so use the
+ // *for_testing() method below to simulate the race condition and ensure that
+ // IdentityManager passes on the callback in this case.
+ token_service()->set_all_credentials_loaded_for_testing(false);
+
+ CoreAccountId dummy_account_id("dummy_account");
+
+ base::RunLoop run_loop;
+ token_service()->RevokeCredentials(dummy_account_id);
+ run_loop.RunUntilIdle();
+
+ EXPECT_EQ(
+ dummy_account_id,
+ identity_manager_observer()->AccountIdFromRefreshTokenRemovedCallback());
+}
+
+TEST_F(IdentityManagerTest, IdentityManagerGetsTokensLoadedEvent) {
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnRefreshTokensLoadedCallback(
+ run_loop.QuitClosure());
+
+ // Credentials are already loaded in PrimaryAccountManager::Initialize()
+ // which runs even before the IdentityManager is created. That's why
+ // we fake the credentials loaded state and force another load in
+ // order to be able to capture the TokensLoaded event.
+ token_service()->set_all_credentials_loaded_for_testing(false);
+ token_service()->LoadCredentials("");
+ run_loop.Run();
+}
+
+TEST_F(IdentityManagerTest,
+ CallbackSentOnUpdateToAccountsInCookieWithNoAccounts) {
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnAccountsInCookieUpdatedCallback(
+ run_loop.QuitClosure());
+
+ SetListAccountsResponseNoAccounts(test_url_loader_factory());
+ identity_manager()->GetGaiaCookieManagerService()->TriggerListAccounts();
+ run_loop.Run();
+
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar_info =
+ identity_manager_observer()
+ ->AccountsInfoFromAccountsInCookieUpdatedCallback();
+ EXPECT_TRUE(accounts_in_cookie_jar_info.accounts_are_fresh);
+ EXPECT_TRUE(accounts_in_cookie_jar_info.signed_in_accounts.empty());
+}
+
+TEST_F(IdentityManagerTest,
+ CallbackSentOnUpdateToAccountsInCookieWithOneAccount) {
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnAccountsInCookieUpdatedCallback(
+ run_loop.QuitClosure());
+
+ SetListAccountsResponseOneAccount(kTestEmail, kTestGaiaId,
+ test_url_loader_factory());
+ identity_manager()->GetGaiaCookieManagerService()->TriggerListAccounts();
+ run_loop.Run();
+
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar_info =
+ identity_manager_observer()
+ ->AccountsInfoFromAccountsInCookieUpdatedCallback();
+ EXPECT_TRUE(accounts_in_cookie_jar_info.accounts_are_fresh);
+ ASSERT_EQ(1u, accounts_in_cookie_jar_info.signed_in_accounts.size());
+ ASSERT_TRUE(accounts_in_cookie_jar_info.signed_out_accounts.empty());
+
+ gaia::ListedAccount listed_account =
+ accounts_in_cookie_jar_info.signed_in_accounts[0];
+ EXPECT_EQ(
+ identity_manager()->PickAccountIdForAccount(kTestGaiaId, kTestEmail),
+ listed_account.id);
+ EXPECT_EQ(kTestGaiaId, listed_account.gaia_id);
+ EXPECT_EQ(kTestEmail, listed_account.email);
+}
+
+TEST_F(IdentityManagerTest,
+ CallbackSentOnUpdateToAccountsInCookieWithTwoAccounts) {
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnAccountsInCookieUpdatedCallback(
+ run_loop.QuitClosure());
+
+ SetListAccountsResponseTwoAccounts(kTestEmail, kTestGaiaId, kTestEmail2,
+ kTestGaiaId2, test_url_loader_factory());
+ identity_manager()->GetGaiaCookieManagerService()->TriggerListAccounts();
+ run_loop.Run();
+
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar_info =
+ identity_manager_observer()
+ ->AccountsInfoFromAccountsInCookieUpdatedCallback();
+ EXPECT_TRUE(accounts_in_cookie_jar_info.accounts_are_fresh);
+ ASSERT_EQ(2u, accounts_in_cookie_jar_info.signed_in_accounts.size());
+ ASSERT_TRUE(accounts_in_cookie_jar_info.signed_out_accounts.empty());
+
+ // Verify not only that both accounts are present but that they are listed in
+ // the expected order as well.
+ gaia::ListedAccount listed_account1 =
+ accounts_in_cookie_jar_info.signed_in_accounts[0];
+ EXPECT_EQ(
+ identity_manager()->PickAccountIdForAccount(kTestGaiaId, kTestEmail),
+ listed_account1.id);
+ EXPECT_EQ(kTestGaiaId, listed_account1.gaia_id);
+ EXPECT_EQ(kTestEmail, listed_account1.email);
+
+ gaia::ListedAccount account_info2 =
+ accounts_in_cookie_jar_info.signed_in_accounts[1];
+ EXPECT_EQ(
+ identity_manager()->PickAccountIdForAccount(kTestGaiaId2, kTestEmail2),
+ account_info2.id);
+ EXPECT_EQ(kTestGaiaId2, account_info2.gaia_id);
+ EXPECT_EQ(kTestEmail2, account_info2.email);
+}
+
+TEST_F(IdentityManagerTest, CallbackSentOnUpdateToSignOutAccountsInCookie) {
+ struct SignedOutStatus {
+ int account_1;
+ int account_2;
+ } signed_out_status_set[] = {{0, 0}, {1, 0}, {0, 1}, {1, 1}};
+
+ for (const auto& signed_out_status : signed_out_status_set) {
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnAccountsInCookieUpdatedCallback(
+ run_loop.QuitClosure());
+
+ SetListAccountsResponseWithParams(
+ {{kTestEmail, kTestGaiaId, true /* valid */,
+ signed_out_status.account_1 /* signed_out */, true /* verified */},
+ {kTestEmail2, kTestGaiaId2, true /* valid */,
+ signed_out_status.account_2 /* signed_out */, true /* verified */}},
+ test_url_loader_factory());
+
+ identity_manager()->GetGaiaCookieManagerService()->TriggerListAccounts();
+ run_loop.Run();
+
+ unsigned int accounts_signed_out =
+ signed_out_status.account_1 + signed_out_status.account_2;
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar_info =
+ identity_manager_observer()
+ ->AccountsInfoFromAccountsInCookieUpdatedCallback();
+ EXPECT_TRUE(accounts_in_cookie_jar_info.accounts_are_fresh);
+ ASSERT_EQ(2 - accounts_signed_out,
+ accounts_in_cookie_jar_info.signed_in_accounts.size());
+ ASSERT_EQ(accounts_signed_out,
+ accounts_in_cookie_jar_info.signed_out_accounts.size());
+
+ // Verify not only that both accounts are present but that they are listed
+ // in the expected order as well.
+ //
+ // The two variables below, control the lookup indexes signed in and signed
+ // out accounts list, respectively.
+ int i = 0, j = 0;
+ gaia::ListedAccount listed_account1 =
+ signed_out_status.account_1
+ ? accounts_in_cookie_jar_info.signed_out_accounts[i++]
+ : accounts_in_cookie_jar_info.signed_in_accounts[j++];
+ if (!signed_out_status.account_1)
+ EXPECT_EQ(
+ identity_manager()->PickAccountIdForAccount(kTestGaiaId, kTestEmail),
+ listed_account1.id);
+ EXPECT_EQ(kTestGaiaId, listed_account1.gaia_id);
+ EXPECT_EQ(kTestEmail, listed_account1.email);
+
+ gaia::ListedAccount listed_account2 =
+ signed_out_status.account_2
+ ? accounts_in_cookie_jar_info.signed_out_accounts[i++]
+ : accounts_in_cookie_jar_info.signed_in_accounts[j++];
+ if (!signed_out_status.account_2)
+ EXPECT_EQ(identity_manager()->PickAccountIdForAccount(kTestGaiaId2,
+ kTestEmail2),
+ listed_account2.id);
+ EXPECT_EQ(kTestGaiaId2, listed_account2.gaia_id);
+ EXPECT_EQ(kTestEmail2, listed_account2.email);
+ }
+}
+
+TEST_F(IdentityManagerTest,
+ CallbackSentOnUpdateToAccountsInCookieWithStaleAccounts) {
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnAccountsInCookieUpdatedCallback(
+ run_loop.QuitClosure());
+
+ // Configure list accounts to return a permanent Gaia auth error.
+ SetListAccountsResponseWithUnexpectedServiceResponse(
+ test_url_loader_factory());
+ identity_manager()->GetGaiaCookieManagerService()->TriggerListAccounts();
+ run_loop.Run();
+
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar_info =
+ identity_manager_observer()
+ ->AccountsInfoFromAccountsInCookieUpdatedCallback();
+ EXPECT_FALSE(accounts_in_cookie_jar_info.accounts_are_fresh);
+ EXPECT_TRUE(accounts_in_cookie_jar_info.signed_in_accounts.empty());
+ EXPECT_TRUE(accounts_in_cookie_jar_info.signed_out_accounts.empty());
+}
+
+TEST_F(IdentityManagerTest, GetAccountsInCookieJarWithNoAccounts) {
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnAccountsInCookieUpdatedCallback(
+ run_loop.QuitClosure());
+
+ SetListAccountsResponseNoAccounts(test_url_loader_factory());
+
+ // Do an initial call to GetAccountsInCookieJar(). This call should return no
+ // accounts but should also trigger an internal update and eventual
+ // notification that the accounts in the cookie jar have been updated.
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar =
+ identity_manager()->GetAccountsInCookieJar();
+ EXPECT_FALSE(accounts_in_cookie_jar.accounts_are_fresh);
+ EXPECT_TRUE(accounts_in_cookie_jar.signed_in_accounts.empty());
+ EXPECT_TRUE(accounts_in_cookie_jar.signed_out_accounts.empty());
+
+ run_loop.Run();
+
+ // The state of the accounts in IdentityManager should now reflect the
+ // internal update.
+ const AccountsInCookieJarInfo updated_accounts_in_cookie_jar =
+ identity_manager()->GetAccountsInCookieJar();
+
+ EXPECT_TRUE(updated_accounts_in_cookie_jar.accounts_are_fresh);
+ EXPECT_TRUE(updated_accounts_in_cookie_jar.signed_in_accounts.empty());
+ EXPECT_TRUE(updated_accounts_in_cookie_jar.signed_out_accounts.empty());
+}
+
+TEST_F(IdentityManagerTest, GetAccountsInCookieJarWithOneAccount) {
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnAccountsInCookieUpdatedCallback(
+ run_loop.QuitClosure());
+
+ SetListAccountsResponseOneAccount(kTestEmail, kTestGaiaId,
+ test_url_loader_factory());
+
+ // Do an initial call to GetAccountsInCookieJar(). This call should return no
+ // accounts but should also trigger an internal update and eventual
+ // notification that the accounts in the cookie jar have been updated.
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar =
+ identity_manager()->GetAccountsInCookieJar();
+ EXPECT_FALSE(accounts_in_cookie_jar.accounts_are_fresh);
+ EXPECT_TRUE(accounts_in_cookie_jar.signed_in_accounts.empty());
+ EXPECT_TRUE(accounts_in_cookie_jar.signed_out_accounts.empty());
+
+ run_loop.Run();
+
+ // The state of the accounts in IdentityManager should now reflect the
+ // internal update.
+ const AccountsInCookieJarInfo& updated_accounts_in_cookie_jar =
+ identity_manager()->GetAccountsInCookieJar();
+
+ EXPECT_TRUE(updated_accounts_in_cookie_jar.accounts_are_fresh);
+ ASSERT_EQ(1u, updated_accounts_in_cookie_jar.signed_in_accounts.size());
+ ASSERT_TRUE(updated_accounts_in_cookie_jar.signed_out_accounts.empty());
+
+ gaia::ListedAccount listed_account =
+ updated_accounts_in_cookie_jar.signed_in_accounts[0];
+ EXPECT_EQ(
+ identity_manager()->PickAccountIdForAccount(kTestGaiaId, kTestEmail),
+ listed_account.id);
+ EXPECT_EQ(kTestGaiaId, listed_account.gaia_id);
+ EXPECT_EQ(kTestEmail, listed_account.email);
+}
+
+TEST_F(IdentityManagerTest, GetAccountsInCookieJarWithTwoAccounts) {
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnAccountsInCookieUpdatedCallback(
+ run_loop.QuitClosure());
+
+ SetListAccountsResponseTwoAccounts(kTestEmail, kTestGaiaId, kTestEmail2,
+ kTestGaiaId2, test_url_loader_factory());
+
+ // Do an initial call to GetAccountsInCookieJar(). This call should return no
+ // accounts but should also trigger an internal update and eventual
+ // notification that the accounts in the cookie jar have been updated.
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar =
+ identity_manager()->GetAccountsInCookieJar();
+ EXPECT_FALSE(accounts_in_cookie_jar.accounts_are_fresh);
+ EXPECT_TRUE(accounts_in_cookie_jar.signed_in_accounts.empty());
+ EXPECT_TRUE(accounts_in_cookie_jar.signed_out_accounts.empty());
+
+ run_loop.Run();
+
+ // The state of the accounts in IdentityManager should now reflect the
+ // internal update.
+ const AccountsInCookieJarInfo& updated_accounts_in_cookie_jar =
+ identity_manager()->GetAccountsInCookieJar();
+
+ EXPECT_TRUE(updated_accounts_in_cookie_jar.accounts_are_fresh);
+ ASSERT_EQ(2u, updated_accounts_in_cookie_jar.signed_in_accounts.size());
+ ASSERT_TRUE(updated_accounts_in_cookie_jar.signed_out_accounts.empty());
+
+ // Verify not only that both accounts are present but that they are listed in
+ // the expected order as well.
+ gaia::ListedAccount listed_account1 =
+ updated_accounts_in_cookie_jar.signed_in_accounts[0];
+ EXPECT_EQ(
+ identity_manager()->PickAccountIdForAccount(kTestGaiaId, kTestEmail),
+ listed_account1.id);
+ EXPECT_EQ(kTestGaiaId, listed_account1.gaia_id);
+ EXPECT_EQ(kTestEmail, listed_account1.email);
+
+ gaia::ListedAccount listed_account2 =
+ updated_accounts_in_cookie_jar.signed_in_accounts[1];
+ EXPECT_EQ(
+ identity_manager()->PickAccountIdForAccount(kTestGaiaId2, kTestEmail2),
+ listed_account2.id);
+ EXPECT_EQ(kTestGaiaId2, listed_account2.gaia_id);
+ EXPECT_EQ(kTestEmail2, listed_account2.email);
+}
+
+TEST_F(IdentityManagerTest, CallbackSentOnSuccessfulAdditionOfAccountToCookie) {
+ const char kTestAccountId[] = "account_id";
+
+ std::string account_from_add_account_to_cookie_completed_callback;
+ GoogleServiceAuthError error_from_add_account_to_cookie_completed_callback;
+ auto completion_callback =
+ base::BindLambdaForTesting([&](const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error) {
+ account_from_add_account_to_cookie_completed_callback = account_id;
+ error_from_add_account_to_cookie_completed_callback = error;
+ });
+
+ identity_manager()->GetGaiaCookieManagerService()->AddAccountToCookie(
+ kTestAccountId, gaia::GaiaSource::kChrome,
+ std::move(completion_callback));
+ SimulateAdditionOfAccountToCookieSuccess(
+ identity_manager()->GetGaiaCookieManagerService(), "token");
+ EXPECT_EQ(account_from_add_account_to_cookie_completed_callback,
+ kTestAccountId);
+ EXPECT_EQ(error_from_add_account_to_cookie_completed_callback,
+ GoogleServiceAuthError::AuthErrorNone());
+}
+
+TEST_F(IdentityManagerTest, CallbackSentOnFailureAdditionOfAccountToCookie) {
+ const char kTestAccountId[] = "account_id";
+
+ std::string account_from_add_account_to_cookie_completed_callback;
+ GoogleServiceAuthError error_from_add_account_to_cookie_completed_callback;
+ auto completion_callback =
+ base::BindLambdaForTesting([&](const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error) {
+ account_from_add_account_to_cookie_completed_callback = account_id;
+ error_from_add_account_to_cookie_completed_callback = error;
+ });
+
+ identity_manager()->GetGaiaCookieManagerService()->AddAccountToCookie(
+ kTestAccountId, gaia::GaiaSource::kChrome,
+ std::move(completion_callback));
+
+ GoogleServiceAuthError error(GoogleServiceAuthError::SERVICE_ERROR);
+ SimulateAdditionOfAccountToCookieSuccessFailure(
+ identity_manager()->GetGaiaCookieManagerService(), error);
+
+ EXPECT_EQ(account_from_add_account_to_cookie_completed_callback,
+ kTestAccountId);
+ EXPECT_EQ(error_from_add_account_to_cookie_completed_callback, error);
+}
+
+TEST_F(IdentityManagerTest,
+ CallbackSentOnSetAccountsInCookieCompleted_Success) {
+ const CoreAccountId kTestAccountId("account_id");
+ const CoreAccountId kTestAccountId2("account_id2");
+ const std::vector<std::pair<CoreAccountId, std::string>> accounts = {
+ {kTestAccountId, kTestAccountId.id},
+ {kTestAccountId2, kTestAccountId2.id}};
+
+ SetAccountsInCookieResult
+ error_from_set_accounts_in_cookie_completed_callback;
+ auto completion_callback = base::BindLambdaForTesting(
+ [&error_from_set_accounts_in_cookie_completed_callback](
+ SetAccountsInCookieResult error) {
+ error_from_set_accounts_in_cookie_completed_callback = error;
+ });
+
+ // Needed to insert request in the queue.
+ identity_manager()->GetGaiaCookieManagerService()->SetAccountsInCookie(
+ accounts, gaia::GaiaSource::kChrome, std::move(completion_callback));
+
+ SimulateOAuthMultiloginFinished(
+ identity_manager()->GetGaiaCookieManagerService(),
+ SetAccountsInCookieResult::kSuccess);
+
+ EXPECT_EQ(error_from_set_accounts_in_cookie_completed_callback,
+ SetAccountsInCookieResult::kSuccess);
+}
+
+TEST_F(IdentityManagerTest,
+ CallbackSentOnSetAccountsInCookieCompleted_Failure) {
+ const CoreAccountId kTestAccountId("account_id");
+ const CoreAccountId kTestAccountId2("account_id2");
+ const std::vector<std::pair<CoreAccountId, std::string>> accounts = {
+ {kTestAccountId, kTestAccountId.id},
+ {kTestAccountId2, kTestAccountId2.id}};
+
+ SetAccountsInCookieResult
+ error_from_set_accounts_in_cookie_completed_callback;
+ auto completion_callback = base::BindLambdaForTesting(
+ [&error_from_set_accounts_in_cookie_completed_callback](
+ SetAccountsInCookieResult error) {
+ error_from_set_accounts_in_cookie_completed_callback = error;
+ });
+
+ // Needed to insert request in the queue.
+ identity_manager()->GetGaiaCookieManagerService()->SetAccountsInCookie(
+ accounts, gaia::GaiaSource::kChrome, std::move(completion_callback));
+
+ // Sample an erroneous response.
+ SetAccountsInCookieResult error = SetAccountsInCookieResult::kPersistentError;
+
+ SimulateOAuthMultiloginFinished(
+ identity_manager()->GetGaiaCookieManagerService(), error);
+
+ EXPECT_EQ(error_from_set_accounts_in_cookie_completed_callback, error);
+}
+
+TEST_F(IdentityManagerTest, CallbackSentOnAccountsCookieDeletedByUserAction) {
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnCookieDeletedByUserCallback(
+ run_loop.QuitClosure());
+ net::CanonicalCookie cookie("APISID", std::string(), ".google.com", "/",
+ base::Time(), base::Time(), base::Time(), false,
+ false, net::CookieSameSite::NO_RESTRICTION,
+ net::COOKIE_PRIORITY_DEFAULT);
+ SimulateCookieDeletedByUser(identity_manager()->GetGaiaCookieManagerService(),
+ cookie);
+ run_loop.Run();
+}
+
+TEST_F(IdentityManagerTest, OnNetworkInitialized) {
+ auto test_cookie_manager = std::make_unique<network::TestCookieManager>();
+ network::TestCookieManager* test_cookie_manager_ptr =
+ test_cookie_manager.get();
+ signin_client()->set_cookie_manager(std::move(test_cookie_manager));
+
+ identity_manager()->OnNetworkInitialized();
+
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnCookieDeletedByUserCallback(
+ run_loop.QuitClosure());
+
+ // Dispatch a known change of a known cookie instance *through the mojo
+ // pipe* in order to ensure the GCMS is listening to CookieManager changes.
+ //
+ // It is important the the cause of the change is known here (ie
+ // network::mojom::CookieChangeCause::EXPLICIT) so the test can block of the
+ // proper IdentityManager observer callback to be called (in this case
+ // OnAccountsCookieDeletedByUserAction).
+ //
+ // Note that this call differs from calling SimulateCookieDeletedByUser()
+ // directly in the sense that SimulateCookieDeletedByUser() does not go
+ // through any mojo pipe.
+ net::CanonicalCookie cookie("APISID", std::string(), ".google.com", "/",
+ base::Time(), base::Time(), base::Time(), false,
+ false, net::CookieSameSite::NO_RESTRICTION,
+ net::COOKIE_PRIORITY_DEFAULT);
+ test_cookie_manager_ptr->DispatchCookieChange(
+ cookie, network::mojom::CookieChangeCause::EXPLICIT);
+ run_loop.Run();
+}
+
+TEST_F(IdentityManagerTest,
+ BatchChangeObserversAreNotifiedOnCredentialsUpdate) {
+ identity_manager()->GetPrimaryAccountManager()->SetAuthenticatedAccountInfo(
+ kTestGaiaId, kTestEmail);
+ token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
+
+ EXPECT_EQ(1ul, identity_manager_observer()->BatchChangeRecords().size());
+ EXPECT_EQ(1ul,
+ identity_manager_observer()->BatchChangeRecords().at(0).size());
+ EXPECT_EQ(primary_account_id(),
+ identity_manager_observer()->BatchChangeRecords().at(0).at(0));
+}
+
+// Checks that FindAccountInfoForAccountWithRefreshTokenByAccountId() returns
+// information about the account if the account is found or nullopt if there
+// are no accounts with requested |account_id|.
+TEST_F(IdentityManagerTest,
+ FindAccountInfoForAccountWithRefreshTokenByAccountId) {
+ // Add an account (note: cannot use kTestEmail as it is already inserted
+ // by the fixture common code, so use a different address).
+ const AccountInfo foo_account_info =
+ MakeAccountAvailable(identity_manager(), "foo@bar.com");
+
+ base::Optional<AccountInfo> maybe_account_info;
+ maybe_account_info =
+ identity_manager()->FindAccountInfoForAccountWithRefreshTokenByAccountId(
+ "dummy_value");
+ EXPECT_FALSE(maybe_account_info.has_value());
+
+ maybe_account_info =
+ identity_manager()->FindAccountInfoForAccountWithRefreshTokenByAccountId(
+ foo_account_info.account_id);
+ EXPECT_TRUE(maybe_account_info.has_value());
+ EXPECT_EQ(foo_account_info.account_id, maybe_account_info.value().account_id);
+ EXPECT_EQ(foo_account_info.email, maybe_account_info.value().email);
+ EXPECT_EQ(foo_account_info.gaia, maybe_account_info.value().gaia);
+}
+
+// Checks that FindAccountInfoForAccountWithRefreshTokenByEmailAddress() returns
+// information about the account if the account is found or nullopt if there
+// are no accounts with requested |email_address|.
+TEST_F(IdentityManagerTest,
+ FindAccountInfoForAccountWithRefreshTokenByEmailAddress) {
+ // Add an account (note: cannot use kTestEmail as it is already inserted
+ // by the fixture common code, so use a different address).
+ const AccountInfo foo_account_info =
+ MakeAccountAvailable(identity_manager(), "foo@bar.com");
+
+ base::Optional<AccountInfo> maybe_account_info;
+ maybe_account_info =
+ identity_manager()
+ ->FindAccountInfoForAccountWithRefreshTokenByEmailAddress(
+ "dummy_value");
+ EXPECT_FALSE(maybe_account_info.has_value());
+
+ maybe_account_info =
+ identity_manager()
+ ->FindAccountInfoForAccountWithRefreshTokenByEmailAddress(
+ foo_account_info.email);
+ EXPECT_TRUE(maybe_account_info.has_value());
+ EXPECT_EQ(foo_account_info.account_id, maybe_account_info.value().account_id);
+ EXPECT_EQ(foo_account_info.email, maybe_account_info.value().email);
+ EXPECT_EQ(foo_account_info.gaia, maybe_account_info.value().gaia);
+}
+
+// Checks that FindAccountInfoForAccountWithRefreshTokenByGaiaId() returns
+// information about the account if the account is found or nullopt if there
+// are no accounts with requested |gaia_id|.
+TEST_F(IdentityManagerTest, FindAccountInfoForAccountWithRefreshTokenByGaiaId) {
+ // Add an account (note: cannot use kTestEmail as it is already inserted
+ // by the fixture common code, so use a different address).
+ const AccountInfo foo_account_info =
+ MakeAccountAvailable(identity_manager(), "foo@bar.com");
+
+ base::Optional<AccountInfo> maybe_account_info;
+ maybe_account_info =
+ identity_manager()->FindAccountInfoForAccountWithRefreshTokenByGaiaId(
+ "dummy_value");
+ EXPECT_FALSE(maybe_account_info.has_value());
+
+ maybe_account_info =
+ identity_manager()->FindAccountInfoForAccountWithRefreshTokenByGaiaId(
+ foo_account_info.gaia);
+ EXPECT_TRUE(maybe_account_info.has_value());
+ EXPECT_EQ(foo_account_info.account_id, maybe_account_info.value().account_id);
+ EXPECT_EQ(foo_account_info.email, maybe_account_info.value().email);
+ EXPECT_EQ(foo_account_info.gaia, maybe_account_info.value().gaia);
+}
+
+// Checks that AreRefreshTokensLoaded() returns true after LoadCredentials.
+TEST_F(IdentityManagerTest, AreRefreshTokensLoaded) {
+ base::RunLoop run_loop;
+ identity_manager_observer()->SetOnRefreshTokensLoadedCallback(
+ run_loop.QuitClosure());
+
+ // Credentials are already loaded in PrimaryAccountManager::Initialize()
+ // which runs even before the IdentityManager is created. That's why
+ // we fake the credentials loaded state and force another load in
+ // order to test AreRefreshTokensLoaded.
+ token_service()->set_all_credentials_loaded_for_testing(false);
+ EXPECT_FALSE(identity_manager()->AreRefreshTokensLoaded());
+ token_service()->LoadCredentials("");
+ run_loop.Run();
+ EXPECT_TRUE(identity_manager()->AreRefreshTokensLoaded());
+}
+
+TEST_F(IdentityManagerTest, AccountIdMigration_DoneOnInitialization) {
+ // Migration gets marked as DONE while initializing the AccountTrackerService
+ // on platforms supporting account ID migration only.
+ if (IdentityManager::IsAccountIdMigrationSupported()) {
+ EXPECT_EQ(identity_manager()->GetAccountIdMigrationState(),
+ IdentityManager::AccountIdMigrationState::MIGRATION_DONE);
+ } else {
+ EXPECT_EQ(identity_manager()->GetAccountIdMigrationState(),
+ IdentityManager::AccountIdMigrationState::MIGRATION_NOT_STARTED);
+ }
+}
+
+// Checks that IdentityManager::Observer gets OnAccountUpdated when account info
+// is updated.
+TEST_F(IdentityManagerTest, ObserveOnAccountUpdated) {
+ const AccountInfo account_info =
+ MakeAccountAvailable(identity_manager(), kTestEmail3);
+
+ SimulateSuccessfulFetchOfAccountInfo(
+ identity_manager(), account_info.account_id, account_info.email,
+ account_info.account_id, kTestHostedDomain, kTestFullName, kTestGivenName,
+ kTestLocale, kTestPictureUrl);
+
+ EXPECT_EQ(account_info.account_id, identity_manager_observer()
+ ->AccountFromAccountUpdatedCallback()
+ .account_id);
+ EXPECT_EQ(
+ account_info.email,
+ identity_manager_observer()->AccountFromAccountUpdatedCallback().email);
+}
+
+TEST_F(IdentityManagerTest, TestOnAccountRemovedWithInfoCallback) {
+ AccountInfo account_info =
+ MakeAccountAvailable(identity_manager(), kTestEmail2);
+ EXPECT_EQ(kTestEmail2, account_info.email);
+
+ account_tracker()->RemoveAccount(account_info.account_id);
+
+ // Check if OnAccountRemovedWithInfo is called after removing |account_info|
+ // by RemoveAccount().
+ EXPECT_TRUE(
+ identity_manager_observer()->WasCalledAccountRemovedWithInfoCallback());
+
+ // Check if the passed AccountInfo is the same to the removing one.
+ EXPECT_EQ(account_info.account_id,
+ identity_manager_observer()
+ ->AccountFromAccountRemovedWithInfoCallback()
+ .account_id);
+ EXPECT_EQ(account_info.email,
+ identity_manager_observer()
+ ->AccountFromAccountRemovedWithInfoCallback()
+ .email);
+}
+
+TEST_F(IdentityManagerTest, TestPickAccountIdForAccount) {
+ const CoreAccountId account_id =
+ identity_manager()->PickAccountIdForAccount(kTestGaiaId, kTestEmail);
+ const bool account_id_migration_done =
+ identity_manager()->GetAccountIdMigrationState() ==
+ IdentityManager::AccountIdMigrationState::MIGRATION_DONE;
+ if (account_id_migration_done) {
+ EXPECT_EQ(account_id, kTestGaiaId);
+ } else {
+ EXPECT_TRUE(gaia::AreEmailsSame(account_id, kTestEmail));
+ }
+}
+
+// Check that FindExtendedAccountInfoForAccount returns a valid account info
+// iff the account is known, has refresh token and all the extended information
+// is available.
+TEST_F(IdentityManagerTest, FindExtendedAccountInfoForAccount) {
+ CoreAccountInfo account_info;
+ account_info.email = kTestEmail;
+ account_info.gaia = kTestGaiaId;
+ account_info.account_id =
+ identity_manager()->PickAccountIdForAccount(kTestGaiaId, kTestEmail);
+
+ // FindExtendedAccountInfoForAccount() returns empty optional if the
+ // account_info is invalid.
+ EXPECT_FALSE(identity_manager()
+ ->FindExtendedAccountInfoForAccount(CoreAccountInfo{})
+ .has_value());
+
+ // FindExtendedAccountInfoForAccount() returns empty optional if the
+ // account_info is unknown.
+ EXPECT_FALSE(identity_manager()
+ ->FindExtendedAccountInfoForAccount(account_info)
+ .has_value());
+
+ // Insert the core account information in the AccountTrackerService.
+ const CoreAccountId account_id =
+ account_tracker()->SeedAccountInfo(kTestGaiaId, kTestEmail);
+ ASSERT_EQ(account_info.account_id, account_id);
+
+ // FindExtendedAccountInfoForAccount() returns empty optional if the account
+ // has no refresh token.
+ EXPECT_FALSE(identity_manager()
+ ->FindExtendedAccountInfoForAccount(account_info)
+ .has_value());
+
+ // Insert refresh token for account.
+ SetRefreshTokenForAccount(identity_manager(), account_info.account_id,
+ "refresh-token");
+
+ // FindExtendedAccountInfoForAccount() returns extended account information if
+ // the account is known and has valid refresh token.
+ const base::Optional<AccountInfo> extended_account_info =
+ identity_manager()->FindExtendedAccountInfoForAccount(account_info);
+
+ ASSERT_TRUE(extended_account_info.has_value());
+ EXPECT_EQ(account_info.gaia, extended_account_info.value().gaia);
+ EXPECT_EQ(account_info.email, extended_account_info.value().email);
+ EXPECT_EQ(account_info.account_id, extended_account_info.value().account_id);
+}
+
+#if defined(OS_ANDROID)
+TEST_F(IdentityManagerTest, ForceRefreshOfExtendedAccountInfo) {
+ // The flow of this test results in an interaction with
+ // ChildAccountInfoFetcherAndroid, which requires initialization in order to
+ // avoid a crash.
+ ChildAccountInfoFetcherAndroid::InitializeForTests();
+
+ identity_manager()->GetAccountFetcherService()->OnNetworkInitialized();
+ AccountInfo account_info =
+ MakeAccountAvailable(identity_manager(), kTestEmail2);
+ identity_manager()->ForceRefreshOfExtendedAccountInfo(
+ account_info.account_id);
+
+ SimulateSuccessfulFetchOfAccountInfo(
+ identity_manager(), account_info.account_id, account_info.email,
+ account_info.account_id, kTestHostedDomain, kTestFullName, kTestGivenName,
+ kTestLocale, kTestPictureUrl);
+
+ const AccountInfo& refreshed_account_info =
+ identity_manager_observer()->AccountFromAccountUpdatedCallback();
+ EXPECT_EQ(account_info.account_id, refreshed_account_info.account_id);
+ EXPECT_EQ(account_info.email, refreshed_account_info.email);
+ EXPECT_EQ(account_info.gaia, refreshed_account_info.gaia);
+ EXPECT_EQ(kTestHostedDomain, refreshed_account_info.hosted_domain);
+ EXPECT_EQ(kTestFullName, refreshed_account_info.full_name);
+ EXPECT_EQ(kTestGivenName, refreshed_account_info.given_name);
+ EXPECT_EQ(kTestLocale, refreshed_account_info.locale);
+ EXPECT_EQ(kTestPictureUrl, refreshed_account_info.picture_url);
+}
+#endif
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/identity_test_environment.cc b/chromium/components/signin/public/identity_manager/identity_test_environment.cc
new file mode 100644
index 00000000000..6c033416f65
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/identity_test_environment.cc
@@ -0,0 +1,505 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
+#include "components/image_fetcher/core/fake_image_decoder.h"
+#include "components/signin/internal/identity_manager/account_fetcher_service.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h"
+#include "components/signin/internal/identity_manager/diagnostics_provider_impl.h"
+#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h"
+#include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h"
+#include "components/signin/internal/identity_manager/primary_account_manager.h"
+#include "components/signin/internal/identity_manager/primary_account_mutator_impl.h"
+#include "components/signin/internal/identity_manager/primary_account_policy_manager_impl.h"
+#include "components/signin/public/base/test_signin_client.h"
+#include "components/signin/public/identity_manager/accounts_mutator.h"
+#include "components/signin/public/identity_manager/device_accounts_synchronizer.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/identity_test_utils.h"
+#include "components/signin/public/identity_manager/primary_account_mutator.h"
+#include "components/signin/public/identity_manager/test_identity_manager_observer.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "google_apis/gaia/oauth2_access_token_consumer.h"
+
+#if defined(OS_IOS)
+#include "components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h"
+#endif
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#include "components/signin/internal/identity_manager/accounts_mutator_impl.h"
+#endif
+
+namespace signin {
+
+class IdentityManagerDependenciesOwner {
+ public:
+ IdentityManagerDependenciesOwner(
+ sync_preferences::TestingPrefServiceSyncable* pref_service,
+ TestSigninClient* test_signin_client);
+ ~IdentityManagerDependenciesOwner();
+
+ sync_preferences::TestingPrefServiceSyncable* pref_service();
+
+ TestSigninClient* signin_client();
+
+ private:
+ // Depending on whether a |pref_service| instance is passed in
+ // the constructor, exactly one of these will be non-null.
+ std::unique_ptr<sync_preferences::TestingPrefServiceSyncable>
+ owned_pref_service_;
+ sync_preferences::TestingPrefServiceSyncable* raw_pref_service_ = nullptr;
+
+ std::unique_ptr<TestSigninClient> owned_signin_client_;
+ TestSigninClient* raw_signin_client_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(IdentityManagerDependenciesOwner);
+};
+
+IdentityManagerDependenciesOwner::IdentityManagerDependenciesOwner(
+ sync_preferences::TestingPrefServiceSyncable* pref_service_param,
+ TestSigninClient* signin_client_param)
+ : owned_pref_service_(
+ pref_service_param
+ ? nullptr
+ : std::make_unique<
+ sync_preferences::TestingPrefServiceSyncable>()),
+ raw_pref_service_(pref_service_param),
+ owned_signin_client_(
+ signin_client_param
+ ? nullptr
+ : std::make_unique<TestSigninClient>(pref_service())),
+ raw_signin_client_(signin_client_param) {}
+
+IdentityManagerDependenciesOwner::~IdentityManagerDependenciesOwner() = default;
+
+sync_preferences::TestingPrefServiceSyncable*
+IdentityManagerDependenciesOwner::pref_service() {
+ DCHECK(raw_pref_service_ || owned_pref_service_);
+ DCHECK(!(raw_pref_service_ && owned_pref_service_));
+
+ return raw_pref_service_ ? raw_pref_service_ : owned_pref_service_.get();
+}
+
+TestSigninClient* IdentityManagerDependenciesOwner::signin_client() {
+ DCHECK(raw_signin_client_ || owned_signin_client_);
+ DCHECK(!(raw_signin_client_ && owned_signin_client_));
+
+ return raw_signin_client_ ? raw_signin_client_ : owned_signin_client_.get();
+}
+
+IdentityTestEnvironment::IdentityTestEnvironment(
+ network::TestURLLoaderFactory* test_url_loader_factory,
+ sync_preferences::TestingPrefServiceSyncable* pref_service,
+ AccountConsistencyMethod account_consistency,
+ TestSigninClient* test_signin_client)
+ : IdentityTestEnvironment(
+ std::make_unique<IdentityManagerDependenciesOwner>(
+ pref_service,
+ test_signin_client),
+ test_url_loader_factory,
+ account_consistency) {
+ DCHECK(!test_url_loader_factory || !test_signin_client);
+}
+
+IdentityTestEnvironment::IdentityTestEnvironment(
+ IdentityManager* identity_manager) {
+ DCHECK(identity_manager);
+ raw_identity_manager_ = identity_manager;
+ Initialize();
+}
+
+void IdentityTestEnvironment::Initialize() {
+ DCHECK(base::ThreadTaskRunnerHandle::Get())
+ << "IdentityTestEnvironment requires a properly set up task "
+ "environment. "
+ "If your test has an existing one, move it to be initialized before "
+ "IdentityTestEnvironment. Otherwise, use "
+ "base::test::ScopedTaskEnvironment.";
+ test_identity_manager_observer_ =
+ std::make_unique<TestIdentityManagerObserver>(this->identity_manager());
+ this->identity_manager()->AddDiagnosticsObserver(this);
+}
+
+IdentityTestEnvironment::IdentityTestEnvironment(
+ std::unique_ptr<IdentityManagerDependenciesOwner> dependencies_owner,
+ network::TestURLLoaderFactory* test_url_loader_factory,
+ AccountConsistencyMethod account_consistency) {
+ dependencies_owner_ = std::move(dependencies_owner);
+ TestSigninClient* test_signin_client = dependencies_owner_->signin_client();
+ if (test_url_loader_factory)
+ test_signin_client->OverrideTestUrlLoaderFactory(test_url_loader_factory);
+
+ sync_preferences::TestingPrefServiceSyncable* test_pref_service =
+ dependencies_owner_->pref_service();
+
+ IdentityManager::RegisterProfilePrefs(test_pref_service->registry());
+ IdentityManager::RegisterLocalStatePrefs(test_pref_service->registry());
+
+ owned_identity_manager_ =
+ BuildIdentityManagerForTests(test_signin_client, test_pref_service,
+ base::FilePath(), account_consistency);
+
+ Initialize();
+}
+
+// static
+std::unique_ptr<IdentityManager>
+IdentityTestEnvironment::BuildIdentityManagerForTests(
+ SigninClient* signin_client,
+ PrefService* pref_service,
+ base::FilePath user_data_dir,
+ AccountConsistencyMethod account_consistency) {
+ auto account_tracker_service = std::make_unique<AccountTrackerService>();
+ account_tracker_service->Initialize(pref_service, user_data_dir);
+
+ auto token_service =
+ std::make_unique<FakeProfileOAuth2TokenService>(pref_service);
+
+ auto account_fetcher_service = std::make_unique<AccountFetcherService>();
+ account_fetcher_service->Initialize(
+ signin_client, token_service.get(), account_tracker_service.get(),
+ std::make_unique<image_fetcher::FakeImageDecoder>());
+
+ std::unique_ptr<PrimaryAccountPolicyManager> policy_manager;
+#if !defined(OS_CHROMEOS)
+ policy_manager =
+ std::make_unique<PrimaryAccountPolicyManagerImpl>(signin_client);
+#endif
+ std::unique_ptr<PrimaryAccountManager> primary_account_manager =
+ std::make_unique<PrimaryAccountManager>(
+ signin_client, token_service.get(), account_tracker_service.get(),
+ account_consistency, std::move(policy_manager));
+ primary_account_manager->Initialize(pref_service);
+
+ std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service =
+ std::make_unique<GaiaCookieManagerService>(token_service.get(),
+ signin_client);
+
+ std::unique_ptr<PrimaryAccountMutator> primary_account_mutator =
+ std::make_unique<PrimaryAccountMutatorImpl>(account_tracker_service.get(),
+ primary_account_manager.get(),
+ pref_service);
+
+ std::unique_ptr<AccountsMutator> accounts_mutator;
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ accounts_mutator = std::make_unique<AccountsMutatorImpl>(
+ token_service.get(), account_tracker_service.get(),
+ primary_account_manager.get(), pref_service);
+#endif
+
+ auto diagnostics_provider = std::make_unique<DiagnosticsProviderImpl>(
+ token_service.get(), gaia_cookie_manager_service.get());
+
+ auto accounts_cookie_mutator = std::make_unique<AccountsCookieMutatorImpl>(
+ gaia_cookie_manager_service.get(), account_tracker_service.get());
+
+ std::unique_ptr<DeviceAccountsSynchronizer> device_accounts_synchronizer;
+#if defined(OS_IOS)
+ device_accounts_synchronizer =
+ std::make_unique<DeviceAccountsSynchronizerImpl>(
+ token_service->GetDelegate());
+#endif
+
+ return std::make_unique<IdentityManager>(
+ std::move(account_tracker_service), std::move(token_service),
+ std::move(gaia_cookie_manager_service),
+ std::move(primary_account_manager), std::move(account_fetcher_service),
+ std::move(primary_account_mutator), std::move(accounts_mutator),
+ std::move(accounts_cookie_mutator), std::move(diagnostics_provider),
+ std::move(device_accounts_synchronizer));
+}
+
+IdentityTestEnvironment::~IdentityTestEnvironment() {
+ // Remove the Observer that IdentityTestEnvironment added during its
+ // initialization.
+ identity_manager()->RemoveDiagnosticsObserver(this);
+}
+
+IdentityManager* IdentityTestEnvironment::identity_manager() {
+ DCHECK(raw_identity_manager_ || owned_identity_manager_);
+ DCHECK(!(raw_identity_manager_ && owned_identity_manager_));
+
+ return raw_identity_manager_ ? raw_identity_manager_
+ : owned_identity_manager_.get();
+}
+
+TestIdentityManagerObserver*
+IdentityTestEnvironment::identity_manager_observer() {
+ return test_identity_manager_observer_.get();
+}
+
+CoreAccountInfo IdentityTestEnvironment::SetPrimaryAccount(
+ const std::string& email) {
+ return signin::SetPrimaryAccount(identity_manager(), email);
+}
+
+void IdentityTestEnvironment::SetRefreshTokenForPrimaryAccount() {
+ signin::SetRefreshTokenForPrimaryAccount(identity_manager());
+}
+
+void IdentityTestEnvironment::SetInvalidRefreshTokenForPrimaryAccount() {
+ signin::SetInvalidRefreshTokenForPrimaryAccount(identity_manager());
+}
+
+void IdentityTestEnvironment::RemoveRefreshTokenForPrimaryAccount() {
+ signin::RemoveRefreshTokenForPrimaryAccount(identity_manager());
+}
+
+AccountInfo IdentityTestEnvironment::MakePrimaryAccountAvailable(
+ const std::string& email) {
+ return signin::MakePrimaryAccountAvailable(identity_manager(), email);
+}
+
+void IdentityTestEnvironment::ClearPrimaryAccount(
+ ClearPrimaryAccountPolicy policy) {
+ signin::ClearPrimaryAccount(identity_manager(), policy);
+}
+
+AccountInfo IdentityTestEnvironment::MakeAccountAvailable(
+ const std::string& email) {
+ return signin::MakeAccountAvailable(identity_manager(), email);
+}
+
+void IdentityTestEnvironment::SetRefreshTokenForAccount(
+ const CoreAccountId& account_id) {
+ return signin::SetRefreshTokenForAccount(identity_manager(), account_id);
+}
+
+void IdentityTestEnvironment::SetInvalidRefreshTokenForAccount(
+ const CoreAccountId& account_id) {
+ return signin::SetInvalidRefreshTokenForAccount(identity_manager(),
+ account_id);
+}
+
+void IdentityTestEnvironment::RemoveRefreshTokenForAccount(
+ const CoreAccountId& account_id) {
+ return signin::RemoveRefreshTokenForAccount(identity_manager(), account_id);
+}
+
+void IdentityTestEnvironment::UpdatePersistentErrorOfRefreshTokenForAccount(
+ const CoreAccountId& account_id,
+ const GoogleServiceAuthError& auth_error) {
+ return signin::UpdatePersistentErrorOfRefreshTokenForAccount(
+ identity_manager(), account_id, auth_error);
+}
+
+void IdentityTestEnvironment::SetCookieAccounts(
+ const std::vector<CookieParamsForTest>& cookie_accounts) {
+ signin::SetCookieAccounts(
+ identity_manager(),
+ dependencies_owner_->signin_client()->GetTestURLLoaderFactory(),
+ cookie_accounts);
+}
+
+void IdentityTestEnvironment::SetAutomaticIssueOfAccessTokens(bool grant) {
+ fake_token_service()->set_auto_post_fetch_response_on_message_loop(grant);
+}
+
+void IdentityTestEnvironment::
+ WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ const std::string& token,
+ const base::Time& expiration,
+ const std::string& id_token) {
+ WaitForAccessTokenRequestIfNecessary(base::nullopt);
+ fake_token_service()->IssueTokenForAllPendingRequests(
+ OAuth2AccessTokenConsumer::TokenResponse(token, expiration, id_token));
+}
+
+void IdentityTestEnvironment::
+ WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ const CoreAccountId& account_id,
+ const std::string& token,
+ const base::Time& expiration,
+ const std::string& id_token) {
+ WaitForAccessTokenRequestIfNecessary(account_id);
+ fake_token_service()->IssueAllTokensForAccount(
+ account_id,
+ OAuth2AccessTokenConsumer::TokenResponse(token, expiration, id_token));
+}
+
+void IdentityTestEnvironment::
+ WaitForAccessTokenRequestIfNecessaryAndRespondWithTokenForScopes(
+ const std::string& token,
+ const base::Time& expiration,
+ const std::string& id_token,
+ const identity::ScopeSet& scopes) {
+ WaitForAccessTokenRequestIfNecessary(base::nullopt);
+ fake_token_service()->IssueTokenForScope(
+ scopes,
+ OAuth2AccessTokenConsumer::TokenResponse(token, expiration, id_token));
+}
+
+void IdentityTestEnvironment::
+ WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
+ const GoogleServiceAuthError& error) {
+ WaitForAccessTokenRequestIfNecessary(base::nullopt);
+ fake_token_service()->IssueErrorForAllPendingRequests(error);
+}
+
+void IdentityTestEnvironment::
+ WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
+ const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error) {
+ WaitForAccessTokenRequestIfNecessary(account_id);
+ fake_token_service()->IssueErrorForAllPendingRequestsForAccount(account_id,
+ error);
+}
+
+void IdentityTestEnvironment::SetCallbackForNextAccessTokenRequest(
+ base::OnceClosure callback) {
+ on_access_token_requested_callback_ = std::move(callback);
+}
+
+IdentityTestEnvironment::AccessTokenRequestState::AccessTokenRequestState() =
+ default;
+IdentityTestEnvironment::AccessTokenRequestState::~AccessTokenRequestState() =
+ default;
+IdentityTestEnvironment::AccessTokenRequestState::AccessTokenRequestState(
+ AccessTokenRequestState&& other) = default;
+IdentityTestEnvironment::AccessTokenRequestState&
+IdentityTestEnvironment::AccessTokenRequestState::operator=(
+ AccessTokenRequestState&& other) = default;
+
+void IdentityTestEnvironment::OnAccessTokenRequested(
+ const CoreAccountId& account_id,
+ const std::string& consumer_id,
+ const identity::ScopeSet& scopes) {
+ // Post a task to handle this access token request in order to support the
+ // case where the access token request is handled synchronously in the
+ // production code, in which case this callback could be coming in ahead
+ // of an invocation of WaitForAccessTokenRequestIfNecessary() that will be
+ // made in this same iteration of the run loop.
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&IdentityTestEnvironment::HandleOnAccessTokenRequested,
+ weak_ptr_factory_.GetWeakPtr(), account_id));
+}
+
+void IdentityTestEnvironment::HandleOnAccessTokenRequested(
+ CoreAccountId account_id) {
+ if (on_access_token_requested_callback_) {
+ std::move(on_access_token_requested_callback_).Run();
+ return;
+ }
+
+ for (auto it = requesters_.begin(); it != requesters_.end(); ++it) {
+ if (!it->account_id || (it->account_id.value() == account_id)) {
+ if (it->state == AccessTokenRequestState::kAvailable)
+ return;
+ if (it->on_available)
+ std::move(it->on_available).Run();
+ requesters_.erase(it);
+ return;
+ }
+ }
+
+ // A requests came in for a request for which we are not waiting. Record
+ // that it's available.
+ requesters_.emplace_back();
+ requesters_.back().state = AccessTokenRequestState::kAvailable;
+ requesters_.back().account_id = account_id;
+}
+
+void IdentityTestEnvironment::WaitForAccessTokenRequestIfNecessary(
+ base::Optional<CoreAccountId> account_id) {
+ // Handle HandleOnAccessTokenRequested getting called before
+ // WaitForAccessTokenRequestIfNecessary.
+ if (account_id) {
+ for (auto it = requesters_.begin(); it != requesters_.end(); ++it) {
+ if (it->account_id && it->account_id.value() == account_id.value()) {
+ // Can't wait twice for same thing.
+ DCHECK_EQ(AccessTokenRequestState::kAvailable, it->state);
+ requesters_.erase(it);
+ return;
+ }
+ }
+ } else {
+ for (auto it = requesters_.begin(); it != requesters_.end(); ++it) {
+ if (it->state == AccessTokenRequestState::kAvailable) {
+ requesters_.erase(it);
+ return;
+ }
+ }
+ }
+
+ base::RunLoop run_loop;
+ requesters_.emplace_back();
+ requesters_.back().state = AccessTokenRequestState::kPending;
+ requesters_.back().account_id = std::move(account_id);
+ requesters_.back().on_available = run_loop.QuitClosure();
+ run_loop.Run();
+}
+
+FakeProfileOAuth2TokenService* IdentityTestEnvironment::fake_token_service() {
+ // We can't absolutely guarantee that IdentityTestEnvironment was not given an
+ // IdentityManager that uses a non-fake FakeProfileOAuth2TokenService. If that
+ // ever happens, this will blow up. There doesn't seem to be a better option.
+ return static_cast<FakeProfileOAuth2TokenService*>(
+ identity_manager()->GetTokenService());
+}
+
+void IdentityTestEnvironment::UpdateAccountInfoForAccount(
+ AccountInfo account_info) {
+ signin::UpdateAccountInfoForAccount(identity_manager(), account_info);
+}
+
+void IdentityTestEnvironment::ResetToAccountsNotYetLoadedFromDiskState() {
+ fake_token_service()->set_all_credentials_loaded_for_testing(false);
+}
+
+void IdentityTestEnvironment::ReloadAccountsFromDisk() {
+ fake_token_service()->LoadCredentials("");
+}
+
+bool IdentityTestEnvironment::IsAccessTokenRequestPending() {
+ return fake_token_service()->GetPendingRequests().size();
+}
+
+void IdentityTestEnvironment::SetFreshnessOfAccountsInGaiaCookie(
+ bool accounts_are_fresh) {
+ signin::SetFreshnessOfAccountsInGaiaCookie(identity_manager(),
+ accounts_are_fresh);
+}
+
+void IdentityTestEnvironment::EnableRemovalOfExtendedAccountInfo() {
+ identity_manager()->GetAccountFetcherService()->EnableAccountRemovalForTest();
+}
+
+void IdentityTestEnvironment::SimulateSuccessfulFetchOfAccountInfo(
+ const CoreAccountId& account_id,
+ const std::string& email,
+ const std::string& gaia,
+ const std::string& hosted_domain,
+ const std::string& full_name,
+ const std::string& given_name,
+ const std::string& locale,
+ const std::string& picture_url) {
+ signin::SimulateSuccessfulFetchOfAccountInfo(
+ identity_manager(), account_id, email, gaia, hosted_domain, full_name,
+ given_name, locale, picture_url);
+}
+
+void IdentityTestEnvironment::SimulateMergeSessionFailure(
+ const GoogleServiceAuthError& auth_error) {
+ // GaiaCookieManagerService changes the visibility of inherited method
+ // OnMergeSessionFailure from public to private. Cast to a base class
+ // pointer to call the method.
+ static_cast<GaiaAuthConsumer*>(
+ identity_manager()->GetGaiaCookieManagerService())
+ ->OnMergeSessionFailure(auth_error);
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/identity_test_environment.h b/chromium/components/signin/public/identity_manager/identity_test_environment.h
new file mode 100644
index 00000000000..3b5efc73fbf
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/identity_test_environment.h
@@ -0,0 +1,370 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_TEST_ENVIRONMENT_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_TEST_ENVIRONMENT_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/optional.h"
+#include "build/build_config.h"
+#include "components/signin/public/base/account_consistency_method.h"
+#include "components/signin/public/base/signin_client.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/identity_test_utils.h"
+
+class FakeProfileOAuth2TokenService;
+class IdentityTestEnvironmentProfileAdaptor;
+class PrefService;
+class TestSigninClient;
+
+namespace sync_preferences {
+class TestingPrefServiceSyncable;
+}
+
+namespace network {
+class TestURLLoaderFactory;
+}
+
+namespace signin {
+
+class IdentityManagerDependenciesOwner;
+class TestIdentityManagerObserver;
+
+// Class that creates an IdentityManager for use in testing contexts and
+// provides facilities for driving that IdentityManager. The IdentityManager
+// instance is brought up in an environment where the primary account is
+// not available; call MakePrimaryAccountAvailable() as needed.
+// NOTE: IdentityTestEnvironment requires that tests have a properly set up
+// task environment. If your test doesn't already have one, use a
+// base::test::ScopedTaskEnvironment instance variable to fulfill this
+// requirement.
+class IdentityTestEnvironment : public IdentityManager::DiagnosticsObserver {
+ public:
+ // Preferred constructor: constructs an IdentityManager object and its
+ // dependencies internally. Cannot be used if the client of this class
+ // is still interacting directly with those dependencies (e.g., if
+ // IdentityTestEnvironment is being introduced to incrementally convert
+ // a test). In that case, use the below constructor and switch to this
+ // constructor once the conversion is complete.
+ //
+ // This constructor takes an optional parameter |test_url_loader_factory| to
+ // use for cookie-related network requests.
+ // Note: the provided |test_url_loader_factory| is expected to outlive
+ // IdentityTestEnvironment.
+ //
+ // This constructor also takes an optional PrefService instance as parameter,
+ // which allows tests to move away from referencing IdentityManager's
+ // dependencies directly (namely AccountTrackerService, PO2TS), but still be
+ // able to tweak preferences on demand.
+ //
+ // |account_consistency| specifies the account consistency policy that will be
+ // used.
+ //
+ // A specific TestSigninClient instance can be passed optionally. If it is
+ // null, the test environment will automatically build one internally.
+ //
+ // Note: at least one of |test_url_loader_factory| and |test_signin_client|
+ // must be nulltpr. They cannot both be specified at the same time.
+ IdentityTestEnvironment(
+ network::TestURLLoaderFactory* test_url_loader_factory = nullptr,
+ sync_preferences::TestingPrefServiceSyncable* pref_service = nullptr,
+ AccountConsistencyMethod account_consistency =
+ AccountConsistencyMethod::kDisabled,
+ TestSigninClient* test_signin_client = nullptr);
+
+ ~IdentityTestEnvironment() override;
+
+ // The IdentityManager instance associated with this instance.
+ IdentityManager* identity_manager();
+
+ // Returns the |TestIdentityManagerObserver| watching the IdentityManager.
+ TestIdentityManagerObserver* identity_manager_observer();
+
+ // Sets the primary account for the given email address, generating a GAIA ID
+ // that corresponds uniquely to that email address. On non-ChromeOS, results
+ // in the firing of the IdentityManager and PrimaryAccountManager callbacks
+ // for signin success. Blocks until the primary account is set. Returns the
+ // CoreAccountInfo of the newly-set account.
+ CoreAccountInfo SetPrimaryAccount(const std::string& email);
+
+ // Sets a refresh token for the primary account (which must already be set).
+ // Before updating the refresh token, blocks until refresh tokens are loaded.
+ // After updating the token, blocks until the update is processed by
+ // |identity_manager|.
+ void SetRefreshTokenForPrimaryAccount();
+
+ // Sets a special invalid refresh token for the primary account (which must
+ // already be set). Before updating the refresh token, blocks until refresh
+ // tokens are loaded. After updating the token, blocks until the update is
+ // processed by |identity_manager|.
+ void SetInvalidRefreshTokenForPrimaryAccount();
+
+ // Removes any refresh token for the primary account, if present. Blocks until
+ // the refresh token is removed.
+ void RemoveRefreshTokenForPrimaryAccount();
+
+ // Makes the primary account available for the given email address, generating
+ // a GAIA ID and refresh token that correspond uniquely to that email address.
+ // On non-ChromeOS platforms, this will also result in the firing of the
+ // IdentityManager and PrimaryAccountManager callbacks for signin success. On
+ // all platforms, this method blocks until the primary account is available.
+ // Returns the AccountInfo of the newly-available account.
+ AccountInfo MakePrimaryAccountAvailable(const std::string& email);
+
+ // Clears the primary account if present, with |policy| used to determine
+ // whether to keep or remove all accounts. On non-ChromeOS, results in the
+ // firing of the IdentityManager and PrimaryAccountManager callbacks for
+ // signout. Blocks until the primary account is cleared.
+ void ClearPrimaryAccount(
+ ClearPrimaryAccountPolicy policy = ClearPrimaryAccountPolicy::DEFAULT);
+
+ // Makes an account available for the given email address, generating a GAIA
+ // ID and refresh token that correspond uniquely to that email address. Blocks
+ // until the account is available. Returns the AccountInfo of the
+ // newly-available account.
+ AccountInfo MakeAccountAvailable(const std::string& email);
+
+ // Sets a refresh token for the given account (which must already be
+ // available). Before updating the refresh token, blocks until refresh tokens
+ // are loaded. After updating the token, blocks until the update is processed
+ // by |identity_manager|. NOTE: See disclaimer at top of file re: direct
+ // usage.
+ void SetRefreshTokenForAccount(const CoreAccountId& account_id);
+
+ // Sets a special invalid refresh token for the given account (which must
+ // already be available). Before updating the refresh token, blocks until
+ // refresh tokens are loaded. After updating the token, blocks until the
+ // update is processed by |identity_manager|. NOTE: See disclaimer at top of
+ // file re: direct usage.
+ void SetInvalidRefreshTokenForAccount(const CoreAccountId& account_id);
+
+ // Removes any refresh token that is present for the given account. Blocks
+ // until the refresh token is removed.
+ // NOTE: See disclaimer at top of file re: direct usage.
+ void RemoveRefreshTokenForAccount(const CoreAccountId& account_id);
+
+ // Updates the persistent auth error set on |account_id| which must be a known
+ // account, i.e., an account with a refresh token.
+ void UpdatePersistentErrorOfRefreshTokenForAccount(
+ const CoreAccountId& account_id,
+ const GoogleServiceAuthError& auth_error);
+
+ // Puts the given accounts into the Gaia cookie, replacing any previous
+ // accounts. Blocks until the accounts have been set.
+ void SetCookieAccounts(
+ const std::vector<CookieParamsForTest>& cookie_accounts);
+
+ // When this is set, access token requests will be automatically granted with
+ // an access token value of "access_token".
+ void SetAutomaticIssueOfAccessTokens(bool grant);
+
+ // Issues |token| in response to any access token request that either has (a)
+ // already occurred and has not been matched by a previous call to this or
+ // other WaitFor... method, or (b) will occur in the future. In the latter
+ // case, waits until the access token request occurs.
+ // |id_token| is an uncommonly-needed parameter that contains extra
+ // information regarding the user's currently-registered services; if this
+ // means nothing to you, you don't need to concern yourself with it.
+ // NOTE: This method behaves this way to allow IdentityTestEnvironment to be
+ // agnostic with respect to whether access token requests are handled
+ // synchronously or asynchronously in the production code.
+ // NOTE: This version is suitable for use in the common context where access
+ // token requests are only being made for one account. If you need to
+ // disambiguate requests coming for different accounts, see the version below.
+ void WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ const std::string& token,
+ const base::Time& expiration,
+ const std::string& id_token = std::string());
+
+ // Issues |token| in response to an access token request for |account_id| that
+ // either already occurred and has not been matched by a previous call to this
+ // or other WaitFor... method , or (b) will occur in the future. In the latter
+ // case, waits until the access token request occurs.
+ // |id_token| is an uncommonly-needed parameter that contains extra
+ // information regarding the user's currently-registered services; if this
+ // means nothing to you, you don't need to concern yourself with it.
+ // NOTE: This method behaves this way to allow
+ // IdentityTestEnvironment to be agnostic with respect to whether access token
+ // requests are handled synchronously or asynchronously in the production
+ // code.
+ void WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ const CoreAccountId& account_id,
+ const std::string& token,
+ const base::Time& expiration,
+ const std::string& id_token = std::string());
+
+ // Similar to WaitForAccessTokenRequestIfNecessaryAndRespondWithToken above
+ // apart from the fact that it issues tokens for a given set of scopes only,
+ // instead of issueing all tokens for all requests (the method variant above).
+ void WaitForAccessTokenRequestIfNecessaryAndRespondWithTokenForScopes(
+ const std::string& token,
+ const base::Time& expiration,
+ const std::string& id_token,
+ const identity::ScopeSet& scopes);
+
+ // Issues |error| in response to any access token request that either has (a)
+ // already occurred and has not been matched by a previous call to this or
+ // other WaitFor... method, or (b) will occur in the future. In the latter
+ // case, waits until the access token request occurs.
+ // NOTE: This method behaves this way to allow IdentityTestEnvironment to be
+ // agnostic with respect to whether access token requests are handled
+ // synchronously or asynchronously in the production code.
+ // NOTE: This version is suitable for use in the common context where access
+ // token requests are only being made for one account. If you need to
+ // disambiguate requests coming for different accounts, see the version below.
+ void WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
+ const GoogleServiceAuthError& error);
+
+ // Issues |error| in response to an access token request for |account_id| that
+ // either has (a) already occurred and has not been matched by a previous call
+ // to this or other WaitFor... method, or (b) will occur in the future. In the
+ // latter case, waits until the access token request occurs.
+ // NOTE: This method behaves this way to allow
+ // IdentityTestEnvironment to be agnostic with respect to whether access token
+ // requests are handled synchronously or asynchronously in the production
+ // code.
+ void WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
+ const CoreAccountId& account_id,
+ const GoogleServiceAuthError& error);
+
+ // Sets a callback that will be invoked on the next incoming access token
+ // request. Note that this can not be combined with the
+ // WaitForAccessTokenRequestIfNecessaryAndRespondWith* methods - you must
+ // either wait for the callback to get called, or explicitly reset it by
+ // passing in a null callback, before the Wait* methods can be used again.
+ void SetCallbackForNextAccessTokenRequest(base::OnceClosure callback);
+
+ // Updates the info for |account_info.account_id|, which must be a known
+ // account.
+ void UpdateAccountInfoForAccount(AccountInfo account_info);
+
+ // Resets to the state where accounts have not yet been loaded from disk.
+ void ResetToAccountsNotYetLoadedFromDiskState();
+
+ // Simulates the reloading of the accounts from disk.
+ void ReloadAccountsFromDisk();
+
+ // Returns whether there is a access token request pending.
+ bool IsAccessTokenRequestPending();
+
+ // Sets whether the list of accounts in Gaia cookie jar is fresh and does not
+ // need to be updated.
+ void SetFreshnessOfAccountsInGaiaCookie(bool accounts_are_fresh);
+
+ // By default, extended account info removal is disabled in testing
+ // contexts. This call enables it for tests that require
+ // IdentityManager::Observer::OnExtendedAccountInfoRemoved() to fire as
+ // expected. TODO(https://crbug.com/927687): Enable this unconditionally.
+ void EnableRemovalOfExtendedAccountInfo();
+
+ // Simulate account fetching using AccountTrackerService without sending
+ // network requests.
+ void SimulateSuccessfulFetchOfAccountInfo(const CoreAccountId& account_id,
+ const std::string& email,
+ const std::string& gaia,
+ const std::string& hosted_domain,
+ const std::string& full_name,
+ const std::string& given_name,
+ const std::string& locale,
+ const std::string& picture_url);
+
+ // Simulates a merge session failure with |auth_error| as the error.
+ void SimulateMergeSessionFailure(const GoogleServiceAuthError& auth_error);
+
+ private:
+ friend class ::IdentityTestEnvironmentProfileAdaptor;
+
+ struct AccessTokenRequestState {
+ AccessTokenRequestState();
+ ~AccessTokenRequestState();
+ AccessTokenRequestState(AccessTokenRequestState&& other);
+ AccessTokenRequestState& operator=(AccessTokenRequestState&& other);
+
+ enum {
+ kPending,
+ kAvailable,
+ } state;
+ base::Optional<std::string> account_id;
+ base::OnceClosure on_available;
+ };
+
+ // Constructs an IdentityTestEnvironment that builds and owns an
+ // IdentityManager. This private constructor is meant to only be called
+ // internally by IdentityTestEnvironment from other constructors.
+ IdentityTestEnvironment(
+ std::unique_ptr<IdentityManagerDependenciesOwner> dependencies_owner,
+ network::TestURLLoaderFactory* test_url_loader_factory,
+ AccountConsistencyMethod account_consistency);
+
+ // Constructs an IdentityTestEnvironment that uses the supplied
+ // |identity_manager|.
+ // For use only in contexts where IdentityManager and its dependencies are all
+ // unavoidably created by the embedder (e.g., //chrome-level unittests that
+ // use the ProfileKeyedServiceFactory infrastructure).
+ // NOTE: This constructor is for usage only in the special case of embedder
+ // unittests that must use the IdentityManager instance associated with the
+ // Profile. If you think you have another use case for it, contact
+ // blundell@chromium.org.
+ IdentityTestEnvironment(IdentityManager* identity_manager);
+
+ // IdentityManager::DiagnosticsObserver:
+ void OnAccessTokenRequested(const CoreAccountId& account_id,
+ const std::string& consumer_id,
+ const identity::ScopeSet& scopes) override;
+
+ // Handles the notification that an access token request was received for
+ // |account_id|. Invokes |on_access_token_request_callback_| if the latter
+ // is non-null *and* either |*pending_access_token_requester_| equals
+ // |account_id| or |pending_access_token_requester_| is empty.
+ void HandleOnAccessTokenRequested(CoreAccountId account_id);
+
+ // If a token request for |account_id| (or any account if nullopt) has already
+ // been made and not matched by a different call, returns immediately.
+ // Otherwise and runs a nested runloop until a matching access token request
+ // is observed.
+ void WaitForAccessTokenRequestIfNecessary(
+ base::Optional<CoreAccountId> account_id);
+
+ // Returns the FakeProfileOAuth2TokenService owned by IdentityManager.
+ FakeProfileOAuth2TokenService* fake_token_service();
+
+ // Owner of all dependencies that don't belong to IdentityManager.
+ std::unique_ptr<IdentityManagerDependenciesOwner> dependencies_owner_;
+
+ // This will be null if a TestSigninClient was provided to
+ // IdentityTestEnvironment's constructor.
+ std::unique_ptr<TestSigninClient> owned_signin_client_;
+
+ // Depending on which constructor is used, exactly one of these will be
+ // non-null. See the documentation on the constructor wherein IdentityManager
+ // is passed in for required lifetime invariants in that case.
+ std::unique_ptr<IdentityManager> owned_identity_manager_;
+ IdentityManager* raw_identity_manager_ = nullptr;
+
+ std::unique_ptr<TestIdentityManagerObserver> test_identity_manager_observer_;
+
+ base::OnceClosure on_access_token_requested_callback_;
+ std::vector<AccessTokenRequestState> requesters_;
+
+ // Create an IdentityManager instance for tests.
+ static std::unique_ptr<IdentityManager> BuildIdentityManagerForTests(
+ SigninClient* signin_client,
+ PrefService* pref_service,
+ base::FilePath user_data_dir,
+ AccountConsistencyMethod account_consistency =
+ AccountConsistencyMethod::kDisabled);
+
+ // Shared constructor initialization logic.
+ void Initialize();
+
+ base::WeakPtrFactory<IdentityTestEnvironment> weak_ptr_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(IdentityTestEnvironment);
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_TEST_ENVIRONMENT_H_
diff --git a/chromium/components/signin/public/identity_manager/identity_test_environment_unittest.cc b/chromium/components/signin/public/identity_manager/identity_test_environment_unittest.cc
new file mode 100644
index 00000000000..9c03209a972
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/identity_test_environment_unittest.cc
@@ -0,0 +1,57 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+
+#include "base/bind.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/signin/public/identity_manager/access_token_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace signin {
+
+class IdentityTestEnvironmentTest : public testing::Test {
+ public:
+ IdentityTestEnvironmentTest()
+ : scoped_task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::DEFAULT,
+ base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::
+ QUEUED) {}
+
+ ~IdentityTestEnvironmentTest() override {
+ scoped_task_environment_.RunUntilIdle();
+ }
+
+ private:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ DISALLOW_COPY_AND_ASSIGN(IdentityTestEnvironmentTest);
+};
+
+TEST_F(IdentityTestEnvironmentTest,
+ IdentityTestEnvironmentCancelsPendingRequestsOnDestruction) {
+ std::unique_ptr<IdentityTestEnvironment> identity_test_environment =
+ std::make_unique<IdentityTestEnvironment>();
+
+ identity_test_environment->MakePrimaryAccountAvailable("primary@example.com");
+ AccessTokenFetcher::TokenCallback callback = base::BindOnce(
+ [](GoogleServiceAuthError error, AccessTokenInfo access_token_info) {});
+ std::set<std::string> scopes{"scope"};
+
+ std::unique_ptr<AccessTokenFetcher> fetcher =
+ identity_test_environment->identity_manager()
+ ->CreateAccessTokenFetcherForAccount(
+ identity_test_environment->identity_manager()
+ ->GetPrimaryAccountId(),
+ "dummy_consumer", scopes, std::move(callback),
+ AccessTokenFetcher::Mode::kImmediate);
+
+ // Deleting the IdentityTestEnvironment should cancel any pending
+ // task in order to avoid use-after-free crashes. The destructor of
+ // the test will spin the runloop which would run
+ // IdentityTestEnvironment pending tasks if not canceled.
+ identity_test_environment.reset();
+ fetcher.reset();
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/identity_test_utils.cc b/chromium/components/signin/public/identity_manager/identity_test_utils.cc
new file mode 100644
index 00000000000..1cbd39b19bf
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/identity_test_utils.cc
@@ -0,0 +1,376 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/identity_test_utils.h"
+
+#include <vector>
+
+#include "base/run_loop.h"
+#include "build/build_config.h"
+#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h"
+#include "components/signin/internal/identity_manager/primary_account_manager.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
+#include "components/signin/public/base/list_accounts_test_utils.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/test_identity_manager_observer.h"
+#include "google_apis/gaia/gaia_auth_util.h"
+#include "google_apis/gaia/gaia_constants.h"
+
+#if defined(OS_ANDROID)
+#include "components/signin/internal/identity_manager/oauth2_token_service_delegate_android.h"
+#endif
+
+namespace signin {
+
+namespace {
+
+void WaitForLoadCredentialsToComplete(IdentityManager* identity_manager) {
+ base::RunLoop run_loop;
+ TestIdentityManagerObserver load_credentials_observer(identity_manager);
+ load_credentials_observer.SetOnRefreshTokensLoadedCallback(
+ run_loop.QuitClosure());
+
+ if (identity_manager->AreRefreshTokensLoaded())
+ return;
+
+ // Do NOT explicitly load credentials here:
+ // 1. It is not re-entrant and will DCHECK fail.
+ // 2. It should have been called by IdentityManager during its initialization.
+
+ run_loop.Run();
+}
+
+// Helper function that updates the refresh token for |account_id| to
+// |new_token|. Before updating the refresh token, blocks until refresh tokens
+// are loaded. After updating the token, blocks until the update is processed by
+// |identity_manager|.
+void UpdateRefreshTokenForAccount(
+ ProfileOAuth2TokenService* token_service,
+ AccountTrackerService* account_tracker_service,
+ IdentityManager* identity_manager,
+ const std::string& account_id,
+ const std::string& new_token) {
+ DCHECK_EQ(account_tracker_service->GetAccountInfo(account_id).account_id,
+ account_id)
+ << "To set the refresh token for an unknown account, use "
+ "MakeAccountAvailable()";
+
+ // Ensure that refresh tokens are loaded; some platforms enforce the invariant
+ // that refresh token mutation cannot occur until refresh tokens are loaded,
+ // and it is desired to eventually enforce that invariant across all
+ // platforms.
+ WaitForLoadCredentialsToComplete(identity_manager);
+
+ base::RunLoop run_loop;
+ TestIdentityManagerObserver token_updated_observer(identity_manager);
+ token_updated_observer.SetOnRefreshTokenUpdatedCallback(
+ run_loop.QuitClosure());
+
+ token_service->UpdateCredentials(account_id, new_token);
+
+ run_loop.Run();
+}
+
+} // namespace
+
+CoreAccountInfo SetPrimaryAccount(IdentityManager* identity_manager,
+ const std::string& email) {
+ DCHECK(!identity_manager->HasPrimaryAccount());
+ PrimaryAccountManager* primary_account_manager =
+ identity_manager->GetPrimaryAccountManager();
+ DCHECK(!primary_account_manager->IsAuthenticated());
+
+ AccountTrackerService* account_tracker_service =
+ identity_manager->GetAccountTrackerService();
+ AccountInfo account_info =
+ account_tracker_service->FindAccountInfoByEmail(email);
+ if (account_info.account_id.empty()) {
+ std::string gaia_id = GetTestGaiaIdForEmail(email);
+ account_tracker_service->SeedAccountInfo(gaia_id, email);
+ account_info = account_tracker_service->FindAccountInfoByEmail(email);
+ }
+
+ std::string gaia_id = account_info.gaia;
+ DCHECK(!gaia_id.empty());
+
+ primary_account_manager->SignIn(email);
+
+ DCHECK(primary_account_manager->IsAuthenticated());
+ DCHECK(identity_manager->HasPrimaryAccount());
+ return identity_manager->GetPrimaryAccountInfo();
+}
+
+void SetRefreshTokenForPrimaryAccount(IdentityManager* identity_manager,
+ const std::string& token_value) {
+ DCHECK(identity_manager->HasPrimaryAccount());
+ std::string account_id = identity_manager->GetPrimaryAccountId();
+ SetRefreshTokenForAccount(identity_manager, account_id, token_value);
+}
+
+void SetInvalidRefreshTokenForPrimaryAccount(
+ IdentityManager* identity_manager) {
+ DCHECK(identity_manager->HasPrimaryAccount());
+ std::string account_id = identity_manager->GetPrimaryAccountId();
+
+ SetInvalidRefreshTokenForAccount(identity_manager, account_id);
+}
+
+void RemoveRefreshTokenForPrimaryAccount(IdentityManager* identity_manager) {
+ if (!identity_manager->HasPrimaryAccount())
+ return;
+
+ std::string account_id = identity_manager->GetPrimaryAccountId();
+
+ RemoveRefreshTokenForAccount(identity_manager, account_id);
+}
+
+AccountInfo MakePrimaryAccountAvailable(IdentityManager* identity_manager,
+ const std::string& email) {
+ CoreAccountInfo account_info = SetPrimaryAccount(identity_manager, email);
+ SetRefreshTokenForPrimaryAccount(identity_manager);
+ base::Optional<AccountInfo> primary_account_info =
+ identity_manager->FindAccountInfoForAccountWithRefreshTokenByAccountId(
+ account_info.account_id);
+ // Ensure that extended information for the account is available after setting
+ // the refresh token.
+ DCHECK(primary_account_info.has_value());
+ return primary_account_info.value();
+}
+
+void ClearPrimaryAccount(IdentityManager* identity_manager,
+ ClearPrimaryAccountPolicy policy) {
+#if defined(OS_CHROMEOS)
+ // TODO(blundell): If we ever need this functionality on ChromeOS (which seems
+ // unlikely), plumb this through to just clear the primary account info
+ // synchronously with IdentityManager.
+ NOTREACHED();
+#else
+ if (!identity_manager->HasPrimaryAccount())
+ return;
+
+ base::RunLoop run_loop;
+ TestIdentityManagerObserver signout_observer(identity_manager);
+ signout_observer.SetOnPrimaryAccountClearedCallback(run_loop.QuitClosure());
+
+ PrimaryAccountManager* primary_account_manager =
+ identity_manager->GetPrimaryAccountManager();
+ signin_metrics::ProfileSignout signout_source_metric =
+ signin_metrics::SIGNOUT_TEST;
+ signin_metrics::SignoutDelete signout_delete_metric =
+ signin_metrics::SignoutDelete::IGNORE_METRIC;
+
+ switch (policy) {
+ case ClearPrimaryAccountPolicy::DEFAULT:
+ primary_account_manager->SignOut(signout_source_metric,
+ signout_delete_metric);
+ break;
+ case ClearPrimaryAccountPolicy::KEEP_ALL_ACCOUNTS:
+ primary_account_manager->SignOutAndKeepAllAccounts(signout_source_metric,
+ signout_delete_metric);
+ break;
+ case ClearPrimaryAccountPolicy::REMOVE_ALL_ACCOUNTS:
+ primary_account_manager->SignOutAndRemoveAllAccounts(
+ signout_source_metric, signout_delete_metric);
+ break;
+ }
+
+ run_loop.Run();
+#endif
+}
+
+AccountInfo MakeAccountAvailable(IdentityManager* identity_manager,
+ const std::string& email) {
+ AccountTrackerService* account_tracker_service =
+ identity_manager->GetAccountTrackerService();
+
+ DCHECK(account_tracker_service);
+ DCHECK(account_tracker_service->FindAccountInfoByEmail(email).IsEmpty());
+
+ // Wait until tokens are loaded, otherwise the account will be removed as soon
+ // as tokens finish loading.
+ WaitForLoadCredentialsToComplete(identity_manager);
+
+ std::string gaia_id = GetTestGaiaIdForEmail(email);
+ account_tracker_service->SeedAccountInfo(gaia_id, email);
+
+ AccountInfo account_info =
+ account_tracker_service->FindAccountInfoByEmail(email);
+ DCHECK(!account_info.account_id.empty());
+
+ SetRefreshTokenForAccount(identity_manager, account_info.account_id);
+
+ return account_info;
+}
+
+AccountInfo MakeAccountAvailableWithCookies(
+ IdentityManager* identity_manager,
+ network::TestURLLoaderFactory* test_url_loader_factory,
+ const std::string& email,
+ const std::string& gaia_id) {
+ AccountTrackerService* account_tracker_service =
+ identity_manager->GetAccountTrackerService();
+
+ DCHECK(account_tracker_service);
+ DCHECK(account_tracker_service->FindAccountInfoByEmail(email).IsEmpty());
+
+ // Wait until tokens are loaded, otherwise the account will be removed as soon
+ // as tokens finish loading.
+ WaitForLoadCredentialsToComplete(identity_manager);
+
+ SetCookieAccounts(identity_manager, test_url_loader_factory,
+ {{email, gaia_id}});
+
+ account_tracker_service->SeedAccountInfo(gaia_id, email);
+
+ AccountInfo account_info =
+ account_tracker_service->FindAccountInfoByEmail(email);
+ DCHECK(!account_info.account_id.empty());
+
+ SetRefreshTokenForAccount(identity_manager, account_info.account_id);
+
+ return account_info;
+}
+
+void SetRefreshTokenForAccount(IdentityManager* identity_manager,
+ const std::string& account_id,
+ const std::string& token_value) {
+ UpdateRefreshTokenForAccount(
+ identity_manager->GetTokenService(),
+ identity_manager->GetAccountTrackerService(), identity_manager,
+ account_id,
+ token_value.empty() ? "refresh_token_for_" + account_id : token_value);
+}
+
+void SetInvalidRefreshTokenForAccount(IdentityManager* identity_manager,
+ const std::string& account_id) {
+ UpdateRefreshTokenForAccount(identity_manager->GetTokenService(),
+
+ identity_manager->GetAccountTrackerService(),
+ identity_manager, account_id,
+ GaiaConstants::kInvalidRefreshToken);
+}
+
+void RemoveRefreshTokenForAccount(IdentityManager* identity_manager,
+ const std::string& account_id) {
+ if (!identity_manager->HasAccountWithRefreshToken(account_id))
+ return;
+
+ base::RunLoop run_loop;
+ TestIdentityManagerObserver token_updated_observer(identity_manager);
+ token_updated_observer.SetOnRefreshTokenRemovedCallback(
+ run_loop.QuitClosure());
+
+ identity_manager->GetTokenService()->RevokeCredentials(account_id);
+
+ run_loop.Run();
+}
+
+void SetCookieAccounts(
+ IdentityManager* identity_manager,
+ network::TestURLLoaderFactory* test_url_loader_factory,
+ const std::vector<CookieParamsForTest>& cookie_accounts) {
+ // Convert |cookie_accounts| to the format list_accounts_test_utils wants.
+ std::vector<CookieParams> gaia_cookie_accounts;
+ for (const CookieParamsForTest& params : cookie_accounts) {
+ gaia_cookie_accounts.push_back({params.email, params.gaia_id,
+ /*valid=*/true, /*signed_out=*/false,
+ /*verified=*/true});
+ }
+
+ base::RunLoop run_loop;
+ TestIdentityManagerObserver cookie_observer(identity_manager);
+ cookie_observer.SetOnAccountsInCookieUpdatedCallback(run_loop.QuitClosure());
+
+ SetListAccountsResponseWithParams(gaia_cookie_accounts,
+ test_url_loader_factory);
+
+ GaiaCookieManagerService* cookie_manager =
+ identity_manager->GetGaiaCookieManagerService();
+ cookie_manager->set_list_accounts_stale_for_testing(true);
+ cookie_manager->ListAccounts(nullptr, nullptr);
+
+ run_loop.Run();
+}
+
+void UpdateAccountInfoForAccount(IdentityManager* identity_manager,
+ AccountInfo account_info) {
+ // Make sure the account being updated is a known account.
+
+ AccountTrackerService* account_tracker_service =
+ identity_manager->GetAccountTrackerService();
+
+ DCHECK(account_tracker_service);
+ DCHECK(!account_tracker_service->GetAccountInfo(account_info.account_id)
+ .account_id.empty());
+
+ account_tracker_service->SeedAccountInfo(account_info);
+}
+
+void SetFreshnessOfAccountsInGaiaCookie(IdentityManager* identity_manager,
+ bool accounts_are_fresh) {
+ GaiaCookieManagerService* cookie_manager =
+ identity_manager->GetGaiaCookieManagerService();
+ cookie_manager->set_list_accounts_stale_for_testing(!accounts_are_fresh);
+}
+
+std::string GetTestGaiaIdForEmail(const std::string& email) {
+ std::string gaia_id =
+ std::string("gaia_id_for_") + gaia::CanonicalizeEmail(email);
+ // Avoid character '@' in the gaia ID string as there is code in the codebase
+ // that asserts that a gaia ID does not contain a "@" character.
+ std::replace(gaia_id.begin(), gaia_id.end(), '@', '_');
+ return gaia_id;
+}
+
+void UpdatePersistentErrorOfRefreshTokenForAccount(
+ IdentityManager* identity_manager,
+ const std::string& account_id,
+ const GoogleServiceAuthError& auth_error) {
+ DCHECK(identity_manager->HasAccountWithRefreshToken(account_id));
+ identity_manager->GetTokenService()->GetDelegate()->UpdateAuthError(
+ account_id, auth_error);
+}
+
+void DisableAccessTokenFetchRetries(IdentityManager* identity_manager) {
+ identity_manager->GetTokenService()
+ ->set_max_authorization_token_fetch_retries_for_testing(0);
+}
+
+#if defined(OS_ANDROID)
+void DisableInteractionWithSystemAccounts() {
+ OAuth2TokenServiceDelegateAndroid::
+ set_disable_interaction_with_system_accounts();
+}
+#endif
+
+void CancelAllOngoingGaiaCookieOperations(IdentityManager* identity_manager) {
+ identity_manager->GetGaiaCookieManagerService()->CancelAll();
+}
+
+void SimulateSuccessfulFetchOfAccountInfo(IdentityManager* identity_manager,
+ const std::string& account_id,
+ const std::string& email,
+ const std::string& gaia,
+ const std::string& hosted_domain,
+ const std::string& full_name,
+ const std::string& given_name,
+ const std::string& locale,
+ const std::string& picture_url) {
+ base::DictionaryValue user_info;
+ user_info.SetString("id", gaia);
+ user_info.SetString("email", email);
+ user_info.SetString("hd", hosted_domain);
+ user_info.SetString("name", full_name);
+ user_info.SetString("given_name", given_name);
+ user_info.SetString("locale", locale);
+ user_info.SetString("picture", picture_url);
+
+ AccountTrackerService* account_tracker_service =
+ identity_manager->GetAccountTrackerService();
+ account_tracker_service->SetAccountInfoFromUserInfo(account_id, &user_info);
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/identity_test_utils.h b/chromium/components/signin/public/identity_manager/identity_test_utils.h
new file mode 100644
index 00000000000..c7842e60214
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/identity_test_utils.h
@@ -0,0 +1,187 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_TEST_UTILS_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_TEST_UTILS_H_
+
+#include <string>
+
+#include "build/build_config.h"
+#include "components/signin/public/identity_manager/account_info.h"
+
+namespace network {
+class TestURLLoaderFactory;
+}
+
+class GoogleServiceAuthError;
+
+// Test-related utilities that don't fit in either IdentityTestEnvironment or
+// IdentityManager itself. NOTE: Using these utilities directly is discouraged,
+// but sometimes necessary during conversion. Use IdentityTestEnvironment if
+// possible. These utilities should be used directly only if the production code
+// is using IdentityManager, but it is not yet feasible to convert the test code
+// to use IdentityTestEnvironment. Any such usage should only be temporary,
+// i.e., should be followed as quickly as possible by conversion of the test
+// code to use IdentityTestEnvironment.
+namespace signin {
+
+// Controls whether to keep or remove accounts when clearing the primary
+// account.
+enum class ClearPrimaryAccountPolicy {
+ // Use the default internal policy.
+ DEFAULT,
+ // Explicitly keep all accounts.
+ KEEP_ALL_ACCOUNTS,
+ // Explicitly remove all accounts.
+ REMOVE_ALL_ACCOUNTS
+};
+
+struct CookieParamsForTest {
+ std::string email;
+ std::string gaia_id;
+};
+
+class IdentityManager;
+
+// Sets the primary account (which must not already be set) to the given email
+// address, generating a GAIA ID that corresponds uniquely to that email
+// address. On non-ChromeOS, results in the firing of the IdentityManager and
+// PrimaryAccountManager callbacks for signin success. Blocks until the primary
+// account is set. Returns the CoreAccountInfo of the newly-set account.
+// NOTE: See disclaimer at top of file re: direct usage.
+CoreAccountInfo SetPrimaryAccount(IdentityManager* identity_manager,
+ const std::string& email);
+
+// Sets a refresh token for the primary account (which must already be set).
+// Blocks until the refresh token is set. If |token_value| is empty a default
+// value will be used instead.
+// NOTE: See disclaimer at top of file re: direct usage.
+void SetRefreshTokenForPrimaryAccount(
+ IdentityManager* identity_manager,
+ const std::string& token_value = std::string());
+
+// Sets a special invalid refresh token for the primary account (which must
+// already be set). Blocks until the refresh token is set.
+// NOTE: See disclaimer at top of file re: direct usage.
+void SetInvalidRefreshTokenForPrimaryAccount(IdentityManager* identity_manager);
+
+// Removes any refresh token for the primary account, if present. Blocks until
+// the refresh token is removed.
+// NOTE: See disclaimer at top of file re: direct usage.
+void RemoveRefreshTokenForPrimaryAccount(IdentityManager* identity_manager);
+
+// Makes the primary account (which must not already be set) available for the
+// given email address, generating a GAIA ID and refresh token that correspond
+// uniquely to that email address. On non-ChromeOS, results in the firing of the
+// IdentityManager and PrimaryAccountManager callbacks for signin success.
+// Blocks until the primary account is available. Returns the AccountInfo of the
+// newly-available account.
+// NOTE: See disclaimer at top of file re: direct usage.
+AccountInfo MakePrimaryAccountAvailable(IdentityManager* identity_manager,
+ const std::string& email);
+
+// Clears the primary account if present, with |policy| used to determine
+// whether to keep or remove all accounts. On non-ChromeOS, results in the
+// firing of the IdentityManager and PrimaryAccountManager callbacks for
+// signout. Blocks until the primary account is cleared.
+// NOTE: See disclaimer at top of file re: direct usage.
+void ClearPrimaryAccount(
+ IdentityManager* identity_manager,
+ ClearPrimaryAccountPolicy policy = ClearPrimaryAccountPolicy::DEFAULT);
+
+// Makes an account available for the given email address, generating a GAIA ID
+// and refresh token that correspond uniquely to that email address. Blocks
+// until the account is available. Returns the AccountInfo of the
+// newly-available account.
+// NOTE: See disclaimer at top of file re: direct usage.
+AccountInfo MakeAccountAvailable(IdentityManager* identity_manager,
+ const std::string& email);
+
+// Combination of MakeAccountAvailable() and SetCookieAccounts() for a single
+// account. It makes an account available for the given email address, and GAIA
+// ID, setting the cookies and the refresh token that correspond uniquely to
+// that email address. Blocks until the account is available. Returns the
+// AccountInfo of the newly-available account.
+// NOTE: See disclaimer at top of file re: direct usage.
+AccountInfo MakeAccountAvailableWithCookies(
+ IdentityManager* identity_manager,
+ network::TestURLLoaderFactory* test_url_loader_factory,
+ const std::string& email,
+ const std::string& gaia_id);
+
+// Sets a refresh token for the given account (which must already be available).
+// Blocks until the refresh token is set. If |token_value| is empty a default
+// value will be used instead.
+// NOTE: See disclaimer at top of file re: direct usage.
+void SetRefreshTokenForAccount(IdentityManager* identity_manager,
+ const std::string& account_id,
+ const std::string& token_value = std::string());
+
+// Sets a special invalid refresh token for the given account (which must
+// already be available). Blocks until the refresh token is set.
+// NOTE: See disclaimer at top of file re: direct usage.
+void SetInvalidRefreshTokenForAccount(IdentityManager* identity_manager,
+ const std::string& account_id);
+
+// Removes any refresh token that is present for the given account. Blocks until
+// the refresh token is removed. Is a no-op if no refresh token is present for
+// the given account.
+// NOTE: See disclaimer at top of file re: direct usage.
+void RemoveRefreshTokenForAccount(IdentityManager* identity_manager,
+ const std::string& account_id);
+
+// Puts the given accounts into the Gaia cookie, replacing any previous
+// accounts. Blocks until the accounts have been set.
+// |test_url_loader_factory| is used to set a fake ListAccounts response
+// containing the provided |cookie_accounts|, which are then put into
+// the Gaia cookie.
+// NOTE: See disclaimer at top of file re: direct usage.
+void SetCookieAccounts(IdentityManager* identity_manager,
+ network::TestURLLoaderFactory* test_url_loader_factory,
+ const std::vector<CookieParamsForTest>& cookie_accounts);
+
+// Updates the info for |account_info.account_id|, which must be a known
+// account.
+void UpdateAccountInfoForAccount(IdentityManager* identity_manager,
+ AccountInfo account_info);
+
+// Sets whether the list of accounts in Gaia cookie jar is fresh and does not
+// need to be updated.
+void SetFreshnessOfAccountsInGaiaCookie(IdentityManager* identity_manager,
+ bool accounts_are_fresh);
+
+std::string GetTestGaiaIdForEmail(const std::string& email);
+
+// Updates the persistent auth error set on |account_id| which must be a known
+// account, i.e., an account with a refresh token.
+void UpdatePersistentErrorOfRefreshTokenForAccount(
+ IdentityManager* identity_manager,
+ const std::string& account_id,
+ const GoogleServiceAuthError& auth_error);
+
+// Disables internal retries of failed access token fetches.
+void DisableAccessTokenFetchRetries(IdentityManager* identity_manager);
+
+#if defined(OS_ANDROID)
+// Disables interaction with system accounts, which requires special permission.
+void DisableInteractionWithSystemAccounts();
+#endif
+
+// Cancels all ongoing operations related to the accounts in the Gaia cookie.
+void CancelAllOngoingGaiaCookieOperations(IdentityManager* identity_manager);
+
+// Simulate account fetching using AccountTrackerService without sending
+// network requests.
+void SimulateSuccessfulFetchOfAccountInfo(IdentityManager* identity_manager,
+ const std::string& account_id,
+ const std::string& email,
+ const std::string& gaia,
+ const std::string& hosted_domain,
+ const std::string& full_name,
+ const std::string& given_name,
+ const std::string& locale,
+ const std::string& picture_url);
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_TEST_UTILS_H_
diff --git a/chromium/components/signin/core/browser/identity_utils.cc b/chromium/components/signin/public/identity_manager/identity_utils.cc
index ed3cb950eac..11061a1d694 100644
--- a/chromium/components/signin/core/browser/identity_utils.cc
+++ b/chromium/components/signin/public/identity_manager/identity_utils.cc
@@ -2,16 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/identity_utils.h"
+#include "components/signin/public/identity_manager/identity_utils.h"
#include <string>
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/prefs/pref_service.h"
+#include "components/signin/public/base/signin_pref_names.h"
#include "third_party/icu/source/i18n/unicode/regex.h"
-namespace identity {
+namespace signin {
+
+namespace {
bool IsUsernameAllowedByPattern(base::StringPiece username,
base::StringPiece pattern) {
@@ -47,18 +50,12 @@ bool IsUsernameAllowedByPattern(base::StringPiece username,
return !!match; // !! == convert from UBool to bool.
}
-bool LegacyIsUsernameAllowedByPatternFromPrefs(
- PrefService* prefs,
- const std::string& username,
- const std::string& pattern_pref_name) {
- // TODO(crbug.com/908121): We need to deal for now with the fact that most
- // unit tests don't register a local state with the browser process, in which
- // case all usernames are considered 'allowed'.
- if (!prefs)
- return true;
+} // namespace
- return IsUsernameAllowedByPattern(username,
- prefs->GetString(pattern_pref_name));
+bool IsUsernameAllowedByPatternFromPrefs(const PrefService* prefs,
+ const std::string& username) {
+ return IsUsernameAllowedByPattern(
+ username, prefs->GetString(prefs::kGoogleServicesUsernamePattern));
}
-} // namespace identity
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/identity_utils.h b/chromium/components/signin/public/identity_manager/identity_utils.h
new file mode 100644
index 00000000000..62927ab4e7e
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/identity_utils.h
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Functions that are shared between the Identity Service implementation and its
+// consumers. Currently in //components/signin because they are used by classes
+// in this component, which cannot depend on //services/identity to avoid a
+// dependency cycle. When these classes have no direct consumers and are moved
+// to //services/identity, these functions should correspondingly be moved to
+// //services/identity/public/cpp.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_UTILS_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_UTILS_H_
+
+#include "base/strings/string_piece.h"
+
+class PrefService;
+
+namespace signin {
+
+// Returns true if the username is allowed based on a pattern registered
+// |prefs::kGoogleServicesUsernamePattern| with the preferences service
+// referenced by |prefs|.
+bool IsUsernameAllowedByPatternFromPrefs(const PrefService* prefs,
+ const std::string& username);
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_UTILS_H_
diff --git a/chromium/components/signin/public/identity_manager/identity_utils_unittest.cc b/chromium/components/signin/public/identity_manager/identity_utils_unittest.cc
new file mode 100644
index 00000000000..0be69ddf6f4
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/identity_utils_unittest.cc
@@ -0,0 +1,97 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/identity_utils.h"
+
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+const char kUsername[] = "test@test.com";
+
+const char kValidWildcardPattern[] = ".*@test.com";
+const char kInvalidWildcardPattern[] = "*@test.com";
+
+const char kMatchingPattern1[] = "test@test.com";
+const char kMatchingPattern2[] = ".*@test.com";
+const char kMatchingPattern3[] = "test@.*.com";
+const char kMatchingPattern4[] = ".*@.*.com";
+const char kMatchingPattern5[] = ".*@.*";
+const char kMatchingPattern6[] = ".*";
+
+const char kNonMatchingPattern[] = ".*foo.*";
+const char kNonMatchingUsernamePattern[] = "foo@test.com";
+const char kNonMatchingDomainPattern[] = "test@foo.com";
+} // namespace
+
+class IdentityUtilsTest : public testing::Test {
+ public:
+ IdentityUtilsTest() {
+ prefs_.registry()->RegisterStringPref(prefs::kGoogleServicesUsernamePattern,
+ std::string());
+ }
+
+ TestingPrefServiceSimple* prefs() { return &prefs_; }
+
+ private:
+ TestingPrefServiceSimple prefs_;
+};
+
+TEST_F(IdentityUtilsTest, IsUsernameAllowedByPatternFromPrefs_EmptyPatterns) {
+ prefs()->SetString(prefs::kGoogleServicesUsernamePattern, "");
+ EXPECT_TRUE(signin::IsUsernameAllowedByPatternFromPrefs(prefs(), kUsername));
+
+ prefs()->SetString(prefs::kGoogleServicesUsernamePattern, " ");
+ EXPECT_FALSE(signin::IsUsernameAllowedByPatternFromPrefs(prefs(), kUsername));
+}
+
+TEST_F(IdentityUtilsTest,
+ IsUsernameAllowedByPatternFromPrefs_InvalidWildcardPatterns) {
+ // signin::IsUsernameAllowedByPatternFromPrefs should recognize invalid
+ // wildcard patterns like "*@foo.com" and insert a "." before them
+ // automatically.
+ prefs()->SetString(prefs::kGoogleServicesUsernamePattern,
+ kValidWildcardPattern);
+ EXPECT_TRUE(signin::IsUsernameAllowedByPatternFromPrefs(prefs(), kUsername));
+
+ prefs()->SetString(prefs::kGoogleServicesUsernamePattern,
+ kInvalidWildcardPattern);
+ EXPECT_TRUE(signin::IsUsernameAllowedByPatternFromPrefs(prefs(), kUsername));
+}
+
+TEST_F(IdentityUtilsTest,
+ IsUsernameAllowedByPatternFromPrefs_MatchingWildcardPatterns) {
+ prefs()->SetString(prefs::kGoogleServicesUsernamePattern, kMatchingPattern1);
+ EXPECT_TRUE(signin::IsUsernameAllowedByPatternFromPrefs(prefs(), kUsername));
+
+ prefs()->SetString(prefs::kGoogleServicesUsernamePattern, kMatchingPattern2);
+ EXPECT_TRUE(signin::IsUsernameAllowedByPatternFromPrefs(prefs(), kUsername));
+
+ prefs()->SetString(prefs::kGoogleServicesUsernamePattern, kMatchingPattern3);
+ EXPECT_TRUE(signin::IsUsernameAllowedByPatternFromPrefs(prefs(), kUsername));
+
+ prefs()->SetString(prefs::kGoogleServicesUsernamePattern, kMatchingPattern4);
+ EXPECT_TRUE(signin::IsUsernameAllowedByPatternFromPrefs(prefs(), kUsername));
+
+ prefs()->SetString(prefs::kGoogleServicesUsernamePattern, kMatchingPattern5);
+ EXPECT_TRUE(signin::IsUsernameAllowedByPatternFromPrefs(prefs(), kUsername));
+
+ prefs()->SetString(prefs::kGoogleServicesUsernamePattern, kMatchingPattern6);
+ EXPECT_TRUE(signin::IsUsernameAllowedByPatternFromPrefs(prefs(), kUsername));
+
+ prefs()->SetString(prefs::kGoogleServicesUsernamePattern,
+ kNonMatchingPattern);
+ EXPECT_FALSE(signin::IsUsernameAllowedByPatternFromPrefs(prefs(), kUsername));
+
+ prefs()->SetString(prefs::kGoogleServicesUsernamePattern,
+ kNonMatchingUsernamePattern);
+ EXPECT_FALSE(signin::IsUsernameAllowedByPatternFromPrefs(prefs(), kUsername));
+
+ prefs()->SetString(prefs::kGoogleServicesUsernamePattern,
+ kNonMatchingDomainPattern);
+ EXPECT_FALSE(signin::IsUsernameAllowedByPatternFromPrefs(prefs(), kUsername));
+}
diff --git a/chromium/components/signin/public/identity_manager/ios/BUILD.gn b/chromium/components/signin/public/identity_manager/ios/BUILD.gn
new file mode 100644
index 00000000000..0f06fb4a39b
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/ios/BUILD.gn
@@ -0,0 +1,32 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("ios") {
+ configs += [ "//build/config/compiler:enable_arc" ]
+
+ sources = [
+ "device_accounts_provider.h",
+ "device_accounts_provider.mm",
+ ]
+
+ public_deps = [
+ "//base",
+ ]
+}
+
+source_set("test_support") {
+ configs += [ "//build/config/compiler:enable_arc" ]
+
+ testonly = true
+
+ sources = [
+ "fake_device_accounts_provider.h",
+ "fake_device_accounts_provider.mm",
+ ]
+
+ public_deps = [
+ ":ios",
+ "//base",
+ ]
+}
diff --git a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h b/chromium/components/signin/public/identity_manager/ios/device_accounts_provider.h
index 2696f19c368..bbb5bbc87f8 100644
--- a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h
+++ b/chromium/components/signin/public/identity_manager/ios/device_accounts_provider.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_IOS_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_IOS_PROVIDER_H_
-#define COMPONENTS_SIGNIN_IOS_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_IOS_PROVIDER_H_
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IOS_DEVICE_ACCOUNTS_PROVIDER_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IOS_DEVICE_ACCOUNTS_PROVIDER_H_
#if defined(__OBJC__)
@class NSDate;
@@ -37,21 +37,22 @@ enum AuthenticationErrorCategory {
kAuthenticationErrorCategoryUnknownIdentityErrors,
};
-// Interface that provides support for ProfileOAuth2TokenServiceIOS.
-class ProfileOAuth2TokenServiceIOSProvider {
+// Interface that provides a mechanism for interacting with the underlying
+// device accounts support.
+class DeviceAccountsProvider {
public:
// Account information.
struct AccountInfo {
std::string gaia;
std::string email;
+ std::string hosted_domain;
};
- typedef base::Callback<void(NSString* token,
- NSDate* expiration,
- NSError* error)> AccessTokenCallback;
+ using AccessTokenCallback = base::OnceCallback<
+ void(NSString* token, NSDate* expiration, NSError* error)>;
- ProfileOAuth2TokenServiceIOSProvider() {}
- virtual ~ProfileOAuth2TokenServiceIOSProvider() {}
+ DeviceAccountsProvider() {}
+ virtual ~DeviceAccountsProvider() {}
// Returns the ids of all accounts.
virtual std::vector<AccountInfo> GetAllAccounts() const;
@@ -61,7 +62,7 @@ class ProfileOAuth2TokenServiceIOSProvider {
virtual void GetAccessToken(const std::string& gaia_id,
const std::string& client_id,
const std::set<std::string>& scopes,
- const AccessTokenCallback& callback);
+ AccessTokenCallback callback);
// Returns the authentication error category of |error| associated with the
// account with id |gaia_id|.
@@ -70,4 +71,4 @@ class ProfileOAuth2TokenServiceIOSProvider {
NSError* error) const;
};
-#endif // COMPONENTS_SIGNIN_IOS_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_IOS_PROVIDER_H_
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IOS_DEVICE_ACCOUNTS_PROVIDER_H_
diff --git a/chromium/components/signin/public/identity_manager/ios/device_accounts_provider.mm b/chromium/components/signin/public/identity_manager/ios/device_accounts_provider.mm
new file mode 100644
index 00000000000..9e11272a25a
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/ios/device_accounts_provider.mm
@@ -0,0 +1,26 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/ios/device_accounts_provider.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+std::vector<DeviceAccountsProvider::AccountInfo>
+DeviceAccountsProvider::GetAllAccounts() const {
+ return std::vector<DeviceAccountsProvider::AccountInfo>();
+}
+
+void DeviceAccountsProvider::GetAccessToken(const std::string& gaia_id,
+ const std::string& client_id,
+ const std::set<std::string>& scopes,
+ AccessTokenCallback callback) {}
+
+AuthenticationErrorCategory
+DeviceAccountsProvider::GetAuthenticationErrorCategory(
+ const std::string& gaia_id,
+ NSError* error) const {
+ return kAuthenticationErrorCategoryUnknownErrors;
+}
diff --git a/chromium/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.h b/chromium/components/signin/public/identity_manager/ios/fake_device_accounts_provider.h
index 9fabc729041..c4b442d0149 100644
--- a/chromium/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.h
+++ b/chromium/components/signin/public/identity_manager/ios/fake_device_accounts_provider.h
@@ -2,29 +2,28 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef IOS_TEST_MOCK_PROFILE_OAUTH2_TOKEN_SERVICE_PROVIDER_IOS_H_
-#define IOS_TEST_MOCK_PROFILE_OAUTH2_TOKEN_SERVICE_PROVIDER_IOS_H_
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IOS_FAKE_DEVICE_ACCOUNTS_PROVIDER_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IOS_FAKE_DEVICE_ACCOUNTS_PROVIDER_H_
-#include <memory>
+#include <set>
#include <string>
#include <utility>
#include <vector>
#include "base/macros.h"
-#include "components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h"
+#include "components/signin/public/identity_manager/ios/device_accounts_provider.h"
-// Mock class of ProfileOAuth2TokenServiceIOSProvider for testing.
-class FakeProfileOAuth2TokenServiceIOSProvider
- : public ProfileOAuth2TokenServiceIOSProvider {
+// Mock class of DeviceAccountsProvider for testing.
+class FakeDeviceAccountsProvider : public DeviceAccountsProvider {
public:
- FakeProfileOAuth2TokenServiceIOSProvider();
- ~FakeProfileOAuth2TokenServiceIOSProvider() override;
+ FakeDeviceAccountsProvider();
+ ~FakeDeviceAccountsProvider() override;
- // ProfileOAuth2TokenServiceIOSProvider
+ // DeviceAccountsProvider
void GetAccessToken(const std::string& account_id,
const std::string& client_id,
const std::set<std::string>& scopes,
- const AccessTokenCallback& callback) override;
+ AccessTokenCallback callback) override;
std::vector<AccountInfo> GetAllAccounts() const override;
AuthenticationErrorCategory GetAuthenticationErrorCategory(
const std::string& gaia_id,
@@ -39,12 +38,12 @@ class FakeProfileOAuth2TokenServiceIOSProvider
void IssueAccessTokenErrorForAllRequests();
private:
- typedef std::pair<std::string, AccessTokenCallback> AccessTokenRequest;
+ using AccessTokenRequest = std::pair<std::string, AccessTokenCallback>;
std::vector<AccountInfo> accounts_;
std::vector<AccessTokenRequest> requests_;
- DISALLOW_COPY_AND_ASSIGN(FakeProfileOAuth2TokenServiceIOSProvider);
+ DISALLOW_COPY_AND_ASSIGN(FakeDeviceAccountsProvider);
};
-#endif // IOS_TEST_PROVIDER_CHROME_BROWSER_SIGNIN_MOCK_PROFILE_OAUTH2_TOKEN_SERVICE_PROVIDER_IOS_H_
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IOS_FAKE_DEVICE_ACCOUNTS_PROVIDER_H_
diff --git a/chromium/components/signin/public/identity_manager/ios/fake_device_accounts_provider.mm b/chromium/components/signin/public/identity_manager/ios/fake_device_accounts_provider.mm
new file mode 100644
index 00000000000..6c65e6d038a
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/ios/fake_device_accounts_provider.mm
@@ -0,0 +1,73 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/ios/fake_device_accounts_provider.h"
+
+#import <Foundation/Foundation.h>
+
+#include "base/logging.h"
+#include "base/strings/sys_string_conversions.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+FakeDeviceAccountsProvider::FakeDeviceAccountsProvider() {}
+
+FakeDeviceAccountsProvider::~FakeDeviceAccountsProvider() {}
+
+void FakeDeviceAccountsProvider::GetAccessToken(
+ const std::string& account_id,
+ const std::string& client_id,
+ const std::set<std::string>& scopes,
+ AccessTokenCallback callback) {
+ requests_.push_back(AccessTokenRequest(account_id, std::move(callback)));
+}
+
+std::vector<DeviceAccountsProvider::AccountInfo>
+FakeDeviceAccountsProvider::GetAllAccounts() const {
+ return accounts_;
+}
+
+DeviceAccountsProvider::AccountInfo FakeDeviceAccountsProvider::AddAccount(
+ const std::string& gaia,
+ const std::string& email) {
+ DeviceAccountsProvider::AccountInfo account;
+ account.gaia = gaia;
+ account.email = email;
+ accounts_.push_back(account);
+ return account;
+}
+
+void FakeDeviceAccountsProvider::ClearAccounts() {
+ accounts_.clear();
+}
+
+void FakeDeviceAccountsProvider::IssueAccessTokenForAllRequests() {
+ for (auto& pair : requests_) {
+ NSString* access_token = [NSString
+ stringWithFormat:@"fake_access_token [account=%s]", pair.first.c_str()];
+ NSDate* one_hour_from_now = [NSDate dateWithTimeIntervalSinceNow:3600];
+ std::move(pair.second).Run(access_token, one_hour_from_now, nil);
+ }
+ requests_.clear();
+}
+
+void FakeDeviceAccountsProvider::IssueAccessTokenErrorForAllRequests() {
+ for (auto& pair : requests_) {
+ NSError* error = [[NSError alloc] initWithDomain:@"fake_access_token_error"
+ code:-1
+ userInfo:nil];
+ std::move(pair.second).Run(nil, nil, error);
+ }
+ requests_.clear();
+}
+
+AuthenticationErrorCategory
+FakeDeviceAccountsProvider::GetAuthenticationErrorCategory(
+ const std::string& gaia_id,
+ NSError* error) const {
+ DCHECK(error);
+ return kAuthenticationErrorCategoryAuthorizationErrors;
+}
diff --git a/chromium/components/signin/public/identity_manager/load_credentials_state.h b/chromium/components/signin/public/identity_manager/load_credentials_state.h
new file mode 100644
index 00000000000..cd85058683d
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/load_credentials_state.h
@@ -0,0 +1,25 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_LOAD_CREDENTIALS_STATE_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_LOAD_CREDENTIALS_STATE_H_
+
+namespace signin {
+
+enum class LoadCredentialsState {
+ // Describes the status of the operation of loading OAuth2 refresh tokens from
+ // disk.
+ LOAD_CREDENTIALS_NOT_STARTED,
+ LOAD_CREDENTIALS_IN_PROGRESS,
+ LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ LOAD_CREDENTIALS_FINISHED_WITH_DB_CANNOT_BE_OPENED,
+ LOAD_CREDENTIALS_FINISHED_WITH_DB_ERRORS,
+ LOAD_CREDENTIALS_FINISHED_WITH_DECRYPT_ERRORS,
+ LOAD_CREDENTIALS_FINISHED_WITH_NO_TOKEN_FOR_PRIMARY_ACCOUNT,
+ LOAD_CREDENTIALS_FINISHED_WITH_UNKNOWN_ERRORS,
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_LOAD_CREDENTIALS_STATE_H_
diff --git a/chromium/components/signin/public/identity_manager/objc/BUILD.gn b/chromium/components/signin/public/identity_manager/objc/BUILD.gn
new file mode 100644
index 00000000000..ba323fe7dae
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/objc/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("objc") {
+ configs += [ "//build/config/compiler:enable_arc" ]
+ sources = [
+ "identity_manager_observer_bridge.h",
+ "identity_manager_observer_bridge.mm",
+ ]
+
+ public_deps = [
+ "//components/signin/public/identity_manager",
+ ]
+}
diff --git a/chromium/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h b/chromium/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h
new file mode 100644
index 00000000000..3101764cf00
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h
@@ -0,0 +1,75 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_OBJC_IDENTITY_MANAGER_OBSERVER_BRIDGE_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_OBJC_IDENTITY_MANAGER_OBSERVER_BRIDGE_H_
+
+#import <Foundation/Foundation.h>
+#include <vector>
+
+#include "components/signin/public/identity_manager/identity_manager.h"
+
+// Implement this protocol and pass your implementation into an
+// IdentityManagerObserverBridge object to receive IdentityManager observer
+// callbacks in Objective-C.
+@protocol IdentityManagerObserverBridgeDelegate <NSObject>
+
+@optional
+
+// These callbacks follow the semantics of the corresponding
+// IdentityManager::Observer callbacks. See the comments on
+// IdentityManager::Observer in identity_manager.h for the specification of
+// these semantics.
+
+- (void)onPrimaryAccountSet:(const CoreAccountInfo&)primaryAccountInfo;
+- (void)onPrimaryAccountCleared:
+ (const CoreAccountInfo&)previousPrimaryAccountInfo;
+- (void)onRefreshTokenUpdatedForAccount:(const CoreAccountInfo&)accountInfo;
+- (void)onRefreshTokenRemovedForAccount:(const std::string&)accountId;
+- (void)onRefreshTokensLoaded;
+- (void)onAccountsInCookieUpdated:
+ (const signin::AccountsInCookieJarInfo&)accountsInCookieJarInfo
+ error:(const GoogleServiceAuthError&)error;
+- (void)onEndBatchOfRefreshTokenStateChanges;
+
+@end
+
+namespace signin {
+
+// Bridge class that listens for |IdentityManager| notifications and
+// passes them to its Objective-C delegate.
+class IdentityManagerObserverBridge : public IdentityManager::Observer {
+ public:
+ IdentityManagerObserverBridge(
+ IdentityManager* identity_manager,
+ id<IdentityManagerObserverBridgeDelegate> delegate);
+ ~IdentityManagerObserverBridge() override;
+
+ // IdentityManager::Observer.
+ void OnPrimaryAccountSet(
+ const CoreAccountInfo& primary_account_info) override;
+ void OnPrimaryAccountCleared(
+ const CoreAccountInfo& previous_primary_account_info) override;
+ void OnRefreshTokenUpdatedForAccount(
+ const CoreAccountInfo& account_info) override;
+ void OnRefreshTokenRemovedForAccount(
+ const CoreAccountId& account_id) override;
+ void OnRefreshTokensLoaded() override;
+ void OnAccountsInCookieUpdated(
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+ const GoogleServiceAuthError& error) override;
+ void OnEndBatchOfRefreshTokenStateChanges() override;
+
+ private:
+ // Identity manager to observe.
+ IdentityManager* identity_manager_;
+ // Delegate to call.
+ __weak id<IdentityManagerObserverBridgeDelegate> delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(IdentityManagerObserverBridge);
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_OBJC_IDENTITY_MANAGER_OBSERVER_BRIDGE_H_
diff --git a/chromium/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.mm b/chromium/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.mm
new file mode 100644
index 00000000000..4826a43ca5a
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.mm
@@ -0,0 +1,77 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace signin {
+
+IdentityManagerObserverBridge::IdentityManagerObserverBridge(
+ IdentityManager* identity_manager,
+ id<IdentityManagerObserverBridgeDelegate> delegate)
+ : identity_manager_(identity_manager), delegate_(delegate) {
+ identity_manager_->AddObserver(this);
+}
+
+IdentityManagerObserverBridge::~IdentityManagerObserverBridge() {
+ identity_manager_->RemoveObserver(this);
+}
+
+void IdentityManagerObserverBridge::OnPrimaryAccountSet(
+ const CoreAccountInfo& primary_account_info) {
+ if ([delegate_ respondsToSelector:@selector(onPrimaryAccountSet:)]) {
+ [delegate_ onPrimaryAccountSet:primary_account_info];
+ }
+}
+
+void IdentityManagerObserverBridge::OnPrimaryAccountCleared(
+ const CoreAccountInfo& previous_primary_account_info) {
+ if ([delegate_ respondsToSelector:@selector(onPrimaryAccountCleared:)]) {
+ [delegate_ onPrimaryAccountCleared:previous_primary_account_info];
+ }
+}
+
+void IdentityManagerObserverBridge::OnRefreshTokenUpdatedForAccount(
+ const CoreAccountInfo& account_info) {
+ if ([delegate_
+ respondsToSelector:@selector(onRefreshTokenUpdatedForAccount:)]) {
+ [delegate_ onRefreshTokenUpdatedForAccount:account_info];
+ }
+}
+
+void IdentityManagerObserverBridge::OnRefreshTokenRemovedForAccount(
+ const CoreAccountId& account_id) {
+ if ([delegate_
+ respondsToSelector:@selector(onRefreshTokenRemovedForAccount:)]) {
+ [delegate_ onRefreshTokenRemovedForAccount:account_id.id];
+ }
+}
+
+void IdentityManagerObserverBridge::OnRefreshTokensLoaded() {
+ if ([delegate_ respondsToSelector:@selector(onRefreshTokensLoaded)]) {
+ [delegate_ onRefreshTokensLoaded];
+ }
+}
+
+void IdentityManagerObserverBridge::OnAccountsInCookieUpdated(
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+ const GoogleServiceAuthError& error) {
+ if ([delegate_ respondsToSelector:@selector(onAccountsInCookieUpdated:
+ error:)]) {
+ [delegate_ onAccountsInCookieUpdated:accounts_in_cookie_jar_info
+ error:error];
+ }
+}
+
+void IdentityManagerObserverBridge::OnEndBatchOfRefreshTokenStateChanges() {
+ if ([delegate_
+ respondsToSelector:@selector(onEndBatchOfRefreshTokenStateChanges)]) {
+ [delegate_ onEndBatchOfRefreshTokenStateChanges];
+ }
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.cc b/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.cc
new file mode 100644
index 00000000000..5a1415fa58a
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.cc
@@ -0,0 +1,125 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "components/signin/public/identity_manager/access_token_info.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+
+namespace signin {
+
+PrimaryAccountAccessTokenFetcher::PrimaryAccountAccessTokenFetcher(
+ const std::string& oauth_consumer_name,
+ IdentityManager* identity_manager,
+ const identity::ScopeSet& scopes,
+ AccessTokenFetcher::TokenCallback callback,
+ Mode mode)
+ : oauth_consumer_name_(oauth_consumer_name),
+ identity_manager_(identity_manager),
+ scopes_(scopes),
+ callback_(std::move(callback)),
+ identity_manager_observer_(this),
+ access_token_retried_(false),
+ mode_(mode) {
+ if (mode_ == Mode::kImmediate || AreCredentialsAvailable()) {
+ StartAccessTokenRequest();
+ return;
+ }
+
+ // Start observing the IdentityManager. This observer will be removed either
+ // when credentials are obtained and an access token request is started or
+ // when this object is destroyed.
+ identity_manager_observer_.Add(identity_manager_);
+}
+
+PrimaryAccountAccessTokenFetcher::~PrimaryAccountAccessTokenFetcher() {}
+
+bool PrimaryAccountAccessTokenFetcher::AreCredentialsAvailable() const {
+ DCHECK_EQ(Mode::kWaitUntilAvailable, mode_);
+
+ return identity_manager_->HasPrimaryAccountWithRefreshToken();
+}
+
+void PrimaryAccountAccessTokenFetcher::StartAccessTokenRequest() {
+ DCHECK(mode_ == Mode::kImmediate || AreCredentialsAvailable());
+
+ // By the time of starting an access token request, we should no longer be
+ // listening for signin-related events.
+ DCHECK(!identity_manager_observer_.IsObserving(identity_manager_));
+
+ // Note: We might get here even in cases where we know that there's no refresh
+ // token. We're requesting an access token anyway, so that the token service
+ // will generate an appropriate error code that we can return to the client.
+ DCHECK(!access_token_fetcher_);
+
+ // NOTE: This class does not utilize AccessTokenFetcher in its
+ // |kWaitUntilRefreshTokenAvailable| mode because the PAATF semantics specify
+ // that when used in *its* |kWaitUntilAvailable| mode, the access token
+ // request should be started when the account is primary AND has a refresh
+ // token available. AccessTokenFetcher used in
+ // |kWaitUntilRefreshTokenAvailable| mode would guarantee only the latter.
+ access_token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForAccount(
+ identity_manager_->GetPrimaryAccountId(), oauth_consumer_name_, scopes_,
+ base::BindOnce(
+ &PrimaryAccountAccessTokenFetcher::OnAccessTokenFetchComplete,
+ base::Unretained(this)),
+ AccessTokenFetcher::Mode::kImmediate);
+}
+
+void PrimaryAccountAccessTokenFetcher::OnPrimaryAccountSet(
+ const CoreAccountInfo& primary_account_info) {
+ ProcessSigninStateChange();
+}
+
+void PrimaryAccountAccessTokenFetcher::OnRefreshTokenUpdatedForAccount(
+ const CoreAccountInfo& account_info) {
+ ProcessSigninStateChange();
+}
+
+void PrimaryAccountAccessTokenFetcher::ProcessSigninStateChange() {
+ DCHECK_EQ(Mode::kWaitUntilAvailable, mode_);
+
+ if (!AreCredentialsAvailable())
+ return;
+
+ identity_manager_observer_.Remove(identity_manager_);
+
+ StartAccessTokenRequest();
+}
+
+void PrimaryAccountAccessTokenFetcher::OnAccessTokenFetchComplete(
+ GoogleServiceAuthError error,
+ AccessTokenInfo access_token_info) {
+ access_token_fetcher_.reset();
+
+ // There is a special case for Android that RefreshTokenIsAvailable and
+ // StartRequest are called to pre-fetch the account image and name before
+ // sign-in. In that case, our ongoing access token request gets cancelled.
+ // Moreover, OnRefreshTokenAvailable might happen after startup when the
+ // credentials are changed/updated.
+ // To handle these cases, we retry a canceled request once.
+ // However, a request may also get cancelled for legitimate reasons, e.g.
+ // because the user signed out. In those cases, there's no point in retrying,
+ // so only retry if there (still) is a valid refresh token.
+ // NOTE: Maybe we should retry for all transient errors here, so that clients
+ // don't have to.
+ if (mode_ == Mode::kWaitUntilAvailable && !access_token_retried_ &&
+ error.state() == GoogleServiceAuthError::State::REQUEST_CANCELED &&
+ AreCredentialsAvailable()) {
+ access_token_retried_ = true;
+ StartAccessTokenRequest();
+ return;
+ }
+
+ // Per the contract of this class, it is allowed for consumers to delete this
+ // object from within the callback that is run below. Hence, it is not safe to
+ // add any code below this call.
+ std::move(callback_).Run(std::move(error), std::move(access_token_info));
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.h b/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.h
new file mode 100644
index 00000000000..68436bc1958
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.h
@@ -0,0 +1,105 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_PRIMARY_ACCOUNT_ACCESS_TOKEN_FETCHER_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_PRIMARY_ACCOUNT_ACCESS_TOKEN_FETCHER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "base/scoped_observer.h"
+#include "components/signin/public/identity_manager/access_token_fetcher.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "services/identity/public/cpp/scope_set.h"
+
+class GoogleServiceAuthError;
+
+namespace signin {
+struct AccessTokenInfo;
+
+// Helper class to ease the task of obtaining an OAuth2 access token for the
+// authenticated account. This handles various special cases, e.g. when the
+// refresh token isn't loaded yet (during startup), or when there is some
+// transient error.
+// May only be used on the UI thread.
+class PrimaryAccountAccessTokenFetcher : public IdentityManager::Observer {
+ public:
+ // Specifies how this instance should behave:
+ // |kImmediate|: Makes one-shot immediate request.
+ // |kWaitUntilAvailable|: Waits for the primary account to be available
+ // before making the request. In particular, "available" is defined as the
+ // moment when (a) there is a primary account and (b) that account has a
+ // refresh token. This semantics is richer than using an AccessTokenFetcher in
+ // kWaitUntilRefreshTokenAvailable mode, as the latter will make a request
+ // once the specified account has a refresh token, regardless of whether it's
+ // the primary account at that point.
+ // Note that using |kWaitUntilAvailable| can result in waiting forever
+ // if the user is not signed in and doesn't sign in.
+ enum class Mode { kImmediate, kWaitUntilAvailable };
+
+ // Instantiates a fetcher and immediately starts the process of obtaining an
+ // OAuth2 access token for the given |scopes|. The |callback| is called once
+ // the request completes (successful or not). If the
+ // PrimaryAccountAccessTokenFetcher is destroyed before the process completes,
+ // the callback is not called.
+ PrimaryAccountAccessTokenFetcher(const std::string& oauth_consumer_name,
+ IdentityManager* identity_manager,
+ const identity::ScopeSet& scopes,
+ AccessTokenFetcher::TokenCallback callback,
+ Mode mode);
+
+ ~PrimaryAccountAccessTokenFetcher() override;
+
+ // Exposed for tests.
+ bool access_token_request_retried() { return access_token_retried_; }
+
+ private:
+ // Returns true iff there is a primary account with a refresh token. Should
+ // only be called in mode |kWaitUntilAvailable|.
+ bool AreCredentialsAvailable() const;
+
+ void StartAccessTokenRequest();
+
+ // IdentityManager::Observer implementation.
+ void OnPrimaryAccountSet(
+ const CoreAccountInfo& primary_account_info) override;
+ void OnRefreshTokenUpdatedForAccount(
+ const CoreAccountInfo& account_info) override;
+
+ // Checks whether credentials are now available and starts an access token
+ // request if so. Should only be called in mode |kWaitUntilAvailable|.
+ void ProcessSigninStateChange();
+
+ // Invoked by |fetcher_| when an access token request completes.
+ void OnAccessTokenFetchComplete(GoogleServiceAuthError error,
+ AccessTokenInfo access_token_info);
+
+ std::string oauth_consumer_name_;
+ IdentityManager* identity_manager_;
+ identity::ScopeSet scopes_;
+
+ // Per the contract of this class, it is allowed for clients to delete this
+ // object as part of the invocation of |callback_|. Hence, this object must
+ // assume that it is dead after invoking |callback_| and must not run any more
+ // code.
+ AccessTokenFetcher::TokenCallback callback_;
+
+ ScopedObserver<IdentityManager, PrimaryAccountAccessTokenFetcher>
+ identity_manager_observer_;
+
+ // Internal fetcher that does the actual access token request.
+ std::unique_ptr<AccessTokenFetcher> access_token_fetcher_;
+
+ // When a token request gets canceled, we want to retry once.
+ bool access_token_retried_;
+
+ Mode mode_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrimaryAccountAccessTokenFetcher);
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_PRIMARY_ACCOUNT_ACCESS_TOKEN_FETCHER_H_
diff --git a/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher_unittest.cc b/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher_unittest.cc
new file mode 100644
index 00000000000..b0136c69c2b
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher_unittest.cc
@@ -0,0 +1,401 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/test/mock_callback.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/signin/public/identity_manager/access_token_info.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gmock_mutant.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::MockCallback;
+using testing::CallbackToFunctor;
+using testing::InvokeWithoutArgs;
+using testing::StrictMock;
+
+namespace signin {
+
+namespace {
+
+void OnAccessTokenFetchComplete(
+ base::OnceClosure done_closure,
+ const GoogleServiceAuthError& expected_error,
+ const AccessTokenInfo& expected_access_token_info,
+ GoogleServiceAuthError error,
+ AccessTokenInfo access_token_info) {
+ EXPECT_EQ(expected_error, error);
+ if (expected_error == GoogleServiceAuthError::AuthErrorNone())
+ EXPECT_EQ(expected_access_token_info, access_token_info);
+
+ std::move(done_closure).Run();
+}
+
+} // namespace
+
+class PrimaryAccountAccessTokenFetcherTest : public testing::Test,
+ public IdentityManager::Observer {
+ public:
+ using TestTokenCallback =
+ StrictMock<MockCallback<AccessTokenFetcher::TokenCallback>>;
+
+ PrimaryAccountAccessTokenFetcherTest()
+ : access_token_info_("access token",
+ base::Time::Now() + base::TimeDelta::FromHours(1),
+ "id_token") {}
+
+ ~PrimaryAccountAccessTokenFetcherTest() override {}
+
+ std::unique_ptr<PrimaryAccountAccessTokenFetcher> CreateFetcher(
+ AccessTokenFetcher::TokenCallback callback,
+ PrimaryAccountAccessTokenFetcher::Mode mode) {
+ std::set<std::string> scopes{"scope"};
+ return std::make_unique<PrimaryAccountAccessTokenFetcher>(
+ "test_consumer", identity_test_env_.identity_manager(), scopes,
+ std::move(callback), mode);
+ }
+
+ IdentityTestEnvironment* identity_test_env() { return &identity_test_env_; }
+
+ // Signs the user in to the primary account, returning the account ID.
+ std::string SignIn() {
+ return identity_test_env_.MakePrimaryAccountAvailable("me@gmail.com")
+ .account_id;
+ }
+
+ // Returns an AccessTokenInfo with valid information that can be used for
+ // completing access token requests.
+ const AccessTokenInfo& access_token_info() const {
+ return access_token_info_;
+ }
+
+ private:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ IdentityTestEnvironment identity_test_env_;
+ AccessTokenInfo access_token_info_;
+};
+
+TEST_F(PrimaryAccountAccessTokenFetcherTest, OneShotShouldReturnAccessToken) {
+ TestTokenCallback callback;
+
+ std::string account_id = SignIn();
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(
+ callback.Get(), PrimaryAccountAccessTokenFetcher::Mode::kImmediate);
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback, Run(GoogleServiceAuthError::AuthErrorNone(),
+ access_token_info()));
+ identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token);
+}
+
+TEST_F(PrimaryAccountAccessTokenFetcherTest,
+ WaitAndRetryShouldReturnAccessToken) {
+ TestTokenCallback callback;
+
+ std::string account_id = SignIn();
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(
+ callback.Get(),
+ PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable);
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback, Run(GoogleServiceAuthError::AuthErrorNone(),
+ access_token_info()));
+ identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token);
+}
+
+TEST_F(PrimaryAccountAccessTokenFetcherTest, ShouldNotReplyIfDestroyed) {
+ TestTokenCallback callback;
+
+ std::string account_id = SignIn();
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(
+ callback.Get(), PrimaryAccountAccessTokenFetcher::Mode::kImmediate);
+
+ // Destroy the fetcher before the access token request is fulfilled.
+ fetcher.reset();
+
+ // Fulfilling the request now should have no effect.
+ identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token);
+}
+
+TEST_F(PrimaryAccountAccessTokenFetcherTest, OneShotCallsBackWhenSignedOut) {
+ base::RunLoop run_loop;
+
+ // Signed out -> we should get called back.
+ auto fetcher = CreateFetcher(
+ base::BindOnce(&OnAccessTokenFetchComplete, run_loop.QuitClosure(),
+ GoogleServiceAuthError(
+ GoogleServiceAuthError::State::USER_NOT_SIGNED_UP),
+ AccessTokenInfo()),
+ PrimaryAccountAccessTokenFetcher::Mode::kImmediate);
+
+ run_loop.Run();
+}
+
+TEST_F(PrimaryAccountAccessTokenFetcherTest,
+ OneShotCallsBackWhenNoRefreshToken) {
+ base::RunLoop run_loop;
+
+ identity_test_env()->SetPrimaryAccount("me@gmail.com");
+
+ // Signed in, but there is no refresh token -> we should get called back.
+ auto fetcher = CreateFetcher(
+ base::BindOnce(&OnAccessTokenFetchComplete, run_loop.QuitClosure(),
+ GoogleServiceAuthError(
+ GoogleServiceAuthError::State::USER_NOT_SIGNED_UP),
+ AccessTokenInfo()),
+ PrimaryAccountAccessTokenFetcher::Mode::kImmediate);
+
+ run_loop.Run();
+}
+
+TEST_F(PrimaryAccountAccessTokenFetcherTest,
+ WaitAndRetryNoCallbackWhenSignedOut) {
+ TestTokenCallback callback;
+
+ // Signed out -> the fetcher should wait for a sign-in which never happens
+ // in this test, so we shouldn't get called back.
+ auto fetcher = CreateFetcher(
+ callback.Get(),
+ PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable);
+}
+
+// Tests related to waiting for sign-in don't apply on ChromeOS (it doesn't have
+// that concept).
+#if !defined(OS_CHROMEOS)
+
+TEST_F(PrimaryAccountAccessTokenFetcherTest, ShouldWaitForSignIn) {
+ TestTokenCallback callback;
+
+ // Not signed in, so this should wait for a sign-in to complete.
+ auto fetcher = CreateFetcher(
+ callback.Get(),
+ PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable);
+
+ std::string account_id = SignIn();
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback, Run(GoogleServiceAuthError::AuthErrorNone(),
+ access_token_info()));
+ identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token);
+
+ // The request should not have to have been retried.
+ EXPECT_FALSE(fetcher->access_token_request_retried());
+}
+
+#endif // !OS_CHROMEOS
+
+TEST_F(PrimaryAccountAccessTokenFetcherTest, ShouldWaitForRefreshToken) {
+ TestTokenCallback callback;
+
+ std::string account_id =
+ identity_test_env()->SetPrimaryAccount("me@gmail.com").account_id;
+
+ // Signed in, but there is no refresh token -> we should not get called back
+ // (yet).
+ auto fetcher = CreateFetcher(
+ callback.Get(),
+ PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable);
+
+ // Getting a refresh token should result in a request for an access token.
+ identity_test_env()->SetRefreshTokenForPrimaryAccount();
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback, Run(GoogleServiceAuthError::AuthErrorNone(),
+ access_token_info()));
+ identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token);
+
+ // The request should not have to have been retried.
+ EXPECT_FALSE(fetcher->access_token_request_retried());
+}
+
+TEST_F(PrimaryAccountAccessTokenFetcherTest,
+ ShouldIgnoreRefreshTokensForOtherAccounts) {
+ TestTokenCallback callback;
+
+ // Signed-in to account_id, but there's only a refresh token for a different
+ // account.
+ std::string account_id =
+ identity_test_env()->SetPrimaryAccount("me@gmail.com").account_id;
+ identity_test_env()->MakeAccountAvailable(account_id + "2");
+
+ // The fetcher should wait for the correct refresh token.
+ auto fetcher = CreateFetcher(
+ callback.Get(),
+ PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable);
+
+ // A refresh token for yet another account shouldn't matter either.
+ identity_test_env()->MakeAccountAvailable(account_id + "3");
+}
+
+TEST_F(PrimaryAccountAccessTokenFetcherTest,
+ OneShotCanceledAccessTokenRequest) {
+ std::string account_id = SignIn();
+
+ base::RunLoop run_loop;
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(
+ base::BindOnce(
+ &OnAccessTokenFetchComplete, run_loop.QuitClosure(),
+ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
+ AccessTokenInfo()),
+ PrimaryAccountAccessTokenFetcher::Mode::kImmediate);
+
+ // A canceled access token request should result in a callback.
+ identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
+ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
+}
+
+TEST_F(PrimaryAccountAccessTokenFetcherTest,
+ WaitAndRetryCanceledAccessTokenRequest) {
+ TestTokenCallback callback;
+
+ std::string account_id = SignIn();
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(
+ callback.Get(),
+ PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable);
+
+ // A canceled access token request should get retried once.
+ identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
+ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback, Run(GoogleServiceAuthError::AuthErrorNone(),
+ access_token_info()));
+ identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ access_token_info().token, access_token_info().expiration_time,
+ access_token_info().id_token);
+}
+
+TEST_F(PrimaryAccountAccessTokenFetcherTest,
+ ShouldRetryCanceledAccessTokenRequestOnlyOnce) {
+ TestTokenCallback callback;
+
+ std::string account_id = SignIn();
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(
+ callback.Get(),
+ PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable);
+
+ // A canceled access token request should get retried once.
+ identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
+ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
+
+ // On the second failure, we should get called back with an empty access
+ // token.
+ EXPECT_CALL(
+ callback,
+ Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
+ AccessTokenInfo()));
+ identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
+ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
+}
+
+#if !defined(OS_CHROMEOS)
+
+TEST_F(PrimaryAccountAccessTokenFetcherTest,
+ ShouldNotRetryCanceledAccessTokenRequestIfSignedOut) {
+ TestTokenCallback callback;
+
+ std::string account_id = SignIn();
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(
+ callback.Get(),
+ PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable);
+
+ // Simulate the user signing out while the access token request is pending.
+ // In this case, the pending request gets canceled, and the fetcher should
+ // *not* retry.
+ EXPECT_CALL(
+ callback,
+ Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
+ AccessTokenInfo()));
+
+ identity_test_env()->ClearPrimaryAccount();
+}
+
+#endif // !OS_CHROMEOS
+
+TEST_F(PrimaryAccountAccessTokenFetcherTest,
+ ShouldNotRetryCanceledAccessTokenRequestIfRefreshTokenRevoked) {
+ TestTokenCallback callback;
+
+ std::string account_id = SignIn();
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(
+ callback.Get(),
+ PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable);
+
+ // Simulate the refresh token getting removed. In this case, pending
+ // access token requests get canceled, and the fetcher should *not* retry.
+ EXPECT_CALL(
+ callback,
+ Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
+ AccessTokenInfo()));
+ identity_test_env()->RemoveRefreshTokenForPrimaryAccount();
+}
+
+TEST_F(PrimaryAccountAccessTokenFetcherTest,
+ ShouldNotRetryFailedAccessTokenRequest) {
+ TestTokenCallback callback;
+
+ std::string account_id = SignIn();
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(
+ callback.Get(),
+ PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable);
+
+ // An access token failure other than "canceled" should not be retried; we
+ // should immediately get called back with an empty access token.
+ EXPECT_CALL(
+ callback,
+ Run(GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE),
+ AccessTokenInfo()));
+ identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
+ GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/primary_account_mutator.h b/chromium/components/signin/public/identity_manager/primary_account_mutator.h
new file mode 100644
index 00000000000..94755efd2cd
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/primary_account_mutator.h
@@ -0,0 +1,87 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_PRIMARY_ACCOUNT_MUTATOR_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_PRIMARY_ACCOUNT_MUTATOR_H_
+
+#include <string>
+
+namespace signin_metrics {
+enum ProfileSignout : int;
+enum class SignoutDelete;
+} // namespace signin_metrics
+
+struct CoreAccountId;
+
+namespace signin {
+
+// PrimaryAccountMutator is the interface to set and clear the primary account
+// (see IdentityManager for more information).
+//
+// It is a pure interface that has concrete implementation on platform that
+// support changing the signed-in state during the lifetime of the application.
+// On other platforms, there is no implementation, and no instance will be
+// available at runtime (thus accessors may return null).
+class PrimaryAccountMutator {
+ public:
+ // Represents the options for handling the accounts known to the
+ // IdentityManager upon calling ClearPrimaryAccount().
+ enum class ClearAccountsAction {
+ kDefault, // Default action based on internal policy.
+ kKeepAll, // Keep all accounts.
+ kRemoveAll, // Remove all accounts.
+ };
+
+ PrimaryAccountMutator() = default;
+ virtual ~PrimaryAccountMutator() = default;
+
+ // PrimaryAccountMutator is non-copyable, non-moveable.
+ PrimaryAccountMutator(PrimaryAccountMutator&& other) = delete;
+ PrimaryAccountMutator const& operator=(PrimaryAccountMutator&& other) =
+ delete;
+
+ PrimaryAccountMutator(const PrimaryAccountMutator& other) = delete;
+ PrimaryAccountMutator const& operator=(const PrimaryAccountMutator& other) =
+ delete;
+
+ // Marks the account with |account_id| as the primary account, and returns
+ // whether the operation succeeded or not. To succeed, this requires that:
+ // - the account is known by the IdentityManager.
+ // On non-ChromeOS platforms, this additionally requires that:
+ // - setting the primary account is allowed,
+ // - the account username is allowed by policy,
+ // - there is not already a primary account set.
+ // TODO(https://crbug.com/983124): Investigate adding all the extra
+ // requirements on ChromeOS as well.
+ virtual bool SetPrimaryAccount(const CoreAccountId& account_id) = 0;
+
+#if defined(OS_CHROMEOS)
+ // Updates the info of the account corresponding to (|gaia_id|, |email|),
+ // marks it as the primary account, and returns whether the operation
+ // succeeded or not. Currently, this method is guaranteed to succeed.
+ // NOTE: Unlike SetPrimaryAccount(), this method does not require that the
+ // account is known by IdentityManager. The reason is that there are
+ // contexts on ChromeOS where the primary account is not guaranteed to be
+ // known by IdentityManager when it is set.
+ // TODO(https://crbug.com/967605): Port callers to SetPrimaryAccount() once
+ // https://crbug.com/867602 is fixed.
+ virtual bool SetPrimaryAccountAndUpdateAccountInfo(
+ const std::string& gaia_id,
+ const std::string& email) = 0;
+#endif
+
+#if !defined(OS_CHROMEOS)
+ // Clears the primary account, and returns whether the operation
+ // succeeded or not. Depending on |action|, the other accounts
+ // known to the IdentityManager may be deleted.
+ virtual bool ClearPrimaryAccount(
+ ClearAccountsAction action,
+ signin_metrics::ProfileSignout source_metric,
+ signin_metrics::SignoutDelete delete_metric) = 0;
+#endif
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_PRIMARY_ACCOUNT_MUTATOR_H_
diff --git a/chromium/components/signin/public/identity_manager/primary_account_mutator_unittest.cc b/chromium/components/signin/public/identity_manager/primary_account_mutator_unittest.cc
new file mode 100644
index 00000000000..a18d03c290f
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/primary_account_mutator_unittest.cc
@@ -0,0 +1,499 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/primary_account_mutator.h"
+
+#include "base/bind.h"
+#include "base/containers/flat_set.h"
+#include "base/run_loop.h"
+#include "base/scoped_observer.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "components/signin/public/identity_manager/identity_test_utils.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+// Constants used by the different tests.
+const char kPrimaryAccountEmail[] = "primary.account@example.com";
+#if !defined(OS_CHROMEOS)
+const char kAnotherAccountEmail[] = "another.account@example.com";
+const char kUnknownAccountId[] = "{unknown account id}";
+
+// All account consistency methods that are tested by those unit tests when
+// testing ClearPrimaryAccount method.
+const signin::AccountConsistencyMethod kTestedAccountConsistencyMethods[] = {
+ signin::AccountConsistencyMethod::kDisabled,
+ signin::AccountConsistencyMethod::kMirror,
+ signin::AccountConsistencyMethod::kDiceMigration,
+ signin::AccountConsistencyMethod::kDice,
+};
+
+// See RunClearPrimaryAccountTest().
+enum class AuthExpectation { kAuthNormal, kAuthError };
+enum class RemoveAccountExpectation { kKeepAll, kRemovePrimary, kRemoveAll };
+
+// This callback will be invoked every time the IdentityManager::Observer
+// method OnPrimaryAccountCleared is invoked. The parameter will be a
+// reference to the still valid primary account that was cleared.
+using PrimaryAccountClearedCallback =
+ base::RepeatingCallback<void(const CoreAccountInfo&)>;
+
+// This callback will be invoked every time the IdentityManager::Observer
+// method OnRefreshTokenRemoved is invoked. The parameter will be a reference
+// to the account_id whose token was removed.
+using RefreshTokenRemovedCallback =
+ base::RepeatingCallback<void(const std::string&)>;
+
+// Helper IdentityManager::Observer that forwards some events to the
+// callback passed to the constructor.
+class ClearPrimaryAccountTestObserver
+ : public signin::IdentityManager::Observer {
+ public:
+ ClearPrimaryAccountTestObserver(
+ signin::IdentityManager* identity_manager,
+ PrimaryAccountClearedCallback on_primary_account_cleared,
+ RefreshTokenRemovedCallback on_refresh_token_removed)
+ : on_primary_account_cleared_(std::move(on_primary_account_cleared)),
+ on_refresh_token_removed_(std::move(on_refresh_token_removed)),
+ scoped_observer_(this) {
+ DCHECK(on_primary_account_cleared_);
+ DCHECK(on_refresh_token_removed_);
+ scoped_observer_.Add(identity_manager);
+ }
+
+ // signin::IdentityManager::Observer implementation.
+ void OnPrimaryAccountCleared(const CoreAccountInfo& account_info) override {
+ on_primary_account_cleared_.Run(account_info);
+ }
+
+ void OnRefreshTokenRemovedForAccount(
+ const CoreAccountId& account_id) override {
+ on_refresh_token_removed_.Run(account_id);
+ }
+
+ private:
+ PrimaryAccountClearedCallback on_primary_account_cleared_;
+ RefreshTokenRemovedCallback on_refresh_token_removed_;
+ ScopedObserver<signin::IdentityManager, signin::IdentityManager::Observer>
+ scoped_observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(ClearPrimaryAccountTestObserver);
+};
+
+// Helper for testing of ClearPrimaryAccount(). This function requires lots
+// of tests due to having different behaviors based on its arguments. But the
+// setup and execution of these test is all the boiler plate you see here:
+// 1) Ensure you have 2 accounts, both with refresh tokens
+// 2) Clear the primary account
+// 3) Assert clearing succeeds and refresh tokens are optionally removed based
+// on arguments.
+//
+// Optionally, it's possible to specify whether a normal auth process will
+// take place, or whether an auth error should happen, useful for some tests.
+void RunClearPrimaryAccountTest(
+ signin::AccountConsistencyMethod account_consistency_method,
+ signin::PrimaryAccountMutator::ClearAccountsAction account_action,
+ RemoveAccountExpectation account_expectation,
+ AuthExpectation auth_expection = AuthExpectation::kAuthNormal) {
+ base::test::ScopedTaskEnvironment task_environment;
+ signin::IdentityTestEnvironment environment(
+ /*test_url_loader_factory=*/nullptr, /*pref_service=*/nullptr,
+ account_consistency_method);
+
+ signin::IdentityManager* identity_manager = environment.identity_manager();
+ signin::PrimaryAccountMutator* primary_account_mutator =
+ identity_manager->GetPrimaryAccountMutator();
+
+ // Abort the test if the current platform does not support mutation of the
+ // primary account (the returned PrimaryAccountMutator* will be null).
+ if (!primary_account_mutator)
+ return;
+
+ // With the exception of ClearPrimaryAccount_AuthInProgress, every other
+ // ClearPrimaryAccount_* test requires a primary account to be signed in.
+ EXPECT_FALSE(identity_manager->HasPrimaryAccount());
+ AccountInfo account_info =
+ environment.MakeAccountAvailable(kPrimaryAccountEmail);
+ EXPECT_TRUE(
+ primary_account_mutator->SetPrimaryAccount(account_info.account_id));
+ EXPECT_TRUE(identity_manager->HasPrimaryAccount());
+ EXPECT_TRUE(identity_manager->HasPrimaryAccountWithRefreshToken());
+
+ EXPECT_EQ(identity_manager->GetPrimaryAccountId(), account_info.account_id);
+ EXPECT_EQ(identity_manager->GetPrimaryAccountInfo().email,
+ kPrimaryAccountEmail);
+
+ if (auth_expection == AuthExpectation::kAuthError) {
+ // Set primary account to have authentication error.
+ SetRefreshTokenForPrimaryAccount(identity_manager);
+ signin::UpdatePersistentErrorOfRefreshTokenForAccount(
+ identity_manager, account_info.account_id,
+ GoogleServiceAuthError(
+ GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS));
+ }
+
+ // Additionally, ClearPrimaryAccount_* tests also need a secondary account.
+ AccountInfo secondary_account_info =
+ environment.MakeAccountAvailable(kAnotherAccountEmail);
+ EXPECT_TRUE(identity_manager->HasAccountWithRefreshToken(
+ secondary_account_info.account_id));
+
+ // Grab this before clearing for token checks below.
+ auto former_primary_account = identity_manager->GetPrimaryAccountInfo();
+
+ // Make sure we exit the run loop.
+ base::RunLoop run_loop;
+ PrimaryAccountClearedCallback primary_account_cleared_callback =
+ base::BindRepeating([](base::RepeatingClosure quit_closure,
+ const CoreAccountInfo&) { quit_closure.Run(); },
+ run_loop.QuitClosure());
+
+ // Track Observer token removal notification.
+ base::flat_set<std::string> observed_removals;
+ RefreshTokenRemovedCallback refresh_token_removed_callback =
+ base::BindRepeating(
+ [](base::flat_set<std::string>* observed_removals,
+ const std::string& removed_account) {
+ observed_removals->insert(removed_account);
+ },
+ &observed_removals);
+
+ ClearPrimaryAccountTestObserver scoped_observer(
+ identity_manager, primary_account_cleared_callback,
+ refresh_token_removed_callback);
+
+ primary_account_mutator->ClearPrimaryAccount(
+ account_action, signin_metrics::SIGNOUT_TEST,
+ signin_metrics::SignoutDelete::IGNORE_METRIC);
+ run_loop.Run();
+
+ EXPECT_FALSE(identity_manager->HasPrimaryAccount());
+ // NOTE: IdentityManager _may_ still possess this token (see switch below),
+ // but it is no longer considered part of the primary account.
+ EXPECT_FALSE(identity_manager->HasPrimaryAccountWithRefreshToken());
+
+ switch (account_expectation) {
+ case RemoveAccountExpectation::kKeepAll:
+ EXPECT_TRUE(identity_manager->HasAccountWithRefreshToken(
+ former_primary_account.account_id));
+ EXPECT_TRUE(identity_manager->HasAccountWithRefreshToken(
+ secondary_account_info.account_id));
+ EXPECT_TRUE(observed_removals.empty());
+ break;
+ case RemoveAccountExpectation::kRemovePrimary:
+ EXPECT_FALSE(identity_manager->HasAccountWithRefreshToken(
+ former_primary_account.account_id));
+ EXPECT_TRUE(identity_manager->HasAccountWithRefreshToken(
+ secondary_account_info.account_id));
+ EXPECT_TRUE(base::Contains(observed_removals,
+ former_primary_account.account_id.id));
+ EXPECT_FALSE(base::Contains(observed_removals,
+ secondary_account_info.account_id.id));
+ break;
+ case RemoveAccountExpectation::kRemoveAll:
+ EXPECT_FALSE(identity_manager->HasAccountWithRefreshToken(
+ former_primary_account.account_id));
+ EXPECT_FALSE(identity_manager->HasAccountWithRefreshToken(
+ secondary_account_info.account_id));
+ EXPECT_TRUE(base::Contains(observed_removals,
+ former_primary_account.account_id.id));
+ EXPECT_TRUE(base::Contains(observed_removals,
+ secondary_account_info.account_id.id));
+ break;
+ }
+}
+#endif // !defined(OS_CHROMEOS)
+
+} // namespace
+
+using PrimaryAccountMutatorTest = PlatformTest;
+
+// Checks that setting the primary account works.
+TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount) {
+ base::test::ScopedTaskEnvironment task_environment;
+ signin::IdentityTestEnvironment environment;
+
+ signin::IdentityManager* identity_manager = environment.identity_manager();
+ signin::PrimaryAccountMutator* primary_account_mutator =
+ identity_manager->GetPrimaryAccountMutator();
+
+ // Abort the test if the current platform does not support mutation of the
+ // primary account (the returned PrimaryAccountMutator* will be null).
+ if (!primary_account_mutator)
+ return;
+
+ AccountInfo account_info =
+ environment.MakeAccountAvailable(kPrimaryAccountEmail);
+
+ EXPECT_FALSE(environment.identity_manager()->HasPrimaryAccount());
+ EXPECT_TRUE(
+ primary_account_mutator->SetPrimaryAccount(account_info.account_id));
+
+ EXPECT_TRUE(identity_manager->HasPrimaryAccount());
+ EXPECT_EQ(identity_manager->GetPrimaryAccountId(), account_info.account_id);
+}
+
+// Tests that various preconditions of SetPrimaryAccount() not being satisfied
+// should cause the setting of the primary account to fail. Not run on
+// ChromeOS, where those preconditions do not exist.
+// TODO(https://crbug.com/983124): Run these tests on ChromeOS if/once we
+// enable those preconditions on that platform
+#if !defined(OS_CHROMEOS)
+// Checks that setting the primary account fails if the account is not known by
+// the identity service.
+TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount_NoAccount) {
+ base::test::ScopedTaskEnvironment task_environment;
+ signin::IdentityTestEnvironment environment;
+
+ signin::IdentityManager* identity_manager = environment.identity_manager();
+ signin::PrimaryAccountMutator* primary_account_mutator =
+ identity_manager->GetPrimaryAccountMutator();
+
+ // Abort the test if the current platform does not support mutation of the
+ // primary account (the returned PrimaryAccountMutator* will be null).
+ if (!primary_account_mutator)
+ return;
+
+ EXPECT_FALSE(identity_manager->HasPrimaryAccount());
+ EXPECT_FALSE(primary_account_mutator->SetPrimaryAccount(kUnknownAccountId));
+}
+
+// Checks that setting the primary account fails if the account is unknown.
+TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount_UnknownAccount) {
+ base::test::ScopedTaskEnvironment task_environment;
+ signin::IdentityTestEnvironment environment;
+
+ signin::IdentityManager* identity_manager = environment.identity_manager();
+ signin::PrimaryAccountMutator* primary_account_mutator =
+ identity_manager->GetPrimaryAccountMutator();
+
+ // Abort the test if the current platform does not support mutation of the
+ // primary account (the returned PrimaryAccountMutator* will be null).
+ if (!primary_account_mutator)
+ return;
+
+ AccountInfo account_info =
+ environment.MakeAccountAvailable(kPrimaryAccountEmail);
+
+ EXPECT_FALSE(identity_manager->HasPrimaryAccount());
+ EXPECT_FALSE(primary_account_mutator->SetPrimaryAccount(kUnknownAccountId));
+}
+
+// Checks that trying to set the primary account fails when there is already a
+// primary account.
+TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount_AlreadyHasPrimaryAccount) {
+ base::test::ScopedTaskEnvironment task_environment;
+ signin::IdentityTestEnvironment environment;
+
+ signin::IdentityManager* identity_manager = environment.identity_manager();
+ signin::PrimaryAccountMutator* primary_account_mutator =
+ identity_manager->GetPrimaryAccountMutator();
+
+ // Abort the test if the current platform does not support mutation of the
+ // primary account (the returned PrimaryAccountMutator* will be null).
+ if (!primary_account_mutator)
+ return;
+
+ AccountInfo primary_account_info =
+ environment.MakeAccountAvailable(kPrimaryAccountEmail);
+ AccountInfo another_account_info =
+ environment.MakeAccountAvailable(kAnotherAccountEmail);
+
+ EXPECT_FALSE(identity_manager->HasPrimaryAccount());
+ EXPECT_TRUE(primary_account_mutator->SetPrimaryAccount(
+ primary_account_info.account_id));
+
+ EXPECT_TRUE(identity_manager->HasPrimaryAccount());
+ EXPECT_FALSE(primary_account_mutator->SetPrimaryAccount(
+ another_account_info.account_id));
+
+ EXPECT_EQ(identity_manager->GetPrimaryAccountId(),
+ primary_account_info.account_id);
+}
+
+// Checks that trying to set the primary account fails if setting the primary
+// account is not allowed.
+TEST_F(PrimaryAccountMutatorTest,
+ SetPrimaryAccount_SettingPrimaryAccountForbidden) {
+ base::test::ScopedTaskEnvironment task_environment;
+
+ sync_preferences::TestingPrefServiceSyncable pref_service;
+ signin::IdentityTestEnvironment environment(
+ /*test_url_loader_factory=*/nullptr, &pref_service);
+
+ signin::IdentityManager* identity_manager = environment.identity_manager();
+ signin::PrimaryAccountMutator* primary_account_mutator =
+ identity_manager->GetPrimaryAccountMutator();
+
+ // Abort the test if the current platform does not support mutation of the
+ // primary account (the returned PrimaryAccountMutator* will be null).
+ if (!primary_account_mutator)
+ return;
+
+ AccountInfo primary_account_info =
+ environment.MakeAccountAvailable(kPrimaryAccountEmail);
+
+ // Configure prefs so that setting the primary account is disallowed.
+ pref_service.SetBoolean(prefs::kSigninAllowed, false);
+
+ EXPECT_FALSE(identity_manager->HasPrimaryAccount());
+ EXPECT_FALSE(primary_account_mutator->SetPrimaryAccount(
+ primary_account_info.account_id));
+}
+#endif // !defined(OS_CHROMEOS)
+
+// End of tests of preconditions not being satisfied causing the setting of
+// the primary account to fail.
+
+// Tests of clearing the primary account. Not run on ChromeOS, which does not
+// support clearing the primary account.
+#if !defined(OS_CHROMEOS)
+TEST_F(PrimaryAccountMutatorTest, ClearPrimaryAccount_NotSignedIn) {
+ base::test::ScopedTaskEnvironment task_environment;
+ signin::IdentityTestEnvironment environment;
+
+ signin::IdentityManager* identity_manager = environment.identity_manager();
+ signin::PrimaryAccountMutator* primary_account_mutator =
+ identity_manager->GetPrimaryAccountMutator();
+
+ // Abort the test if the current platform does not support mutation of the
+ // primary account (the returned PrimaryAccountMutator* will be null).
+ if (!primary_account_mutator)
+ return;
+
+ // Trying to signout an account that hasn't signed in first should fail.
+ EXPECT_FALSE(identity_manager->HasPrimaryAccount());
+ EXPECT_FALSE(primary_account_mutator->ClearPrimaryAccount(
+ signin::PrimaryAccountMutator::ClearAccountsAction::kDefault,
+ signin_metrics::SIGNOUT_TEST,
+ signin_metrics::SignoutDelete::IGNORE_METRIC));
+
+ // Adding an account without signing in should yield similar a result.
+ AccountInfo primary_account_info =
+ environment.MakeAccountAvailable(kPrimaryAccountEmail);
+
+ EXPECT_FALSE(identity_manager->HasPrimaryAccount());
+ EXPECT_FALSE(primary_account_mutator->ClearPrimaryAccount(
+ signin::PrimaryAccountMutator::ClearAccountsAction::kDefault,
+ signin_metrics::SIGNOUT_TEST,
+ signin_metrics::SignoutDelete::IGNORE_METRIC));
+}
+
+TEST_F(PrimaryAccountMutatorTest, ClearPrimaryAccount_Default) {
+ base::test::ScopedTaskEnvironment task_environment;
+ signin::IdentityTestEnvironment environment;
+
+ signin::IdentityManager* identity_manager = environment.identity_manager();
+ signin::PrimaryAccountMutator* primary_account_mutator =
+ identity_manager->GetPrimaryAccountMutator();
+
+ // Abort the test if the current platform does not support mutation of the
+ // primary account (the returned PrimaryAccountMutator* will be null).
+ if (!primary_account_mutator)
+ return;
+
+ // This test requires two accounts to be made available.
+ AccountInfo primary_account_info =
+ environment.MakeAccountAvailable(kPrimaryAccountEmail);
+ AccountInfo other_account_info =
+ environment.MakeAccountAvailable(kAnotherAccountEmail);
+
+ EXPECT_FALSE(identity_manager->HasPrimaryAccount());
+ EXPECT_TRUE(identity_manager->HasAccountWithRefreshToken(
+ primary_account_info.account_id));
+ EXPECT_TRUE(identity_manager->HasAccountWithRefreshToken(
+ other_account_info.account_id));
+
+ // Sign in the primary account to check ClearPrimaryAccount() later on.
+ primary_account_mutator->SetPrimaryAccount(primary_account_info.account_id);
+ EXPECT_TRUE(identity_manager->HasPrimaryAccount());
+ EXPECT_EQ(identity_manager->GetPrimaryAccountId(),
+ primary_account_info.account_id);
+
+ EXPECT_TRUE(primary_account_mutator->ClearPrimaryAccount(
+ signin::PrimaryAccountMutator::ClearAccountsAction::kDefault,
+ signin_metrics::SIGNOUT_TEST,
+ signin_metrics::SignoutDelete::IGNORE_METRIC));
+
+ // The underlying PrimaryAccountManager in IdentityTestEnvironment will be
+ // created with signin::AccountConsistencyMethod::kDisabled, which should
+ // result in ClearPrimaryAccount() removing all the tokens.
+ EXPECT_FALSE(identity_manager->HasPrimaryAccount());
+ EXPECT_FALSE(identity_manager->HasAccountWithRefreshToken(
+ primary_account_info.account_id));
+ EXPECT_FALSE(identity_manager->HasAccountWithRefreshToken(
+ other_account_info.account_id));
+}
+
+// Test that ClearPrimaryAccount(...) with ClearAccountTokensAction::kKeepAll
+// keep all tokens, independently of the account consistency method.
+TEST_F(PrimaryAccountMutatorTest, ClearPrimaryAccount_KeepAll) {
+ for (signin::AccountConsistencyMethod account_consistency_method :
+ kTestedAccountConsistencyMethods) {
+ RunClearPrimaryAccountTest(
+ account_consistency_method,
+ signin::PrimaryAccountMutator::ClearAccountsAction::kKeepAll,
+ RemoveAccountExpectation::kKeepAll);
+ }
+}
+
+// Test that ClearPrimaryAccount(...) with ClearAccountTokensAction::kRemoveAll
+// remove all tokens, independently of the account consistency method.
+TEST_F(PrimaryAccountMutatorTest, ClearPrimaryAccount_RemoveAll) {
+ for (signin::AccountConsistencyMethod account_consistency_method :
+ kTestedAccountConsistencyMethods) {
+ RunClearPrimaryAccountTest(
+ account_consistency_method,
+ signin::PrimaryAccountMutator::ClearAccountsAction::kRemoveAll,
+ RemoveAccountExpectation::kRemoveAll);
+ }
+}
+
+// Test that ClearPrimaryAccount(...) with ClearAccountTokensAction::kDefault
+// and AccountConsistencyMethod::kDisabled (notably != kDice) removes all
+// tokens.
+TEST_F(PrimaryAccountMutatorTest,
+ ClearPrimaryAccount_Default_DisabledConsistency) {
+ RunClearPrimaryAccountTest(
+ signin::AccountConsistencyMethod::kDisabled,
+ signin::PrimaryAccountMutator::ClearAccountsAction::kDefault,
+ RemoveAccountExpectation::kRemoveAll);
+}
+
+// Test that ClearPrimaryAccount(...) with ClearAccountTokensAction::kDefault
+// and AccountConsistencyMethod::kMirror (notably != kDice) removes all
+// tokens.
+TEST_F(PrimaryAccountMutatorTest,
+ ClearPrimaryAccount_Default_MirrorConsistency) {
+ RunClearPrimaryAccountTest(
+ signin::AccountConsistencyMethod::kMirror,
+ signin::PrimaryAccountMutator::ClearAccountsAction::kDefault,
+ RemoveAccountExpectation::kRemoveAll);
+}
+
+// Test that ClearPrimaryAccount(...) with ClearAccountTokensAction::kDefault
+// and AccountConsistencyMethod::kDice keeps all accounts when the the primary
+// account does not have an authentication error (see *_AuthError test).
+TEST_F(PrimaryAccountMutatorTest, ClearPrimaryAccount_Default_DiceConsistency) {
+ RunClearPrimaryAccountTest(
+ signin::AccountConsistencyMethod::kDice,
+ signin::PrimaryAccountMutator::ClearAccountsAction::kDefault,
+ RemoveAccountExpectation::kKeepAll);
+}
+
+// Test that ClearPrimaryAccount(...) with ClearAccountTokensAction::kDefault
+// and AccountConsistencyMethod::kDice removes *only* the primary account
+// due to it authentication error.
+TEST_F(PrimaryAccountMutatorTest,
+ ClearPrimaryAccount_Default_DiceConsistency_AuthError) {
+ RunClearPrimaryAccountTest(
+ signin::AccountConsistencyMethod::kDice,
+ signin::PrimaryAccountMutator::ClearAccountsAction::kDefault,
+ RemoveAccountExpectation::kRemovePrimary, AuthExpectation::kAuthError);
+}
+#endif // !defined(OS_CHROMEOS)
diff --git a/chromium/components/signin/core/browser/set_accounts_in_cookie_result.h b/chromium/components/signin/public/identity_manager/set_accounts_in_cookie_result.h
index 6adba69ab8f..c5e404402be 100644
--- a/chromium/components/signin/core/browser/set_accounts_in_cookie_result.h
+++ b/chromium/components/signin/public/identity_manager/set_accounts_in_cookie_result.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SET_ACCOUNTS_IN_COOKIE_RESULT_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_SET_ACCOUNTS_IN_COOKIE_RESULT_H_
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_SET_ACCOUNTS_IN_COOKIE_RESULT_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_SET_ACCOUNTS_IN_COOKIE_RESULT_H_
namespace signin {
@@ -19,4 +19,4 @@ enum class SetAccountsInCookieResult {
} // namespace signin
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_SET_ACCOUNTS_IN_COOKIE_RESULT_H_
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_SET_ACCOUNTS_IN_COOKIE_RESULT_H_
diff --git a/chromium/components/signin/public/identity_manager/test_identity_manager_observer.cc b/chromium/components/signin/public/identity_manager/test_identity_manager_observer.cc
new file mode 100644
index 00000000000..afa01cb7176
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/test_identity_manager_observer.cc
@@ -0,0 +1,229 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/public/identity_manager/test_identity_manager_observer.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include <utility>
+
+namespace signin {
+
+TestIdentityManagerObserver::TestIdentityManagerObserver(
+ IdentityManager* identity_manager)
+ : identity_manager_(identity_manager) {
+ identity_manager_->AddObserver(this);
+}
+
+TestIdentityManagerObserver::~TestIdentityManagerObserver() {
+ identity_manager_->RemoveObserver(this);
+}
+
+void TestIdentityManagerObserver::SetOnPrimaryAccountSetCallback(
+ base::OnceClosure callback) {
+ on_primary_account_set_callback_ = std::move(callback);
+}
+
+const CoreAccountInfo&
+TestIdentityManagerObserver::PrimaryAccountFromSetCallback() {
+ return primary_account_from_set_callback_;
+}
+
+void TestIdentityManagerObserver::SetOnPrimaryAccountClearedCallback(
+ base::OnceClosure callback) {
+ on_primary_account_cleared_callback_ = std::move(callback);
+}
+
+const CoreAccountInfo&
+TestIdentityManagerObserver::PrimaryAccountFromClearedCallback() {
+ return primary_account_from_cleared_callback_;
+}
+
+void TestIdentityManagerObserver::SetOnUnconsentedPrimaryAccountChangedCallback(
+ base::OnceClosure callback) {
+ on_unconsented_primary_account_callback_ = std::move(callback);
+}
+
+const CoreAccountInfo&
+TestIdentityManagerObserver::UnconsentedPrimaryAccountFromCallback() {
+ return unconsented_primary_account_from_callback_;
+}
+
+void TestIdentityManagerObserver::SetOnRefreshTokenUpdatedCallback(
+ base::OnceClosure callback) {
+ on_refresh_token_updated_callback_ = std::move(callback);
+}
+
+const CoreAccountInfo&
+TestIdentityManagerObserver::AccountFromRefreshTokenUpdatedCallback() {
+ return account_from_refresh_token_updated_callback_;
+}
+
+void TestIdentityManagerObserver::SetOnErrorStateOfRefreshTokenUpdatedCallback(
+ base::OnceClosure callback) {
+ on_error_state_of_refresh_token_updated_callback_ = std::move(callback);
+}
+
+const CoreAccountInfo& TestIdentityManagerObserver::
+ AccountFromErrorStateOfRefreshTokenUpdatedCallback() {
+ return account_from_error_state_of_refresh_token_updated_callback_;
+}
+
+const GoogleServiceAuthError&
+TestIdentityManagerObserver::ErrorFromErrorStateOfRefreshTokenUpdatedCallback()
+ const {
+ return error_from_error_state_of_refresh_token_updated_callback_;
+}
+
+void TestIdentityManagerObserver::SetOnRefreshTokenRemovedCallback(
+ base::OnceClosure callback) {
+ on_refresh_token_removed_callback_ = std::move(callback);
+}
+
+const CoreAccountId&
+TestIdentityManagerObserver::AccountIdFromRefreshTokenRemovedCallback() {
+ return account_from_refresh_token_removed_callback_;
+}
+
+void TestIdentityManagerObserver::SetOnRefreshTokensLoadedCallback(
+ base::OnceClosure callback) {
+ on_refresh_tokens_loaded_callback_ = std::move(callback);
+}
+
+void TestIdentityManagerObserver::SetOnAccountsInCookieUpdatedCallback(
+ base::OnceClosure callback) {
+ on_accounts_in_cookie_updated_callback_ = std::move(callback);
+}
+
+const AccountsInCookieJarInfo&
+TestIdentityManagerObserver::AccountsInfoFromAccountsInCookieUpdatedCallback() {
+ return accounts_info_from_cookie_change_callback_;
+}
+
+const GoogleServiceAuthError&
+TestIdentityManagerObserver::ErrorFromAccountsInCookieUpdatedCallback() const {
+ return error_from_cookie_change_callback_;
+}
+
+void TestIdentityManagerObserver::SetOnCookieDeletedByUserCallback(
+ base::OnceClosure callback) {
+ on_cookie_deleted_by_user_callback_ = std::move(callback);
+}
+
+const AccountInfo&
+TestIdentityManagerObserver::AccountFromAccountUpdatedCallback() {
+ return account_from_account_updated_callback_;
+}
+
+const AccountInfo&
+TestIdentityManagerObserver::AccountFromAccountRemovedWithInfoCallback() {
+ return account_from_account_removed_with_info_callback_;
+}
+
+bool TestIdentityManagerObserver::WasCalledAccountRemovedWithInfoCallback() {
+ return was_called_account_removed_with_info_callback_;
+}
+
+// Each element represents all the changes from an individual batch that has
+// occurred, with the elements ordered from oldest to newest batch occurrence.
+const std::vector<std::vector<CoreAccountId>>&
+TestIdentityManagerObserver::BatchChangeRecords() const {
+ return batch_change_records_;
+}
+
+// IdentityManager::Observer:
+void TestIdentityManagerObserver::OnPrimaryAccountSet(
+ const CoreAccountInfo& primary_account_info) {
+ primary_account_from_set_callback_ = primary_account_info;
+ if (on_primary_account_set_callback_)
+ std::move(on_primary_account_set_callback_).Run();
+}
+
+void TestIdentityManagerObserver::OnPrimaryAccountCleared(
+ const CoreAccountInfo& previous_primary_account_info) {
+ primary_account_from_cleared_callback_ = previous_primary_account_info;
+ if (on_primary_account_cleared_callback_)
+ std::move(on_primary_account_cleared_callback_).Run();
+}
+
+void TestIdentityManagerObserver::OnUnconsentedPrimaryAccountChanged(
+ const CoreAccountInfo& unconsented_primary_account_info) {
+ unconsented_primary_account_from_callback_ = unconsented_primary_account_info;
+ if (on_unconsented_primary_account_callback_)
+ std::move(on_unconsented_primary_account_callback_).Run();
+}
+
+void TestIdentityManagerObserver::OnRefreshTokenUpdatedForAccount(
+ const CoreAccountInfo& account_info) {
+ if (!is_inside_batch_)
+ StartBatchOfRefreshTokenStateChanges();
+
+ batch_change_records_.rbegin()->emplace_back(account_info.account_id);
+ account_from_refresh_token_updated_callback_ = account_info;
+ if (on_refresh_token_updated_callback_)
+ std::move(on_refresh_token_updated_callback_).Run();
+}
+
+void TestIdentityManagerObserver::OnRefreshTokenRemovedForAccount(
+ const CoreAccountId& account_id) {
+ if (!is_inside_batch_)
+ StartBatchOfRefreshTokenStateChanges();
+
+ batch_change_records_.rbegin()->emplace_back(account_id);
+ account_from_refresh_token_removed_callback_ = account_id;
+ if (on_refresh_token_removed_callback_)
+ std::move(on_refresh_token_removed_callback_).Run();
+}
+
+void TestIdentityManagerObserver::OnErrorStateOfRefreshTokenUpdatedForAccount(
+ const CoreAccountInfo& account_info,
+ const GoogleServiceAuthError& error) {
+ account_from_error_state_of_refresh_token_updated_callback_ = account_info;
+ error_from_error_state_of_refresh_token_updated_callback_ = error;
+ if (on_error_state_of_refresh_token_updated_callback_)
+ std::move(on_error_state_of_refresh_token_updated_callback_).Run();
+}
+
+void TestIdentityManagerObserver::OnRefreshTokensLoaded() {
+ if (on_refresh_tokens_loaded_callback_)
+ std::move(on_refresh_tokens_loaded_callback_).Run();
+}
+
+void TestIdentityManagerObserver::OnAccountsInCookieUpdated(
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+ const GoogleServiceAuthError& error) {
+ accounts_info_from_cookie_change_callback_ = accounts_in_cookie_jar_info;
+ error_from_cookie_change_callback_ = error;
+ if (on_accounts_in_cookie_updated_callback_)
+ std::move(on_accounts_in_cookie_updated_callback_).Run();
+}
+
+void TestIdentityManagerObserver::OnAccountsCookieDeletedByUserAction() {
+ std::move(on_cookie_deleted_by_user_callback_).Run();
+}
+
+void TestIdentityManagerObserver::OnExtendedAccountInfoUpdated(
+ const AccountInfo& info) {
+ account_from_account_updated_callback_ = info;
+}
+
+void TestIdentityManagerObserver::OnExtendedAccountInfoRemoved(
+ const AccountInfo& info) {
+ was_called_account_removed_with_info_callback_ = true;
+ account_from_account_removed_with_info_callback_ = info;
+}
+
+void TestIdentityManagerObserver::StartBatchOfRefreshTokenStateChanges() {
+ EXPECT_FALSE(is_inside_batch_);
+ is_inside_batch_ = true;
+
+ // Start a new batch.
+ batch_change_records_.emplace_back(std::vector<CoreAccountId>());
+}
+
+void TestIdentityManagerObserver::OnEndBatchOfRefreshTokenStateChanges() {
+ is_inside_batch_ = false;
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/public/identity_manager/test_identity_manager_observer.h b/chromium/components/signin/public/identity_manager/test_identity_manager_observer.h
new file mode 100644
index 00000000000..506e2461d6f
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/test_identity_manager_observer.h
@@ -0,0 +1,135 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_TEST_IDENTITY_MANAGER_OBSERVER_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_TEST_IDENTITY_MANAGER_OBSERVER_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "components/signin/public/identity_manager/account_info.h"
+#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+
+namespace signin {
+
+// Class that observes events from IdentityManager. It allows setting
+// |OnceClosure| callbacks to be executed for the observed events and retrieving
+// the potential results and/or errors returned after such events have occurred.
+class TestIdentityManagerObserver : IdentityManager::Observer {
+ public:
+ explicit TestIdentityManagerObserver(IdentityManager* identity_manager);
+ ~TestIdentityManagerObserver() override;
+
+ void SetOnPrimaryAccountSetCallback(base::OnceClosure callback);
+ const CoreAccountInfo& PrimaryAccountFromSetCallback();
+
+ void SetOnPrimaryAccountClearedCallback(base::OnceClosure callback);
+ const CoreAccountInfo& PrimaryAccountFromClearedCallback();
+
+ void SetOnUnconsentedPrimaryAccountChangedCallback(
+ base::OnceClosure callback);
+ const CoreAccountInfo& UnconsentedPrimaryAccountFromCallback();
+
+ void SetOnRefreshTokenUpdatedCallback(base::OnceClosure callback);
+ const CoreAccountInfo& AccountFromRefreshTokenUpdatedCallback();
+
+ void SetOnErrorStateOfRefreshTokenUpdatedCallback(base::OnceClosure callback);
+ const CoreAccountInfo& AccountFromErrorStateOfRefreshTokenUpdatedCallback();
+ const GoogleServiceAuthError&
+ ErrorFromErrorStateOfRefreshTokenUpdatedCallback() const;
+
+ void SetOnRefreshTokenRemovedCallback(base::OnceClosure callback);
+ const CoreAccountId& AccountIdFromRefreshTokenRemovedCallback();
+
+ void SetOnRefreshTokensLoadedCallback(base::OnceClosure callback);
+
+ void SetOnAccountsInCookieUpdatedCallback(base::OnceClosure callback);
+ const AccountsInCookieJarInfo&
+ AccountsInfoFromAccountsInCookieUpdatedCallback();
+ const GoogleServiceAuthError& ErrorFromAccountsInCookieUpdatedCallback()
+ const;
+
+ void SetOnCookieDeletedByUserCallback(base::OnceClosure callback);
+
+ const AccountInfo& AccountFromAccountUpdatedCallback();
+ const AccountInfo& AccountFromAccountRemovedWithInfoCallback();
+ bool WasCalledAccountRemovedWithInfoCallback();
+
+ // Each element represents all the changes from an individual batch that has
+ // occurred, with the elements ordered from oldest to newest batch occurrence.
+ const std::vector<std::vector<CoreAccountId>>& BatchChangeRecords() const;
+
+ private:
+ // IdentityManager::Observer:
+ void OnPrimaryAccountSet(
+ const CoreAccountInfo& primary_account_info) override;
+ void OnPrimaryAccountCleared(
+ const CoreAccountInfo& previous_primary_account_info) override;
+ void OnUnconsentedPrimaryAccountChanged(
+ const CoreAccountInfo& unconsented_primary_account_info) override;
+ void OnRefreshTokenUpdatedForAccount(
+ const CoreAccountInfo& account_info) override;
+ void OnRefreshTokenRemovedForAccount(
+ const CoreAccountId& account_id) override;
+ void OnErrorStateOfRefreshTokenUpdatedForAccount(
+ const CoreAccountInfo& account_info,
+ const GoogleServiceAuthError& error) override;
+ void OnRefreshTokensLoaded() override;
+
+ void OnAccountsInCookieUpdated(
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+ const GoogleServiceAuthError& error) override;
+ void OnAccountsCookieDeletedByUserAction() override;
+
+ void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
+ void OnExtendedAccountInfoRemoved(const AccountInfo& info) override;
+
+ void StartBatchOfRefreshTokenStateChanges();
+ void OnEndBatchOfRefreshTokenStateChanges() override;
+
+ IdentityManager* identity_manager_;
+
+ base::OnceClosure on_primary_account_set_callback_;
+ CoreAccountInfo primary_account_from_set_callback_;
+
+ base::OnceClosure on_primary_account_cleared_callback_;
+ CoreAccountInfo primary_account_from_cleared_callback_;
+
+ base::OnceClosure on_unconsented_primary_account_callback_;
+ CoreAccountInfo unconsented_primary_account_from_callback_;
+
+ base::OnceClosure on_refresh_token_updated_callback_;
+ CoreAccountInfo account_from_refresh_token_updated_callback_;
+
+ base::OnceClosure on_error_state_of_refresh_token_updated_callback_;
+ CoreAccountInfo account_from_error_state_of_refresh_token_updated_callback_;
+ GoogleServiceAuthError
+ error_from_error_state_of_refresh_token_updated_callback_;
+
+ base::OnceClosure on_refresh_token_removed_callback_;
+ CoreAccountId account_from_refresh_token_removed_callback_;
+
+ base::OnceClosure on_refresh_tokens_loaded_callback_;
+
+ base::OnceClosure on_accounts_in_cookie_updated_callback_;
+ AccountsInCookieJarInfo accounts_info_from_cookie_change_callback_;
+ GoogleServiceAuthError error_from_cookie_change_callback_;
+
+ base::OnceClosure on_cookie_deleted_by_user_callback_;
+
+ AccountInfo account_from_account_updated_callback_;
+ AccountInfo account_from_account_removed_with_info_callback_;
+
+ bool is_inside_batch_ = false;
+ bool was_called_account_removed_with_info_callback_ = false;
+ std::vector<std::vector<CoreAccountId>> batch_change_records_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestIdentityManagerObserver);
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_TEST_IDENTITY_MANAGER_OBSERVER_H_
diff --git a/chromium/components/signin/core/browser/ubertoken_fetcher.cc b/chromium/components/signin/public/identity_manager/ubertoken_fetcher.cc
index 6eea8ba9c4d..e3377be94e1 100644
--- a/chromium/components/signin/core/browser/ubertoken_fetcher.cc
+++ b/chromium/components/signin/public/identity_manager/ubertoken_fetcher.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/ubertoken_fetcher.h"
+#include "components/signin/public/identity_manager/ubertoken_fetcher.h"
namespace signin {
diff --git a/chromium/components/signin/core/browser/ubertoken_fetcher.h b/chromium/components/signin/public/identity_manager/ubertoken_fetcher.h
index cc4f1691e5c..f79d635d9a8 100644
--- a/chromium/components/signin/core/browser/ubertoken_fetcher.h
+++ b/chromium/components/signin/public/identity_manager/ubertoken_fetcher.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_UBERTOKEN_FETCHER_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_UBERTOKEN_FETCHER_H_
+#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_UBERTOKEN_FETCHER_H_
+#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_UBERTOKEN_FETCHER_H_
#include <memory>
@@ -32,4 +32,4 @@ class UbertokenFetcher {
} // namespace signin
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_UBERTOKEN_FETCHER_H_
+#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_UBERTOKEN_FETCHER_H_
diff --git a/chromium/components/signin/public/webdata/BUILD.gn b/chromium/components/signin/public/webdata/BUILD.gn
new file mode 100644
index 00000000000..a301f77272d
--- /dev/null
+++ b/chromium/components/signin/public/webdata/BUILD.gn
@@ -0,0 +1,38 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This target cannot depend on anything else from //components/signin.
+static_library("webdata") {
+ sources = [
+ "token_service_table.cc",
+ "token_service_table.h",
+ "token_web_data.cc",
+ "token_web_data.h",
+ ]
+
+ deps = [
+ "//components/os_crypt",
+ "//sql",
+ ]
+
+ public_deps = [
+ "//base",
+ "//components/webdata/common",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "token_service_table_unittest.cc",
+ ]
+
+ deps = [
+ ":webdata",
+ "//base/test:test_support",
+ "//components/os_crypt:test_support",
+ "//components/webdata/common",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/components/signin/core/browser/webdata/token_service_table.cc b/chromium/components/signin/public/webdata/token_service_table.cc
index e938a5f2a12..4e3be5adde4 100644
--- a/chromium/components/signin/core/browser/webdata/token_service_table.cc
+++ b/chromium/components/signin/public/webdata/token_service_table.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/webdata/token_service_table.h"
+#include "components/signin/public/webdata/token_service_table.h"
#include <map>
#include <string>
@@ -34,7 +34,6 @@ enum ReadOneTokenResult {
TokenServiceTable* TokenServiceTable::FromWebDatabase(WebDatabase* db) {
return static_cast<TokenServiceTable*>(db->GetTable(GetKey()));
-
}
WebDatabaseTable::TypeKey TokenServiceTable::GetTypeKey() const {
@@ -73,8 +72,8 @@ bool TokenServiceTable::RemoveAllTokens() {
}
bool TokenServiceTable::RemoveTokenForService(const std::string& service) {
- sql::Statement s(db_->GetUniqueStatement(
- "DELETE FROM token_service WHERE service = ?"));
+ sql::Statement s(
+ db_->GetUniqueStatement("DELETE FROM token_service WHERE service = ?"));
s.BindString(0, service);
bool result = s.Run();
@@ -93,9 +92,9 @@ bool TokenServiceTable::SetTokenForService(const std::string& service,
// Don't bother with a cached statement since this will be a relatively
// infrequent operation.
- sql::Statement s(db_->GetUniqueStatement(
- "INSERT OR REPLACE INTO token_service "
- "(service, encrypted_token) VALUES (?, ?)"));
+ sql::Statement s(
+ db_->GetUniqueStatement("INSERT OR REPLACE INTO token_service "
+ "(service, encrypted_token) VALUES (?, ?)"));
s.BindString(0, service);
s.BindBlob(1, encrypted_token.data(),
static_cast<int>(encrypted_token.length()));
@@ -128,8 +127,8 @@ TokenServiceTable::Result TokenServiceTable::GetAllTokens(
std::string decrypted_token;
std::string service;
service = s.ColumnString(0);
- bool entry_ok = !service.empty() &&
- s.ColumnBlobAsString(1, &encrypted_token);
+ bool entry_ok =
+ !service.empty() && s.ColumnBlobAsString(1, &encrypted_token);
if (entry_ok) {
if (OSCrypt::DecryptString(encrypted_token, &decrypted_token)) {
(*tokens)[service] = decrypted_token;
@@ -149,8 +148,7 @@ TokenServiceTable::Result TokenServiceTable::GetAllTokens(
}
DCHECK_LT(read_token_result, READ_ONE_TOKEN_MAX_VALUE);
UMA_HISTOGRAM_ENUMERATION("Signin.TokenTable.ReadTokenFromDBResult",
- read_token_result,
- READ_ONE_TOKEN_MAX_VALUE);
+ read_token_result, READ_ONE_TOKEN_MAX_VALUE);
}
VLOG(1) << "Loaded tokens: result = " << read_all_tokens_result
<< " ; number of tokens loaded = " << number_of_tokens_loaded;
diff --git a/chromium/components/signin/core/browser/webdata/token_service_table.h b/chromium/components/signin/public/webdata/token_service_table.h
index b6d750f0ce5..28ae99a80a8 100644
--- a/chromium/components/signin/core/browser/webdata/token_service_table.h
+++ b/chromium/components/signin/public/webdata/token_service_table.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_WEBDATA_TOKEN_SERVICE_TABLE_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_WEBDATA_TOKEN_SERVICE_TABLE_H_
+#ifndef COMPONENTS_SIGNIN_PUBLIC_WEBDATA_TOKEN_SERVICE_TABLE_H_
+#define COMPONENTS_SIGNIN_PUBLIC_WEBDATA_TOKEN_SERVICE_TABLE_H_
#include <map>
#include <string>
@@ -48,11 +48,10 @@ class TokenServiceTable : public WebDatabaseTable {
// Store a token in the token_service table. Stored encrypted. May cause
// a mac keychain popup.
// True if we encrypted a token and stored it, false otherwise.
- bool SetTokenForService(const std::string& service,
- const std::string& token);
+ bool SetTokenForService(const std::string& service, const std::string& token);
private:
DISALLOW_COPY_AND_ASSIGN(TokenServiceTable);
};
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_WEBDATA_TOKEN_SERVICE_TABLE_H_
+#endif // COMPONENTS_SIGNIN_PUBLIC_WEBDATA_TOKEN_SERVICE_TABLE_H_
diff --git a/chromium/components/signin/core/browser/webdata/token_service_table_unittest.cc b/chromium/components/signin/public/webdata/token_service_table_unittest.cc
index 32d169a839a..9a3332d5481 100644
--- a/chromium/components/signin/core/browser/webdata/token_service_table_unittest.cc
+++ b/chromium/components/signin/public/webdata/token_service_table_unittest.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "components/signin/public/webdata/token_service_table.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/os_crypt/os_crypt_mocker.h"
-#include "components/signin/core/browser/webdata/token_service_table.h"
#include "components/webdata/common/web_database.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/signin/core/browser/webdata/token_web_data.cc b/chromium/components/signin/public/webdata/token_web_data.cc
index cc38acaa09b..9ecd6b68624 100644
--- a/chromium/components/signin/core/browser/webdata/token_web_data.cc
+++ b/chromium/components/signin/public/webdata/token_web_data.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/signin/core/browser/webdata/token_web_data.h"
+#include "components/signin/public/webdata/token_web_data.h"
#include <memory>
@@ -10,7 +10,7 @@
#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
-#include "components/signin/core/browser/webdata/token_service_table.h"
+#include "components/signin/public/webdata/token_service_table.h"
#include "components/webdata/common/web_database_service.h"
using base::Bind;
@@ -30,17 +30,18 @@ class TokenWebDataBackend
return WebDatabase::COMMIT_NOT_NEEDED;
}
- WebDatabase::State RemoveTokenForService(
- const std::string& service, WebDatabase* db) {
- if (TokenServiceTable::FromWebDatabase(db)
- ->RemoveTokenForService(service)) {
+ WebDatabase::State RemoveTokenForService(const std::string& service,
+ WebDatabase* db) {
+ if (TokenServiceTable::FromWebDatabase(db)->RemoveTokenForService(
+ service)) {
return WebDatabase::COMMIT_NEEDED;
}
return WebDatabase::COMMIT_NOT_NEEDED;
}
- WebDatabase::State SetTokenForService(
- const std::string& service, const std::string& token, WebDatabase* db) {
+ WebDatabase::State SetTokenForService(const std::string& service,
+ const std::string& token,
+ WebDatabase* db) {
if (TokenServiceTable::FromWebDatabase(db)->SetTokenForService(service,
token)) {
return WebDatabase::COMMIT_NEEDED;
@@ -56,8 +57,7 @@ class TokenWebDataBackend
}
protected:
- virtual ~TokenWebDataBackend() {
- }
+ virtual ~TokenWebDataBackend() {}
private:
friend class base::RefCountedDeleteOnSequence<TokenWebDataBackend>;
@@ -79,27 +79,28 @@ TokenWebData::TokenWebData(
void TokenWebData::SetTokenForService(const std::string& service,
const std::string& token) {
- wdbs_->ScheduleDBTask(FROM_HERE,
- Bind(&TokenWebDataBackend::SetTokenForService, token_backend_,
- service, token));
+ wdbs_->ScheduleDBTask(
+ FROM_HERE, Bind(&TokenWebDataBackend::SetTokenForService, token_backend_,
+ service, token));
}
void TokenWebData::RemoveAllTokens() {
- wdbs_->ScheduleDBTask(FROM_HERE,
- Bind(&TokenWebDataBackend::RemoveAllTokens, token_backend_));
+ wdbs_->ScheduleDBTask(
+ FROM_HERE, Bind(&TokenWebDataBackend::RemoveAllTokens, token_backend_));
}
void TokenWebData::RemoveTokenForService(const std::string& service) {
wdbs_->ScheduleDBTask(FROM_HERE,
- Bind(&TokenWebDataBackend::RemoveTokenForService, token_backend_,
- service));
+ Bind(&TokenWebDataBackend::RemoveTokenForService,
+ token_backend_, service));
}
// Null on failure. Success is WDResult<std::string>
WebDataServiceBase::Handle TokenWebData::GetAllTokens(
WebDataServiceConsumer* consumer) {
- return wdbs_->ScheduleDBTaskWithResult(FROM_HERE,
- Bind(&TokenWebDataBackend::GetAllTokens, token_backend_), consumer);
+ return wdbs_->ScheduleDBTaskWithResult(
+ FROM_HERE, Bind(&TokenWebDataBackend::GetAllTokens, token_backend_),
+ consumer);
}
TokenWebData::TokenWebData(
@@ -108,5 +109,4 @@ TokenWebData::TokenWebData(
: WebDataServiceBase(nullptr, ProfileErrorCallback(), ui_task_runner),
token_backend_(new TokenWebDataBackend(db_task_runner)) {}
-TokenWebData::~TokenWebData() {
-}
+TokenWebData::~TokenWebData() {}
diff --git a/chromium/components/signin/core/browser/webdata/token_web_data.h b/chromium/components/signin/public/webdata/token_web_data.h
index 39bb6af92a9..2992fe6caef 100644
--- a/chromium/components/signin/core/browser/webdata/token_web_data.h
+++ b/chromium/components/signin/public/webdata/token_web_data.h
@@ -6,8 +6,8 @@
// information and MUST not be extracted, overwritten or modified except
// through Chromium defined APIs.
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_WEBDATA_TOKEN_WEB_DATA_H__
-#define COMPONENTS_SIGNIN_CORE_BROWSER_WEBDATA_TOKEN_WEB_DATA_H__
+#ifndef COMPONENTS_SIGNIN_PUBLIC_WEBDATA_TOKEN_WEB_DATA_H_
+#define COMPONENTS_SIGNIN_PUBLIC_WEBDATA_TOKEN_WEB_DATA_H_
#include <map>
#include <string>
@@ -18,7 +18,7 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "components/signin/core/browser/webdata/token_service_table.h"
+#include "components/signin/public/webdata/token_service_table.h"
#include "components/webdata/common/web_data_results.h"
#include "components/webdata/common/web_data_service_base.h"
#include "components/webdata/common/web_data_service_consumer.h"
@@ -55,8 +55,7 @@ class TokenWebData : public WebDataServiceBase {
scoped_refptr<base::SingleThreadTaskRunner> db_task_runner);
// Set a token to use for a specified service.
- void SetTokenForService(const std::string& service,
- const std::string& token);
+ void SetTokenForService(const std::string& service, const std::string& token);
// Remove all tokens stored in the web database.
void RemoveAllTokens();
@@ -79,4 +78,4 @@ class TokenWebData : public WebDataServiceBase {
DISALLOW_COPY_AND_ASSIGN(TokenWebData);
};
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_WEBDATA_TOKEN_WEB_DATA_H__
+#endif // COMPONENTS_SIGNIN_PUBLIC_WEBDATA_TOKEN_WEB_DATA_H_