Update V8 to version 4.6.22.
[chromium-blink-merge.git] / chrome / browser / signin / chrome_signin_client.cc
blob50bcd421091655ac720c1b22980313bbc0d949e4
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/guid.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/content_settings/cookie_settings_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/web_data_service_factory.h"
20 #include "chrome/common/chrome_version_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"
32 #include "url/gurl.h"
34 #if defined(ENABLE_SUPERVISED_USERS)
35 #include "chrome/browser/supervised_user/supervised_user_constants.h"
36 #endif
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"
42 #endif
44 #if !defined(OS_ANDROID)
45 #include "chrome/browser/first_run/first_run.h"
46 #endif
48 namespace {
49 const char kEphemeralUserDeviceIDPrefix[] = "t_";
52 ChromeSigninClient::ChromeSigninClient(
53 Profile* profile, SigninErrorController* signin_error_controller)
54 : OAuth2TokenService::Consumer("chrome_signin_client"),
55 profile_(profile),
56 signin_error_controller_(signin_error_controller) {
57 signin_error_controller_->AddObserver(this);
58 #if !defined(OS_CHROMEOS)
59 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
60 #else
61 // UserManager may not exist in unit_tests.
62 if (!user_manager::UserManager::IsInitialized())
63 return;
65 const user_manager::User* user =
66 chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
67 if (!user)
68 return;
69 auto* user_manager = user_manager::UserManager::Get();
70 const std::string& user_id = user->GetUserID();
71 if (user_manager->GetKnownUserDeviceId(user_id).empty()) {
72 const std::string legacy_device_id =
73 GetPrefs()->GetString(prefs::kGoogleServicesSigninScopedDeviceId);
74 if (!legacy_device_id.empty()) {
75 // Need to move device ID from the old location to the new one, if it has
76 // not been done yet.
77 user_manager->SetKnownUserDeviceId(user_id, legacy_device_id);
78 } else {
79 user_manager->SetKnownUserDeviceId(
80 user_id,
81 GenerateSigninScopedDeviceID(
82 user_manager->IsUserNonCryptohomeDataEphemeral(user_id)));
85 GetPrefs()->SetString(prefs::kGoogleServicesSigninScopedDeviceId,
86 std::string());
87 #endif
90 ChromeSigninClient::~ChromeSigninClient() {
91 signin_error_controller_->RemoveObserver(this);
94 void ChromeSigninClient::Shutdown() {
95 #if !defined(OS_CHROMEOS)
96 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
97 #endif
100 void ChromeSigninClient::DoFinalInit() {
101 MaybeFetchSigninTokenHandle();
104 // static
105 bool ChromeSigninClient::ProfileAllowsSigninCookies(Profile* profile) {
106 content_settings::CookieSettings* cookie_settings =
107 CookieSettingsFactory::GetForProfile(profile).get();
108 return signin::SettingsAllowSigninCookies(cookie_settings);
111 // static
112 std::string ChromeSigninClient::GenerateSigninScopedDeviceID(
113 bool for_ephemeral) {
114 std::string guid = base::GenerateGUID();
115 return for_ephemeral ? kEphemeralUserDeviceIDPrefix + guid : guid;
118 PrefService* ChromeSigninClient::GetPrefs() { return profile_->GetPrefs(); }
120 scoped_refptr<TokenWebData> ChromeSigninClient::GetDatabase() {
121 return WebDataServiceFactory::GetTokenWebDataForProfile(
122 profile_, ServiceAccessType::EXPLICIT_ACCESS);
125 bool ChromeSigninClient::CanRevokeCredentials() {
126 #if defined(OS_CHROMEOS)
127 // UserManager may not exist in unit_tests.
128 if (user_manager::UserManager::IsInitialized() &&
129 user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser()) {
130 // Don't allow revoking credentials for Chrome OS supervised users.
131 // See http://crbug.com/332032
132 LOG(ERROR) << "Attempt to revoke supervised user refresh "
133 << "token detected, ignoring.";
134 return false;
136 #else
137 // Don't allow revoking credentials for legacy supervised users.
138 // See http://crbug.com/332032
139 if (profile_->IsLegacySupervised()) {
140 LOG(ERROR) << "Attempt to revoke supervised user refresh "
141 << "token detected, ignoring.";
142 return false;
144 #endif
145 return true;
148 std::string ChromeSigninClient::GetSigninScopedDeviceId() {
149 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
150 switches::kDisableSigninScopedDeviceId)) {
151 return std::string();
154 #if !defined(OS_CHROMEOS)
155 std::string signin_scoped_device_id =
156 GetPrefs()->GetString(prefs::kGoogleServicesSigninScopedDeviceId);
157 if (signin_scoped_device_id.empty()) {
158 // If device_id doesn't exist then generate new and save in prefs.
159 signin_scoped_device_id = GenerateSigninScopedDeviceID(false);
160 DCHECK(!signin_scoped_device_id.empty());
161 GetPrefs()->SetString(prefs::kGoogleServicesSigninScopedDeviceId,
162 signin_scoped_device_id);
164 return signin_scoped_device_id;
165 #else
166 // UserManager may not exist in unit_tests.
167 if (!user_manager::UserManager::IsInitialized())
168 return std::string();
170 const user_manager::User* user =
171 chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
172 if (!user)
173 return std::string();
175 const std::string signin_scoped_device_id =
176 user_manager::UserManager::Get()->GetKnownUserDeviceId(user->GetUserID());
177 LOG_IF(ERROR, signin_scoped_device_id.empty())
178 << "Device ID is not set for user.";
179 return signin_scoped_device_id;
180 #endif
183 void ChromeSigninClient::OnSignedOut() {
184 GetPrefs()->ClearPref(prefs::kGoogleServicesSigninScopedDeviceId);
185 ProfileInfoCache& cache =
186 g_browser_process->profile_manager()->GetProfileInfoCache();
187 size_t index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
189 // If sign out occurs because Sync setup was in progress and the Profile got
190 // deleted, then the profile's no longer in the ProfileInfoCache.
191 if (index == std::string::npos)
192 return;
194 cache.SetLocalAuthCredentialsOfProfileAtIndex(index, std::string());
195 cache.SetAuthInfoOfProfileAtIndex(index, std::string(), base::string16());
196 cache.SetProfileSigninRequiredAtIndex(index, false);
199 net::URLRequestContextGetter* ChromeSigninClient::GetURLRequestContext() {
200 return profile_->GetRequestContext();
203 bool ChromeSigninClient::ShouldMergeSigninCredentialsIntoCookieJar() {
204 return !switches::IsEnableAccountConsistency();
207 std::string ChromeSigninClient::GetProductVersion() {
208 chrome::VersionInfo chrome_version;
209 return chrome_version.CreateVersionString();
212 bool ChromeSigninClient::IsFirstRun() const {
213 #if defined(OS_ANDROID)
214 return false;
215 #else
216 return first_run::IsChromeFirstRun();
217 #endif
220 base::Time ChromeSigninClient::GetInstallDate() {
221 return base::Time::FromTimeT(
222 g_browser_process->metrics_service()->GetInstallDate());
225 bool ChromeSigninClient::AreSigninCookiesAllowed() {
226 return ProfileAllowsSigninCookies(profile_);
229 void ChromeSigninClient::AddContentSettingsObserver(
230 content_settings::Observer* observer) {
231 profile_->GetHostContentSettingsMap()->AddObserver(observer);
234 void ChromeSigninClient::RemoveContentSettingsObserver(
235 content_settings::Observer* observer) {
236 profile_->GetHostContentSettingsMap()->RemoveObserver(observer);
239 scoped_ptr<SigninClient::CookieChangedSubscription>
240 ChromeSigninClient::AddCookieChangedCallback(
241 const GURL& url,
242 const std::string& name,
243 const net::CookieStore::CookieChangedCallback& callback) {
244 scoped_refptr<net::URLRequestContextGetter> context_getter =
245 profile_->GetRequestContext();
246 DCHECK(context_getter.get());
247 scoped_ptr<SigninCookieChangedSubscription> subscription(
248 new SigninCookieChangedSubscription(context_getter, url, name, callback));
249 return subscription.Pass();
252 void ChromeSigninClient::OnSignedIn(const std::string& account_id,
253 const std::string& gaia_id,
254 const std::string& username,
255 const std::string& password) {
256 ProfileManager* profile_manager = g_browser_process->profile_manager();
257 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
258 size_t index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
259 if (index != std::string::npos) {
260 cache.SetAuthInfoOfProfileAtIndex(index, gaia_id,
261 base::UTF8ToUTF16(username));
262 ProfileMetrics::UpdateReportedProfilesStatistics(profile_manager);
266 void ChromeSigninClient::PostSignedIn(const std::string& account_id,
267 const std::string& username,
268 const std::string& password) {
269 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
270 // Don't store password hash except when lock is available for the user.
271 if (!password.empty() && profiles::IsLockAvailable(profile_))
272 LocalAuth::SetLocalAuthCredentials(profile_, password);
273 #endif
276 bool ChromeSigninClient::UpdateAccountInfo(
277 AccountTrackerService::AccountInfo* out_account_info) {
278 return false;
281 void ChromeSigninClient::OnErrorChanged() {
282 // Some tests don't have a ProfileManager.
283 if (g_browser_process->profile_manager() == nullptr)
284 return;
286 ProfileInfoCache& cache = g_browser_process->profile_manager()->
287 GetProfileInfoCache();
288 size_t index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
289 if (index == std::string::npos)
290 return;
292 cache.SetProfileIsAuthErrorAtIndex(index,
293 signin_error_controller_->HasError());
296 void ChromeSigninClient::OnGetTokenInfoResponse(
297 scoped_ptr<base::DictionaryValue> token_info) {
298 if (!token_info->HasKey("error")) {
299 std::string handle;
300 if (token_info->GetString("token_handle", &handle)) {
301 ProfileInfoCache& info_cache =
302 g_browser_process->profile_manager()->GetProfileInfoCache();
303 size_t index = info_cache.GetIndexOfProfileWithPath(profile_->GetPath());
304 info_cache.SetPasswordChangeDetectionTokenAtIndex(index, handle);
305 } else {
306 NOTREACHED();
309 oauth_request_.reset();
312 void ChromeSigninClient::OnOAuthError() {
313 // Ignore the failure. It's not essential and we'll try again next time.
314 oauth_request_.reset();
317 void ChromeSigninClient::OnNetworkError(int response_code) {
318 // Ignore the failure. It's not essential and we'll try again next time.
319 oauth_request_.reset();
322 void ChromeSigninClient::OnGetTokenSuccess(
323 const OAuth2TokenService::Request* request,
324 const std::string& access_token,
325 const base::Time& expiration_time) {
326 // Exchange the access token for a handle that can be used for later
327 // verification that the token is still valid (i.e. the password has not
328 // been changed).
329 if (!oauth_client_) {
330 oauth_client_.reset(new gaia::GaiaOAuthClient(
331 profile_->GetRequestContext()));
333 oauth_client_->GetTokenInfo(access_token, 3 /* retries */, this);
336 void ChromeSigninClient::OnGetTokenFailure(
337 const OAuth2TokenService::Request* request,
338 const GoogleServiceAuthError& error) {
339 // Ignore the failure. It's not essential and we'll try again next time.
340 oauth_request_.reset();
343 #if !defined(OS_CHROMEOS)
344 void ChromeSigninClient::OnNetworkChanged(
345 net::NetworkChangeNotifier::ConnectionType type) {
346 if (type >= net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE)
347 return;
349 for (const base::Closure& callback : delayed_callbacks_)
350 callback.Run();
352 delayed_callbacks_.clear();
354 #endif
356 void ChromeSigninClient::DelayNetworkCall(const base::Closure& callback) {
357 #if defined(OS_CHROMEOS)
358 chromeos::DelayNetworkCall(
359 base::TimeDelta::FromMilliseconds(chromeos::kDefaultNetworkRetryDelayMS),
360 callback);
361 return;
362 #else
363 // Don't bother if we don't have any kind of network connection.
364 if (net::NetworkChangeNotifier::IsOffline()) {
365 delayed_callbacks_.push_back(callback);
366 } else {
367 callback.Run();
369 #endif
372 GaiaAuthFetcher* ChromeSigninClient::CreateGaiaAuthFetcher(
373 GaiaAuthConsumer* consumer,
374 const std::string& source,
375 net::URLRequestContextGetter* getter) {
376 return new GaiaAuthFetcher(consumer, source, getter);
379 void ChromeSigninClient::MaybeFetchSigninTokenHandle() {
380 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
381 // We get a "handle" that can be used to reference the signin token on the
382 // server. We fetch this if we don't have one so that later we can check
383 // it to know if the signin token to which it is attached has been revoked
384 // and thus distinguish between a password mismatch due to the password
385 // being changed and the user simply mis-typing it.
386 if (profiles::IsLockAvailable(profile_)) {
387 ProfileInfoCache& info_cache =
388 g_browser_process->profile_manager()->GetProfileInfoCache();
389 size_t index = info_cache.GetIndexOfProfileWithPath(profile_->GetPath());
390 std::string token = info_cache.GetPasswordChangeDetectionTokenAtIndex(
391 index);
392 std::string account = profile_->GetProfileUserName();
393 if (token.empty() && !oauth_request_) {
394 // If we don't have a token for detecting a password change, create one.
395 ProfileOAuth2TokenService* token_service =
396 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
397 OAuth2TokenService::ScopeSet scopes;
398 scopes.insert(GaiaConstants::kGoogleUserInfoEmail);
399 oauth_request_ = token_service->StartRequest(account, scopes, this);
402 #endif