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 "chrome/browser/signin/chrome_signin_client.h"
7 #include "base/command_line.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/content_settings/cookie_settings_factory.h"
12 #include "chrome/browser/profiles/profile_info_cache.h"
13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "chrome/browser/profiles/profile_metrics.h"
15 #include "chrome/browser/profiles/profile_window.h"
16 #include "chrome/browser/signin/local_auth.h"
17 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
18 #include "chrome/browser/signin/signin_manager_factory.h"
19 #include "chrome/browser/web_data_service_factory.h"
20 #include "chrome/common/channel_info.h"
21 #include "components/content_settings/core/browser/cookie_settings.h"
22 #include "components/metrics/metrics_service.h"
23 #include "components/signin/core/browser/profile_oauth2_token_service.h"
24 #include "components/signin/core/browser/signin_cookie_changed_subscription.h"
25 #include "components/signin/core/browser/signin_header_helper.h"
26 #include "components/signin/core/common/profile_management_switches.h"
27 #include "components/signin/core/common/signin_pref_names.h"
28 #include "components/signin/core/common/signin_switches.h"
29 #include "google_apis/gaia/gaia_constants.h"
30 #include "google_apis/gaia/gaia_urls.h"
31 #include "net/url_request/url_request_context_getter.h"
34 #if defined(ENABLE_SUPERVISED_USERS)
35 #include "chrome/browser/supervised_user/supervised_user_constants.h"
38 #if defined(OS_CHROMEOS)
39 #include "chrome/browser/chromeos/net/delay_network_call.h"
40 #include "chrome/browser/chromeos/profiles/profile_helper.h"
41 #include "components/user_manager/user_manager.h"
44 #if !defined(OS_ANDROID)
45 #include "chrome/browser/first_run/first_run.h"
48 ChromeSigninClient::ChromeSigninClient(
49 Profile
* profile
, SigninErrorController
* signin_error_controller
)
50 : OAuth2TokenService::Consumer("chrome_signin_client"),
52 signin_error_controller_(signin_error_controller
) {
53 signin_error_controller_
->AddObserver(this);
54 #if !defined(OS_CHROMEOS)
55 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
57 // UserManager may not exist in unit_tests.
58 if (!user_manager::UserManager::IsInitialized())
61 const user_manager::User
* user
=
62 chromeos::ProfileHelper::Get()->GetUserByProfile(profile_
);
65 auto* user_manager
= user_manager::UserManager::Get();
66 const std::string
& user_id
= user
->GetUserID();
67 if (user_manager
->GetKnownUserDeviceId(user_id
).empty()) {
68 const std::string legacy_device_id
=
69 GetPrefs()->GetString(prefs::kGoogleServicesSigninScopedDeviceId
);
70 if (!legacy_device_id
.empty()) {
71 // Need to move device ID from the old location to the new one, if it has
73 user_manager
->SetKnownUserDeviceId(user_id
, legacy_device_id
);
75 user_manager
->SetKnownUserDeviceId(
77 GenerateSigninScopedDeviceID(
78 user_manager
->IsUserNonCryptohomeDataEphemeral(user_id
)));
81 GetPrefs()->SetString(prefs::kGoogleServicesSigninScopedDeviceId
,
86 ChromeSigninClient::~ChromeSigninClient() {
87 signin_error_controller_
->RemoveObserver(this);
90 void ChromeSigninClient::Shutdown() {
91 #if !defined(OS_CHROMEOS)
92 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
96 void ChromeSigninClient::DoFinalInit() {
97 MaybeFetchSigninTokenHandle();
101 bool ChromeSigninClient::ProfileAllowsSigninCookies(Profile
* profile
) {
102 content_settings::CookieSettings
* cookie_settings
=
103 CookieSettingsFactory::GetForProfile(profile
).get();
104 return signin::SettingsAllowSigninCookies(cookie_settings
);
107 PrefService
* ChromeSigninClient::GetPrefs() { return profile_
->GetPrefs(); }
109 scoped_refptr
<TokenWebData
> ChromeSigninClient::GetDatabase() {
110 return WebDataServiceFactory::GetTokenWebDataForProfile(
111 profile_
, ServiceAccessType::EXPLICIT_ACCESS
);
114 bool ChromeSigninClient::CanRevokeCredentials() {
115 #if defined(OS_CHROMEOS)
116 // UserManager may not exist in unit_tests.
117 if (user_manager::UserManager::IsInitialized() &&
118 user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser()) {
119 // Don't allow revoking credentials for Chrome OS supervised users.
120 // See http://crbug.com/332032
121 LOG(ERROR
) << "Attempt to revoke supervised user refresh "
122 << "token detected, ignoring.";
126 // Don't allow revoking credentials for legacy supervised users.
127 // See http://crbug.com/332032
128 if (profile_
->IsLegacySupervised()) {
129 LOG(ERROR
) << "Attempt to revoke supervised user refresh "
130 << "token detected, ignoring.";
137 std::string
ChromeSigninClient::GetSigninScopedDeviceId() {
138 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
139 switches::kDisableSigninScopedDeviceId
)) {
140 return std::string();
143 #if !defined(OS_CHROMEOS)
144 return SigninClient::GetOrCreateScopedDeviceIdPref(GetPrefs());
146 // UserManager may not exist in unit_tests.
147 if (!user_manager::UserManager::IsInitialized())
148 return std::string();
150 const user_manager::User
* user
=
151 chromeos::ProfileHelper::Get()->GetUserByProfile(profile_
);
153 return std::string();
155 const std::string signin_scoped_device_id
=
156 user_manager::UserManager::Get()->GetKnownUserDeviceId(user
->GetUserID());
157 LOG_IF(ERROR
, signin_scoped_device_id
.empty())
158 << "Device ID is not set for user.";
159 return signin_scoped_device_id
;
163 void ChromeSigninClient::OnSignedOut() {
164 ProfileInfoCache
& cache
=
165 g_browser_process
->profile_manager()->GetProfileInfoCache();
166 size_t index
= cache
.GetIndexOfProfileWithPath(profile_
->GetPath());
168 // If sign out occurs because Sync setup was in progress and the Profile got
169 // deleted, then the profile's no longer in the ProfileInfoCache.
170 if (index
== std::string::npos
)
173 cache
.SetLocalAuthCredentialsOfProfileAtIndex(index
, std::string());
174 cache
.SetAuthInfoOfProfileAtIndex(index
, std::string(), base::string16());
175 cache
.SetProfileSigninRequiredAtIndex(index
, false);
178 net::URLRequestContextGetter
* ChromeSigninClient::GetURLRequestContext() {
179 return profile_
->GetRequestContext();
182 bool ChromeSigninClient::ShouldMergeSigninCredentialsIntoCookieJar() {
183 return !switches::IsEnableAccountConsistency();
186 std::string
ChromeSigninClient::GetProductVersion() {
187 return chrome::GetVersionString();
190 bool ChromeSigninClient::IsFirstRun() const {
191 #if defined(OS_ANDROID)
194 return first_run::IsChromeFirstRun();
198 base::Time
ChromeSigninClient::GetInstallDate() {
199 return base::Time::FromTimeT(
200 g_browser_process
->metrics_service()->GetInstallDate());
203 bool ChromeSigninClient::AreSigninCookiesAllowed() {
204 return ProfileAllowsSigninCookies(profile_
);
207 void ChromeSigninClient::AddContentSettingsObserver(
208 content_settings::Observer
* observer
) {
209 profile_
->GetHostContentSettingsMap()->AddObserver(observer
);
212 void ChromeSigninClient::RemoveContentSettingsObserver(
213 content_settings::Observer
* observer
) {
214 profile_
->GetHostContentSettingsMap()->RemoveObserver(observer
);
217 scoped_ptr
<SigninClient::CookieChangedSubscription
>
218 ChromeSigninClient::AddCookieChangedCallback(
220 const std::string
& name
,
221 const net::CookieStore::CookieChangedCallback
& callback
) {
222 scoped_refptr
<net::URLRequestContextGetter
> context_getter
=
223 profile_
->GetRequestContext();
224 DCHECK(context_getter
.get());
225 scoped_ptr
<SigninCookieChangedSubscription
> subscription(
226 new SigninCookieChangedSubscription(context_getter
, url
, name
, callback
));
227 return subscription
.Pass();
230 void ChromeSigninClient::OnSignedIn(const std::string
& account_id
,
231 const std::string
& gaia_id
,
232 const std::string
& username
,
233 const std::string
& password
) {
234 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
235 ProfileInfoCache
& cache
= profile_manager
->GetProfileInfoCache();
236 size_t index
= cache
.GetIndexOfProfileWithPath(profile_
->GetPath());
237 if (index
!= std::string::npos
) {
238 cache
.SetAuthInfoOfProfileAtIndex(index
, gaia_id
,
239 base::UTF8ToUTF16(username
));
240 ProfileMetrics::UpdateReportedProfilesStatistics(profile_manager
);
244 void ChromeSigninClient::PostSignedIn(const std::string
& account_id
,
245 const std::string
& username
,
246 const std::string
& password
) {
247 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
248 // Don't store password hash except when lock is available for the user.
249 if (!password
.empty() && profiles::IsLockAvailable(profile_
))
250 LocalAuth::SetLocalAuthCredentials(profile_
, password
);
254 bool ChromeSigninClient::UpdateAccountInfo(AccountInfo
* out_account_info
) {
258 void ChromeSigninClient::OnErrorChanged() {
259 // Some tests don't have a ProfileManager.
260 if (g_browser_process
->profile_manager() == nullptr)
263 ProfileInfoCache
& cache
= g_browser_process
->profile_manager()->
264 GetProfileInfoCache();
265 size_t index
= cache
.GetIndexOfProfileWithPath(profile_
->GetPath());
266 if (index
== std::string::npos
)
269 cache
.SetProfileIsAuthErrorAtIndex(index
,
270 signin_error_controller_
->HasError());
273 void ChromeSigninClient::OnGetTokenInfoResponse(
274 scoped_ptr
<base::DictionaryValue
> token_info
) {
275 if (!token_info
->HasKey("error")) {
277 if (token_info
->GetString("token_handle", &handle
)) {
278 ProfileInfoCache
& info_cache
=
279 g_browser_process
->profile_manager()->GetProfileInfoCache();
280 size_t index
= info_cache
.GetIndexOfProfileWithPath(profile_
->GetPath());
281 info_cache
.SetPasswordChangeDetectionTokenAtIndex(index
, handle
);
284 oauth_request_
.reset();
287 void ChromeSigninClient::OnOAuthError() {
288 // Ignore the failure. It's not essential and we'll try again next time.
289 oauth_request_
.reset();
292 void ChromeSigninClient::OnNetworkError(int response_code
) {
293 // Ignore the failure. It's not essential and we'll try again next time.
294 oauth_request_
.reset();
297 void ChromeSigninClient::OnGetTokenSuccess(
298 const OAuth2TokenService::Request
* request
,
299 const std::string
& access_token
,
300 const base::Time
& expiration_time
) {
301 // Exchange the access token for a handle that can be used for later
302 // verification that the token is still valid (i.e. the password has not
304 if (!oauth_client_
) {
305 oauth_client_
.reset(new gaia::GaiaOAuthClient(
306 profile_
->GetRequestContext()));
308 oauth_client_
->GetTokenInfo(access_token
, 3 /* retries */, this);
311 void ChromeSigninClient::OnGetTokenFailure(
312 const OAuth2TokenService::Request
* request
,
313 const GoogleServiceAuthError
& error
) {
314 // Ignore the failure. It's not essential and we'll try again next time.
315 oauth_request_
.reset();
318 #if !defined(OS_CHROMEOS)
319 void ChromeSigninClient::OnNetworkChanged(
320 net::NetworkChangeNotifier::ConnectionType type
) {
321 if (type
>= net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE
)
324 for (const base::Closure
& callback
: delayed_callbacks_
)
327 delayed_callbacks_
.clear();
331 void ChromeSigninClient::DelayNetworkCall(const base::Closure
& callback
) {
332 #if defined(OS_CHROMEOS)
333 chromeos::DelayNetworkCall(
334 base::TimeDelta::FromMilliseconds(chromeos::kDefaultNetworkRetryDelayMS
),
338 // Don't bother if we don't have any kind of network connection.
339 if (net::NetworkChangeNotifier::IsOffline()) {
340 delayed_callbacks_
.push_back(callback
);
347 GaiaAuthFetcher
* ChromeSigninClient::CreateGaiaAuthFetcher(
348 GaiaAuthConsumer
* consumer
,
349 const std::string
& source
,
350 net::URLRequestContextGetter
* getter
) {
351 return new GaiaAuthFetcher(consumer
, source
, getter
);
354 void ChromeSigninClient::MaybeFetchSigninTokenHandle() {
355 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
356 // We get a "handle" that can be used to reference the signin token on the
357 // server. We fetch this if we don't have one so that later we can check
358 // it to know if the signin token to which it is attached has been revoked
359 // and thus distinguish between a password mismatch due to the password
360 // being changed and the user simply mis-typing it.
361 if (profiles::IsLockAvailable(profile_
)) {
362 ProfileInfoCache
& info_cache
=
363 g_browser_process
->profile_manager()->GetProfileInfoCache();
364 ProfileAttributesEntry
* entry
;
365 // If we don't have a token for detecting a password change, create one.
366 if (info_cache
.GetProfileAttributesWithPath(profile_
->GetPath(), &entry
) &&
367 entry
->GetPasswordChangeDetectionToken().empty() && !oauth_request_
) {
368 std::string account_id
= SigninManagerFactory::GetForProfile(profile_
)
369 ->GetAuthenticatedAccountId();
370 if (!account_id
.empty()) {
371 ProfileOAuth2TokenService
* token_service
=
372 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_
);
373 OAuth2TokenService::ScopeSet scopes
;
374 scopes
.insert(GaiaConstants::kGoogleUserInfoEmail
);
375 oauth_request_
= token_service
->StartRequest(account_id
, scopes
, this);