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_info.h"
18 #include "components/signin/core/browser/account_tracker_service.h"
19 #include "components/signin/core/browser/signin_client.h"
20 #include "components/signin/core/common/signin_pref_names.h"
21 #include "components/signin/core/common/signin_switches.h"
22 #include "google_apis/gaia/gaia_auth_util.h"
23 #include "google_apis/gaia/gaia_constants.h"
24 #include "google_apis/gaia/gaia_urls.h"
26 using namespace signin_internals_util
;
28 SigninManagerBase::SigninManagerBase(
30 AccountTrackerService
* account_tracker_service
)
32 account_tracker_service_(account_tracker_service
),
34 weak_pointer_factory_(this) {
36 DCHECK(account_tracker_service_
);
39 SigninManagerBase::~SigninManagerBase() {}
42 void SigninManagerBase::RegisterProfilePrefs(
43 user_prefs::PrefRegistrySyncable
* registry
) {
44 registry
->RegisterStringPref(prefs::kGoogleServicesHostedDomain
,
46 registry
->RegisterStringPref(prefs::kGoogleServicesLastUsername
,
48 registry
->RegisterInt64Pref(
49 prefs::kGoogleServicesRefreshTokenAnnotateScheduledTime
,
50 base::Time().ToInternalValue());
51 registry
->RegisterStringPref(prefs::kGoogleServicesSigninScopedDeviceId
,
53 registry
->RegisterStringPref(prefs::kGoogleServicesAccountId
, std::string());
54 registry
->RegisterStringPref(prefs::kGoogleServicesUserAccountId
,
56 registry
->RegisterBooleanPref(prefs::kAutologinEnabled
, true);
57 registry
->RegisterBooleanPref(prefs::kReverseAutologinEnabled
, true);
58 registry
->RegisterListPref(prefs::kReverseAutologinRejectedEmailList
,
60 registry
->RegisterInt64Pref(prefs::kSignedInTime
,
61 base::Time().ToInternalValue());
63 // Deprecated prefs: will be removed in a future release.
64 registry
->RegisterStringPref(prefs::kGoogleServicesUsername
, std::string());
68 void SigninManagerBase::RegisterPrefs(PrefRegistrySimple
* registry
) {
69 registry
->RegisterStringPref(prefs::kGoogleServicesUsernamePattern
,
73 void SigninManagerBase::Initialize(PrefService
* local_state
) {
74 // Should never call Initialize() twice.
75 DCHECK(!IsInitialized());
78 // If the user is clearing the token service from the command line, then
79 // clear their login info also (not valid to be logged in without any
81 base::CommandLine
* cmd_line
= base::CommandLine::ForCurrentProcess();
82 if (cmd_line
->HasSwitch(switches::kClearTokenService
)) {
83 client_
->GetPrefs()->ClearPref(prefs::kGoogleServicesAccountId
);
84 client_
->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername
);
85 client_
->GetPrefs()->ClearPref(prefs::kGoogleServicesUserAccountId
);
88 std::string account_id
=
89 client_
->GetPrefs()->GetString(prefs::kGoogleServicesAccountId
);
91 // Handle backward compatibility: if kGoogleServicesAccountId is empty, but
92 // kGoogleServicesUsername is not, then this is an old profile that needs to
93 // be updated. kGoogleServicesUserAccountId should not be empty, and contains
94 // the gaia_id. Use both properties to prime the account tracker before
96 if (account_id
.empty()) {
97 std::string pref_account_username
=
98 client_
->GetPrefs()->GetString(prefs::kGoogleServicesUsername
);
99 if (!pref_account_username
.empty()) {
100 // This is an old profile connected to a google account. Migrate from
101 // kGoogleServicesUsername to kGoogleServicesAccountId.
102 std::string pref_gaia_id
=
103 client_
->GetPrefs()->GetString(prefs::kGoogleServicesUserAccountId
);
105 // If kGoogleServicesUserAccountId is empty, then this is either a cros
106 // machine or a really old profile on one of the other platforms. However
107 // in this case the account tracker should have the gaia_id so fetch it
109 if (pref_gaia_id
.empty()) {
110 AccountInfo info
= 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 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 AccountInfo
SigninManagerBase::GetAuthenticatedAccountInfo() const {
162 return account_tracker_service_
->GetAccountInfo(GetAuthenticatedAccountId());
165 const std::string
& SigninManagerBase::GetAuthenticatedAccountId() const {
166 return authenticated_account_id_
;
169 void SigninManagerBase::SetAuthenticatedAccountInfo(const std::string
& gaia_id
,
170 const std::string
& email
) {
171 DCHECK(!gaia_id
.empty());
172 DCHECK(!email
.empty());
174 std::string account_id
=
175 account_tracker_service_
->SeedAccountInfo(gaia_id
, email
);
176 SetAuthenticatedAccountId(account_id
);
179 void SigninManagerBase::SetAuthenticatedAccountId(
180 const std::string
& account_id
) {
181 DCHECK(!account_id
.empty());
182 if (!authenticated_account_id_
.empty()) {
183 DLOG_IF(ERROR
, account_id
!= authenticated_account_id_
)
184 << "Tried to change the authenticated id to something different: "
185 << "Current: " << authenticated_account_id_
<< ", New: " << account_id
;
189 std::string pref_account_id
=
190 client_
->GetPrefs()->GetString(prefs::kGoogleServicesAccountId
);
192 DCHECK(pref_account_id
.empty() || pref_account_id
== account_id
)
193 << "account_id=" << account_id
194 << " pref_account_id=" << pref_account_id
;
195 authenticated_account_id_
= account_id
;
196 client_
->GetPrefs()->SetString(prefs::kGoogleServicesAccountId
, account_id
);
198 // This preference is set so that code on I/O thread has access to the
199 // Gaia id of the signed in user.
200 AccountInfo info
= account_tracker_service_
->GetAccountInfo(account_id
);
202 // When this function is called from Initialize(), it's possible for
203 // |info.gaia| to be empty when migrating from a really old profile.
204 if (!info
.gaia
.empty()) {
205 client_
->GetPrefs()->SetString(prefs::kGoogleServicesUserAccountId
,
209 // Go ahead and update the last signed in account info here as well. Once a
210 // user is signed in the two preferences should match. Doing it here as
211 // opposed to on signin allows us to catch the upgrade scenario.
212 client_
->GetPrefs()->SetString(prefs::kGoogleServicesLastUsername
,
216 bool SigninManagerBase::IsAuthenticated() const {
217 return !authenticated_account_id_
.empty();
220 bool SigninManagerBase::AuthInProgress() const {
221 // SigninManagerBase never kicks off auth processes itself.
225 void SigninManagerBase::Shutdown() {}
227 void SigninManagerBase::AddObserver(Observer
* observer
) {
228 observer_list_
.AddObserver(observer
);
231 void SigninManagerBase::RemoveObserver(Observer
* observer
) {
232 observer_list_
.RemoveObserver(observer
);
235 void SigninManagerBase::AddSigninDiagnosticsObserver(
236 SigninDiagnosticsObserver
* observer
) {
237 signin_diagnostics_observers_
.AddObserver(observer
);
240 void SigninManagerBase::RemoveSigninDiagnosticsObserver(
241 SigninDiagnosticsObserver
* observer
) {
242 signin_diagnostics_observers_
.RemoveObserver(observer
);
245 void SigninManagerBase::NotifyDiagnosticsObservers(
246 const TimedSigninStatusField
& field
,
247 const std::string
& value
) {
248 FOR_EACH_OBSERVER(SigninDiagnosticsObserver
,
249 signin_diagnostics_observers_
,
250 NotifySigninValueChanged(field
, value
));