Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / signin / chrome_signin_client.cc
blob3379a09728cee805e3740ed3b7030a63ba3338c8
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/content_settings/host_content_settings_map_factory.h"
13 #include "chrome/browser/profiles/profile_info_cache.h"
14 #include "chrome/browser/profiles/profile_manager.h"
15 #include "chrome/browser/profiles/profile_metrics.h"
16 #include "chrome/browser/profiles/profile_window.h"
17 #include "chrome/browser/signin/local_auth.h"
18 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
19 #include "chrome/browser/signin/signin_manager_factory.h"
20 #include "chrome/browser/web_data_service_factory.h"
21 #include "chrome/common/channel_info.h"
22 #include "components/content_settings/core/browser/cookie_settings.h"
23 #include "components/metrics/metrics_service.h"
24 #include "components/signin/core/browser/profile_oauth2_token_service.h"
25 #include "components/signin/core/browser/signin_cookie_changed_subscription.h"
26 #include "components/signin/core/browser/signin_header_helper.h"
27 #include "components/signin/core/common/profile_management_switches.h"
28 #include "components/signin/core/common/signin_pref_names.h"
29 #include "components/signin/core/common/signin_switches.h"
30 #include "google_apis/gaia/gaia_constants.h"
31 #include "google_apis/gaia/gaia_urls.h"
32 #include "net/url_request/url_request_context_getter.h"
33 #include "url/gurl.h"
35 #if defined(ENABLE_SUPERVISED_USERS)
36 #include "chrome/browser/supervised_user/supervised_user_constants.h"
37 #endif
39 #if defined(OS_CHROMEOS)
40 #include "chrome/browser/chromeos/net/delay_network_call.h"
41 #include "chrome/browser/chromeos/profiles/profile_helper.h"
42 #include "components/user_manager/user_manager.h"
43 #endif
45 #if !defined(OS_ANDROID)
46 #include "chrome/browser/first_run/first_run.h"
47 #endif
49 ChromeSigninClient::ChromeSigninClient(
50 Profile* profile, SigninErrorController* signin_error_controller)
51 : OAuth2TokenService::Consumer("chrome_signin_client"),
52 profile_(profile),
53 signin_error_controller_(signin_error_controller) {
54 signin_error_controller_->AddObserver(this);
55 #if !defined(OS_CHROMEOS)
56 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
57 #else
58 // UserManager may not exist in unit_tests.
59 if (!user_manager::UserManager::IsInitialized())
60 return;
62 const user_manager::User* user =
63 chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
64 if (!user)
65 return;
66 auto* user_manager = user_manager::UserManager::Get();
67 const std::string& user_id = user->GetUserID();
68 if (user_manager->GetKnownUserDeviceId(user_id).empty()) {
69 const std::string legacy_device_id =
70 GetPrefs()->GetString(prefs::kGoogleServicesSigninScopedDeviceId);
71 if (!legacy_device_id.empty()) {
72 // Need to move device ID from the old location to the new one, if it has
73 // not been done yet.
74 user_manager->SetKnownUserDeviceId(user_id, legacy_device_id);
75 } else {
76 user_manager->SetKnownUserDeviceId(
77 user_id,
78 GenerateSigninScopedDeviceID(
79 user_manager->IsUserNonCryptohomeDataEphemeral(user_id)));
82 GetPrefs()->SetString(prefs::kGoogleServicesSigninScopedDeviceId,
83 std::string());
84 #endif
87 ChromeSigninClient::~ChromeSigninClient() {
88 signin_error_controller_->RemoveObserver(this);
91 void ChromeSigninClient::Shutdown() {
92 #if !defined(OS_CHROMEOS)
93 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
94 #endif
97 void ChromeSigninClient::DoFinalInit() {
98 MaybeFetchSigninTokenHandle();
101 // static
102 bool ChromeSigninClient::ProfileAllowsSigninCookies(Profile* profile) {
103 content_settings::CookieSettings* cookie_settings =
104 CookieSettingsFactory::GetForProfile(profile).get();
105 return signin::SettingsAllowSigninCookies(cookie_settings);
108 PrefService* ChromeSigninClient::GetPrefs() { return profile_->GetPrefs(); }
110 scoped_refptr<TokenWebData> ChromeSigninClient::GetDatabase() {
111 return WebDataServiceFactory::GetTokenWebDataForProfile(
112 profile_, ServiceAccessType::EXPLICIT_ACCESS);
115 bool ChromeSigninClient::CanRevokeCredentials() {
116 #if defined(OS_CHROMEOS)
117 // UserManager may not exist in unit_tests.
118 if (user_manager::UserManager::IsInitialized() &&
119 user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser()) {
120 // Don't allow revoking credentials for Chrome OS supervised users.
121 // See http://crbug.com/332032
122 LOG(ERROR) << "Attempt to revoke supervised user refresh "
123 << "token detected, ignoring.";
124 return false;
126 #else
127 // Don't allow revoking credentials for legacy supervised users.
128 // See http://crbug.com/332032
129 if (profile_->IsLegacySupervised()) {
130 LOG(ERROR) << "Attempt to revoke supervised user refresh "
131 << "token detected, ignoring.";
132 return false;
134 #endif
135 return true;
138 std::string ChromeSigninClient::GetSigninScopedDeviceId() {
139 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
140 switches::kDisableSigninScopedDeviceId)) {
141 return std::string();
144 #if !defined(OS_CHROMEOS)
145 return SigninClient::GetOrCreateScopedDeviceIdPref(GetPrefs());
146 #else
147 // UserManager may not exist in unit_tests.
148 if (!user_manager::UserManager::IsInitialized())
149 return std::string();
151 const user_manager::User* user =
152 chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
153 if (!user)
154 return std::string();
156 const std::string signin_scoped_device_id =
157 user_manager::UserManager::Get()->GetKnownUserDeviceId(user->GetUserID());
158 LOG_IF(ERROR, signin_scoped_device_id.empty())
159 << "Device ID is not set for user.";
160 return signin_scoped_device_id;
161 #endif
164 void ChromeSigninClient::OnSignedOut() {
165 ProfileInfoCache& cache =
166 g_browser_process->profile_manager()->GetProfileInfoCache();
167 size_t index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
169 // If sign out occurs because Sync setup was in progress and the Profile got
170 // deleted, then the profile's no longer in the ProfileInfoCache.
171 if (index == std::string::npos)
172 return;
174 cache.SetLocalAuthCredentialsOfProfileAtIndex(index, std::string());
175 cache.SetAuthInfoOfProfileAtIndex(index, std::string(), base::string16());
176 cache.SetProfileSigninRequiredAtIndex(index, false);
179 net::URLRequestContextGetter* ChromeSigninClient::GetURLRequestContext() {
180 return profile_->GetRequestContext();
183 bool ChromeSigninClient::ShouldMergeSigninCredentialsIntoCookieJar() {
184 return !switches::IsEnableAccountConsistency();
187 std::string ChromeSigninClient::GetProductVersion() {
188 return chrome::GetVersionString();
191 bool ChromeSigninClient::IsFirstRun() const {
192 #if defined(OS_ANDROID)
193 return false;
194 #else
195 return first_run::IsChromeFirstRun();
196 #endif
199 base::Time ChromeSigninClient::GetInstallDate() {
200 return base::Time::FromTimeT(
201 g_browser_process->metrics_service()->GetInstallDate());
204 bool ChromeSigninClient::AreSigninCookiesAllowed() {
205 return ProfileAllowsSigninCookies(profile_);
208 void ChromeSigninClient::AddContentSettingsObserver(
209 content_settings::Observer* observer) {
210 HostContentSettingsMapFactory::GetForProfile(profile_)
211 ->AddObserver(observer);
214 void ChromeSigninClient::RemoveContentSettingsObserver(
215 content_settings::Observer* observer) {
216 HostContentSettingsMapFactory::GetForProfile(profile_)
217 ->RemoveObserver(observer);
220 scoped_ptr<SigninClient::CookieChangedSubscription>
221 ChromeSigninClient::AddCookieChangedCallback(
222 const GURL& url,
223 const std::string& name,
224 const net::CookieStore::CookieChangedCallback& callback) {
225 scoped_refptr<net::URLRequestContextGetter> context_getter =
226 profile_->GetRequestContext();
227 DCHECK(context_getter.get());
228 scoped_ptr<SigninCookieChangedSubscription> subscription(
229 new SigninCookieChangedSubscription(context_getter, url, name, callback));
230 return subscription.Pass();
233 void ChromeSigninClient::OnSignedIn(const std::string& account_id,
234 const std::string& gaia_id,
235 const std::string& username,
236 const std::string& password) {
237 ProfileManager* profile_manager = g_browser_process->profile_manager();
238 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
239 size_t index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
240 if (index != std::string::npos) {
241 cache.SetAuthInfoOfProfileAtIndex(index, gaia_id,
242 base::UTF8ToUTF16(username));
243 ProfileMetrics::UpdateReportedProfilesStatistics(profile_manager);
247 void ChromeSigninClient::PostSignedIn(const std::string& account_id,
248 const std::string& username,
249 const std::string& password) {
250 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
251 // Don't store password hash except when lock is available for the user.
252 if (!password.empty() && profiles::IsLockAvailable(profile_))
253 LocalAuth::SetLocalAuthCredentials(profile_, password);
254 #endif
257 bool ChromeSigninClient::UpdateAccountInfo(AccountInfo* out_account_info) {
258 return false;
261 void ChromeSigninClient::OnErrorChanged() {
262 // Some tests don't have a ProfileManager.
263 if (g_browser_process->profile_manager() == nullptr)
264 return;
266 ProfileInfoCache& cache = g_browser_process->profile_manager()->
267 GetProfileInfoCache();
268 size_t index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
269 if (index == std::string::npos)
270 return;
272 cache.SetProfileIsAuthErrorAtIndex(index,
273 signin_error_controller_->HasError());
276 void ChromeSigninClient::OnGetTokenInfoResponse(
277 scoped_ptr<base::DictionaryValue> token_info) {
278 if (!token_info->HasKey("error")) {
279 std::string handle;
280 if (token_info->GetString("token_handle", &handle)) {
281 ProfileInfoCache& info_cache =
282 g_browser_process->profile_manager()->GetProfileInfoCache();
283 size_t index = info_cache.GetIndexOfProfileWithPath(profile_->GetPath());
284 info_cache.SetPasswordChangeDetectionTokenAtIndex(index, handle);
287 oauth_request_.reset();
290 void ChromeSigninClient::OnOAuthError() {
291 // Ignore the failure. It's not essential and we'll try again next time.
292 oauth_request_.reset();
295 void ChromeSigninClient::OnNetworkError(int response_code) {
296 // Ignore the failure. It's not essential and we'll try again next time.
297 oauth_request_.reset();
300 void ChromeSigninClient::OnGetTokenSuccess(
301 const OAuth2TokenService::Request* request,
302 const std::string& access_token,
303 const base::Time& expiration_time) {
304 // Exchange the access token for a handle that can be used for later
305 // verification that the token is still valid (i.e. the password has not
306 // been changed).
307 if (!oauth_client_) {
308 oauth_client_.reset(new gaia::GaiaOAuthClient(
309 profile_->GetRequestContext()));
311 oauth_client_->GetTokenInfo(access_token, 3 /* retries */, this);
314 void ChromeSigninClient::OnGetTokenFailure(
315 const OAuth2TokenService::Request* request,
316 const GoogleServiceAuthError& error) {
317 // Ignore the failure. It's not essential and we'll try again next time.
318 oauth_request_.reset();
321 #if !defined(OS_CHROMEOS)
322 void ChromeSigninClient::OnNetworkChanged(
323 net::NetworkChangeNotifier::ConnectionType type) {
324 if (type >= net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE)
325 return;
327 for (const base::Closure& callback : delayed_callbacks_)
328 callback.Run();
330 delayed_callbacks_.clear();
332 #endif
334 void ChromeSigninClient::DelayNetworkCall(const base::Closure& callback) {
335 #if defined(OS_CHROMEOS)
336 chromeos::DelayNetworkCall(
337 base::TimeDelta::FromMilliseconds(chromeos::kDefaultNetworkRetryDelayMS),
338 callback);
339 return;
340 #else
341 // Don't bother if we don't have any kind of network connection.
342 if (net::NetworkChangeNotifier::IsOffline()) {
343 delayed_callbacks_.push_back(callback);
344 } else {
345 callback.Run();
347 #endif
350 GaiaAuthFetcher* ChromeSigninClient::CreateGaiaAuthFetcher(
351 GaiaAuthConsumer* consumer,
352 const std::string& source,
353 net::URLRequestContextGetter* getter) {
354 return new GaiaAuthFetcher(consumer, source, getter);
357 void ChromeSigninClient::MaybeFetchSigninTokenHandle() {
358 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
359 // We get a "handle" that can be used to reference the signin token on the
360 // server. We fetch this if we don't have one so that later we can check
361 // it to know if the signin token to which it is attached has been revoked
362 // and thus distinguish between a password mismatch due to the password
363 // being changed and the user simply mis-typing it.
364 if (profiles::IsLockAvailable(profile_)) {
365 ProfileInfoCache& info_cache =
366 g_browser_process->profile_manager()->GetProfileInfoCache();
367 ProfileAttributesEntry* entry;
368 // If we don't have a token for detecting a password change, create one.
369 if (info_cache.GetProfileAttributesWithPath(profile_->GetPath(), &entry) &&
370 entry->GetPasswordChangeDetectionToken().empty() && !oauth_request_) {
371 std::string account_id = SigninManagerFactory::GetForProfile(profile_)
372 ->GetAuthenticatedAccountId();
373 if (!account_id.empty()) {
374 ProfileOAuth2TokenService* token_service =
375 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
376 OAuth2TokenService::ScopeSet scopes;
377 scopes.insert(GaiaConstants::kGoogleUserInfoEmail);
378 oauth_request_ = token_service->StartRequest(account_id, scopes, this);
382 #endif