Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / signin / core / browser / signin_manager_base.cc
blobf18f009081621c9da93196e444f128685e6e515b
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"
7 #include <string>
8 #include <vector>
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(
29 SigninClient* client,
30 AccountTrackerService* account_tracker_service)
31 : client_(client),
32 account_tracker_service_(account_tracker_service),
33 initialized_(false),
34 weak_pointer_factory_(this) {
35 DCHECK(client_);
36 DCHECK(account_tracker_service_);
39 SigninManagerBase::~SigninManagerBase() {}
41 // static
42 void SigninManagerBase::RegisterProfilePrefs(
43 user_prefs::PrefRegistrySyncable* registry) {
44 registry->RegisterStringPref(prefs::kGoogleServicesHostedDomain,
45 std::string());
46 registry->RegisterStringPref(prefs::kGoogleServicesLastUsername,
47 std::string());
48 registry->RegisterInt64Pref(
49 prefs::kGoogleServicesRefreshTokenAnnotateScheduledTime,
50 base::Time().ToInternalValue());
51 registry->RegisterStringPref(prefs::kGoogleServicesSigninScopedDeviceId,
52 std::string());
53 registry->RegisterStringPref(prefs::kGoogleServicesAccountId, std::string());
54 registry->RegisterStringPref(prefs::kGoogleServicesUserAccountId,
55 std::string());
56 registry->RegisterBooleanPref(prefs::kAutologinEnabled, true);
57 registry->RegisterBooleanPref(prefs::kReverseAutologinEnabled, true);
58 registry->RegisterListPref(prefs::kReverseAutologinRejectedEmailList,
59 new base::ListValue);
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());
67 // static
68 void SigninManagerBase::RegisterPrefs(PrefRegistrySimple* registry) {
69 registry->RegisterStringPref(prefs::kGoogleServicesUsernamePattern,
70 std::string());
73 void SigninManagerBase::Initialize(PrefService* local_state) {
74 // Should never call Initialize() twice.
75 DCHECK(!IsInitialized());
76 initialized_ = true;
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
80 // tokens).
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
95 // proceeding.
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
108 // from there.
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
126 // middle.
127 client_->GetPrefs()->SetString(prefs::kGoogleServicesAccountId,
128 account_id);
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,
148 account_id);
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;
186 return;
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,
206 info.gaia);
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,
213 info.email);
216 bool SigninManagerBase::IsAuthenticated() const {
217 return !authenticated_account_id_.empty();
220 bool SigninManagerBase::AuthInProgress() const {
221 // SigninManagerBase never kicks off auth processes itself.
222 return false;
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));