1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/signin/core/browser/signin_manager_base.h"
10 #include "base/command_line.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "components/pref_registry/pref_registry_syncable.h"
17 #include "components/signin/core/browser/account_tracker_service.h"
18 #include "components/signin/core/browser/signin_client.h"
19 #include "components/signin/core/common/signin_pref_names.h"
20 #include "components/signin/core/common/signin_switches.h"
21 #include "google_apis/gaia/gaia_auth_util.h"
22 #include "google_apis/gaia/gaia_constants.h"
23 #include "google_apis/gaia/gaia_urls.h"
25 using namespace signin_internals_util
;
27 SigninManagerBase::SigninManagerBase(
29 AccountTrackerService
* account_tracker_service
)
31 account_tracker_service_(account_tracker_service
),
33 weak_pointer_factory_(this) {
35 DCHECK(account_tracker_service_
);
38 SigninManagerBase::~SigninManagerBase() {}
41 void SigninManagerBase::RegisterProfilePrefs(
42 user_prefs::PrefRegistrySyncable
* registry
) {
43 registry
->RegisterStringPref(prefs::kGoogleServicesHostedDomain
,
45 registry
->RegisterStringPref(prefs::kGoogleServicesLastUsername
,
47 registry
->RegisterInt64Pref(
48 prefs::kGoogleServicesRefreshTokenAnnotateScheduledTime
,
49 base::Time().ToInternalValue());
50 registry
->RegisterStringPref(prefs::kGoogleServicesSigninScopedDeviceId
,
52 registry
->RegisterStringPref(prefs::kGoogleServicesAccountId
, std::string());
53 registry
->RegisterStringPref(prefs::kGoogleServicesUserAccountId
,
55 registry
->RegisterBooleanPref(prefs::kAutologinEnabled
, true);
56 registry
->RegisterBooleanPref(prefs::kReverseAutologinEnabled
, true);
57 registry
->RegisterListPref(prefs::kReverseAutologinRejectedEmailList
,
59 registry
->RegisterInt64Pref(prefs::kSignedInTime
,
60 base::Time().ToInternalValue());
62 // Deprecated prefs: will be removed in a future release.
63 registry
->RegisterStringPref(prefs::kGoogleServicesUsername
, std::string());
67 void SigninManagerBase::RegisterPrefs(PrefRegistrySimple
* registry
) {
68 registry
->RegisterStringPref(prefs::kGoogleServicesUsernamePattern
,
72 void SigninManagerBase::Initialize(PrefService
* local_state
) {
73 // Should never call Initialize() twice.
74 DCHECK(!IsInitialized());
77 // If the user is clearing the token service from the command line, then
78 // clear their login info also (not valid to be logged in without any
80 base::CommandLine
* cmd_line
= base::CommandLine::ForCurrentProcess();
81 if (cmd_line
->HasSwitch(switches::kClearTokenService
)) {
82 client_
->GetPrefs()->ClearPref(prefs::kGoogleServicesAccountId
);
83 client_
->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername
);
84 client_
->GetPrefs()->ClearPref(prefs::kGoogleServicesUserAccountId
);
87 std::string account_id
=
88 client_
->GetPrefs()->GetString(prefs::kGoogleServicesAccountId
);
90 // Handle backward compatibility: if kGoogleServicesAccountId is empty, but
91 // kGoogleServicesUsername is not, then this is an old profile that needs to
92 // be updated. kGoogleServicesUserAccountId should not be empty, and contains
93 // the gaia_id. Use both properties to prime the account tracker before
95 if (account_id
.empty()) {
96 std::string pref_account_username
=
97 client_
->GetPrefs()->GetString(prefs::kGoogleServicesUsername
);
98 if (!pref_account_username
.empty()) {
99 // This is an old profile connected to a google account. Migrate from
100 // kGoogleServicesUsername to kGoogleServicesAccountId.
101 std::string pref_gaia_id
=
102 client_
->GetPrefs()->GetString(prefs::kGoogleServicesUserAccountId
);
104 // If kGoogleServicesUserAccountId is empty, then this is either a cros
105 // machine or a really old profile on one of the other platforms. However
106 // in this case the account tracker should have the gaia_id so fetch it
108 if (pref_gaia_id
.empty()) {
109 AccountTrackerService::AccountInfo info
=
110 account_tracker_service_
->FindAccountInfoByEmail(
111 pref_account_username
);
112 pref_gaia_id
= info
.gaia
;
115 // If |pref_gaia_id| is still empty, this means the profile has been in
116 // an auth error state for some time (since M39). It could also mean
117 // a profile that has not been used since M33. Before migration to gaia
118 // id is complete, the returned value will be the normalized email, which
119 // is correct. After the migration, the returned value will be empty,
120 // which means the user is essentially signed out.
121 // TODO(rogerta): may want to show a toast or something.
122 account_id
= account_tracker_service_
->SeedAccountInfo(
123 pref_gaia_id
, pref_account_username
);
125 // Set account id before removing obsolete user name in case crash in the
127 client_
->GetPrefs()->SetString(prefs::kGoogleServicesAccountId
,
130 // Now remove obsolete preferences.
131 client_
->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername
);
134 // TODO(rogerta): once migration to gaia id is complete, remove
135 // kGoogleServicesUserAccountId and change all uses of that pref to
136 // kGoogleServicesAccountId.
139 if (!account_id
.empty()) {
140 if (account_tracker_service_
->GetMigrationState() ==
141 AccountTrackerService::MIGRATION_IN_PROGRESS
) {
142 AccountTrackerService::AccountInfo account_info
=
143 account_tracker_service_
->FindAccountInfoByEmail(account_id
);
144 // |account_info.gaia| could be empty if |account_id| is already gaia id.
145 if (!account_info
.gaia
.empty()) {
146 account_id
= account_info
.gaia
;
147 client_
->GetPrefs()->SetString(prefs::kGoogleServicesAccountId
,
151 SetAuthenticatedAccountId(account_id
);
155 bool SigninManagerBase::IsInitialized() const { return initialized_
; }
157 bool SigninManagerBase::IsSigninAllowed() const {
158 return client_
->GetPrefs()->GetBoolean(prefs::kSigninAllowed
);
161 std::string
SigninManagerBase::GetAuthenticatedUsername() const {
162 return account_tracker_service_
->GetAccountInfo(
163 GetAuthenticatedAccountId()).email
;
166 const std::string
& SigninManagerBase::GetAuthenticatedAccountId() const {
167 return authenticated_account_id_
;
170 void SigninManagerBase::SetAuthenticatedAccountInfo(const std::string
& gaia_id
,
171 const std::string
& email
) {
172 DCHECK(!gaia_id
.empty());
173 DCHECK(!email
.empty());
175 std::string account_id
=
176 account_tracker_service_
->SeedAccountInfo(gaia_id
, email
);
177 SetAuthenticatedAccountId(account_id
);
180 void SigninManagerBase::SetAuthenticatedAccountId(
181 const std::string
& account_id
) {
182 DCHECK(!account_id
.empty());
183 if (!authenticated_account_id_
.empty()) {
184 DLOG_IF(ERROR
, account_id
!= authenticated_account_id_
)
185 << "Tried to change the authenticated id to something different: "
186 << "Current: " << authenticated_account_id_
<< ", New: " << account_id
;
190 std::string pref_account_id
=
191 client_
->GetPrefs()->GetString(prefs::kGoogleServicesAccountId
);
193 DCHECK(pref_account_id
.empty() || pref_account_id
== account_id
)
194 << "account_id=" << account_id
195 << " pref_account_id=" << pref_account_id
;
196 authenticated_account_id_
= account_id
;
197 client_
->GetPrefs()->SetString(prefs::kGoogleServicesAccountId
, account_id
);
199 // This preference is set so that code on I/O thread has access to the
200 // Gaia id of the signed in user.
201 AccountTrackerService::AccountInfo info
=
202 account_tracker_service_
->GetAccountInfo(account_id
);
204 // When this function is called from Initialize(), it's possible for
205 // |info.gaia| to be empty when migrating from a really old profile.
206 if (!info
.gaia
.empty()) {
207 client_
->GetPrefs()->SetString(prefs::kGoogleServicesUserAccountId
,
211 // Go ahead and update the last signed in account info here as well. Once a
212 // user is signed in the two preferences should match. Doing it here as
213 // opposed to on signin allows us to catch the upgrade scenario.
214 client_
->GetPrefs()->SetString(prefs::kGoogleServicesLastUsername
,
218 bool SigninManagerBase::IsAuthenticated() const {
219 return !authenticated_account_id_
.empty();
222 bool SigninManagerBase::AuthInProgress() const {
223 // SigninManagerBase never kicks off auth processes itself.
227 void SigninManagerBase::Shutdown() {}
229 void SigninManagerBase::AddObserver(Observer
* observer
) {
230 observer_list_
.AddObserver(observer
);
233 void SigninManagerBase::RemoveObserver(Observer
* observer
) {
234 observer_list_
.RemoveObserver(observer
);
237 void SigninManagerBase::AddSigninDiagnosticsObserver(
238 SigninDiagnosticsObserver
* observer
) {
239 signin_diagnostics_observers_
.AddObserver(observer
);
242 void SigninManagerBase::RemoveSigninDiagnosticsObserver(
243 SigninDiagnosticsObserver
* observer
) {
244 signin_diagnostics_observers_
.RemoveObserver(observer
);
247 void SigninManagerBase::NotifyDiagnosticsObservers(
248 const TimedSigninStatusField
& field
,
249 const std::string
& value
) {
250 FOR_EACH_OBSERVER(SigninDiagnosticsObserver
,
251 signin_diagnostics_observers_
,
252 NotifySigninValueChanged(field
, value
));