[Media Router] Add integration tests and e2e tests for media router and presentation...
[chromium-blink-merge.git] / chrome / browser / signin / chrome_signin_client.cc
blobdc76c7b116a9b73b1cf5182cfb6a4ff164beb076
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.h"
13 #include "chrome/browser/net/chrome_cookie_notification_details.h"
14 #include "chrome/browser/profiles/profile_info_cache.h"
15 #include "chrome/browser/profiles/profile_manager.h"
16 #include "chrome/browser/profiles/profile_metrics.h"
17 #include "chrome/browser/profiles/profile_window.h"
18 #include "chrome/browser/signin/local_auth.h"
19 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
20 #include "chrome/browser/signin/signin_cookie_changed_subscription.h"
21 #include "chrome/browser/web_data_service_factory.h"
22 #include "chrome/common/chrome_version_info.h"
23 #include "components/metrics/metrics_service.h"
24 #include "components/signin/core/browser/profile_oauth2_token_service.h"
25 #include "components/signin/core/common/profile_management_switches.h"
26 #include "components/signin/core/common/signin_pref_names.h"
27 #include "components/signin/core/common/signin_switches.h"
28 #include "google_apis/gaia/gaia_constants.h"
29 #include "google_apis/gaia/gaia_urls.h"
30 #include "net/url_request/url_request_context_getter.h"
31 #include "url/gurl.h"
33 #if defined(ENABLE_SUPERVISED_USERS)
34 #include "chrome/browser/supervised_user/supervised_user_constants.h"
35 #endif
37 #if defined(OS_CHROMEOS)
38 #include "chrome/browser/chromeos/net/delay_network_call.h"
39 #include "chrome/browser/chromeos/profiles/profile_helper.h"
40 #include "components/user_manager/user_manager.h"
41 #endif
43 #if !defined(OS_ANDROID)
44 #include "chrome/browser/first_run/first_run.h"
45 #endif
47 namespace {
48 const char kEphemeralUserDeviceIDPrefix[] = "t_";
51 ChromeSigninClient::ChromeSigninClient(
52 Profile* profile, SigninErrorController* signin_error_controller)
53 : OAuth2TokenService::Consumer("chrome_signin_client"),
54 profile_(profile),
55 signin_error_controller_(signin_error_controller) {
56 signin_error_controller_->AddObserver(this);
57 #if !defined(OS_CHROMEOS)
58 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
59 #else
60 // UserManager may not exist in unit_tests.
61 if (!user_manager::UserManager::IsInitialized())
62 return;
64 const user_manager::User* user =
65 chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
66 if (!user)
67 return;
68 auto* user_manager = user_manager::UserManager::Get();
69 const std::string& user_id = user->GetUserID();
70 if (user_manager->GetKnownUserDeviceId(user_id).empty()) {
71 const std::string legacy_device_id =
72 GetPrefs()->GetString(prefs::kGoogleServicesSigninScopedDeviceId);
73 if (!legacy_device_id.empty()) {
74 // Need to move device ID from the old location to the new one, if it has
75 // not been done yet.
76 user_manager->SetKnownUserDeviceId(user_id, legacy_device_id);
77 } else {
78 user_manager->SetKnownUserDeviceId(
79 user_id,
80 GenerateSigninScopedDeviceID(
81 user_manager->IsUserNonCryptohomeDataEphemeral(user_id)));
84 GetPrefs()->SetString(prefs::kGoogleServicesSigninScopedDeviceId,
85 std::string());
86 #endif
89 ChromeSigninClient::~ChromeSigninClient() {
90 signin_error_controller_->RemoveObserver(this);
93 void ChromeSigninClient::Shutdown() {
94 #if !defined(OS_CHROMEOS)
95 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
96 #endif
99 void ChromeSigninClient::DoFinalInit() {
100 MaybeFetchSigninTokenHandle();
103 // static
104 bool ChromeSigninClient::ProfileAllowsSigninCookies(Profile* profile) {
105 CookieSettings* cookie_settings =
106 CookieSettings::Factory::GetForProfile(profile).get();
107 return SettingsAllowSigninCookies(cookie_settings);
110 // static
111 bool ChromeSigninClient::SettingsAllowSigninCookies(
112 CookieSettings* cookie_settings) {
113 GURL gaia_url = GaiaUrls::GetInstance()->gaia_url();
114 GURL google_url = GaiaUrls::GetInstance()->google_url();
115 return cookie_settings &&
116 cookie_settings->IsSettingCookieAllowed(gaia_url, gaia_url) &&
117 cookie_settings->IsSettingCookieAllowed(google_url, google_url);
120 // static
121 std::string ChromeSigninClient::GenerateSigninScopedDeviceID(
122 bool for_ephemeral) {
123 std::string guid = base::GenerateGUID();
124 return for_ephemeral ? kEphemeralUserDeviceIDPrefix + guid : guid;
127 PrefService* ChromeSigninClient::GetPrefs() { return profile_->GetPrefs(); }
129 scoped_refptr<TokenWebData> ChromeSigninClient::GetDatabase() {
130 return WebDataServiceFactory::GetTokenWebDataForProfile(
131 profile_, ServiceAccessType::EXPLICIT_ACCESS);
134 bool ChromeSigninClient::CanRevokeCredentials() {
135 #if defined(OS_CHROMEOS)
136 // UserManager may not exist in unit_tests.
137 if (user_manager::UserManager::IsInitialized() &&
138 user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser()) {
139 // Don't allow revoking credentials for Chrome OS supervised users.
140 // See http://crbug.com/332032
141 LOG(ERROR) << "Attempt to revoke supervised user refresh "
142 << "token detected, ignoring.";
143 return false;
145 #else
146 // Don't allow revoking credentials for legacy supervised users.
147 // See http://crbug.com/332032
148 if (profile_->IsLegacySupervised()) {
149 LOG(ERROR) << "Attempt to revoke supervised user refresh "
150 << "token detected, ignoring.";
151 return false;
153 #endif
154 return true;
157 std::string ChromeSigninClient::GetSigninScopedDeviceId() {
158 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
159 switches::kDisableSigninScopedDeviceId)) {
160 return std::string();
163 #if !defined(OS_CHROMEOS)
164 std::string signin_scoped_device_id =
165 GetPrefs()->GetString(prefs::kGoogleServicesSigninScopedDeviceId);
166 if (signin_scoped_device_id.empty()) {
167 // If device_id doesn't exist then generate new and save in prefs.
168 signin_scoped_device_id = GenerateSigninScopedDeviceID(false);
169 DCHECK(!signin_scoped_device_id.empty());
170 GetPrefs()->SetString(prefs::kGoogleServicesSigninScopedDeviceId,
171 signin_scoped_device_id);
173 return signin_scoped_device_id;
174 #else
175 // UserManager may not exist in unit_tests.
176 if (!user_manager::UserManager::IsInitialized())
177 return std::string();
179 const user_manager::User* user =
180 chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
181 if (!user)
182 return std::string();
184 const std::string signin_scoped_device_id =
185 user_manager::UserManager::Get()->GetKnownUserDeviceId(user->GetUserID());
186 LOG_IF(ERROR, signin_scoped_device_id.empty())
187 << "Device ID is not set for user.";
188 return signin_scoped_device_id;
189 #endif
192 void ChromeSigninClient::OnSignedOut() {
193 GetPrefs()->ClearPref(prefs::kGoogleServicesSigninScopedDeviceId);
194 ProfileInfoCache& cache =
195 g_browser_process->profile_manager()->GetProfileInfoCache();
196 size_t index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
198 // If sign out occurs because Sync setup was in progress and the Profile got
199 // deleted, then the profile's no longer in the ProfileInfoCache.
200 if (index == std::string::npos)
201 return;
203 cache.SetLocalAuthCredentialsOfProfileAtIndex(index, std::string());
204 cache.SetAuthInfoOfProfileAtIndex(index, std::string(), base::string16());
205 cache.SetProfileSigninRequiredAtIndex(index, false);
208 net::URLRequestContextGetter* ChromeSigninClient::GetURLRequestContext() {
209 return profile_->GetRequestContext();
212 bool ChromeSigninClient::ShouldMergeSigninCredentialsIntoCookieJar() {
213 return !switches::IsEnableAccountConsistency();
216 std::string ChromeSigninClient::GetProductVersion() {
217 chrome::VersionInfo chrome_version;
218 return chrome_version.CreateVersionString();
221 bool ChromeSigninClient::IsFirstRun() const {
222 #if defined(OS_ANDROID)
223 return false;
224 #else
225 return first_run::IsChromeFirstRun();
226 #endif
229 base::Time ChromeSigninClient::GetInstallDate() {
230 return base::Time::FromTimeT(
231 g_browser_process->metrics_service()->GetInstallDate());
234 bool ChromeSigninClient::AreSigninCookiesAllowed() {
235 return ProfileAllowsSigninCookies(profile_);
238 void ChromeSigninClient::AddContentSettingsObserver(
239 content_settings::Observer* observer) {
240 profile_->GetHostContentSettingsMap()->AddObserver(observer);
243 void ChromeSigninClient::RemoveContentSettingsObserver(
244 content_settings::Observer* observer) {
245 profile_->GetHostContentSettingsMap()->RemoveObserver(observer);
248 scoped_ptr<SigninClient::CookieChangedSubscription>
249 ChromeSigninClient::AddCookieChangedCallback(
250 const GURL& url,
251 const std::string& name,
252 const net::CookieStore::CookieChangedCallback& callback) {
253 scoped_refptr<net::URLRequestContextGetter> context_getter =
254 profile_->GetRequestContext();
255 DCHECK(context_getter.get());
256 scoped_ptr<SigninCookieChangedSubscription> subscription(
257 new SigninCookieChangedSubscription(context_getter, url, name, callback));
258 return subscription.Pass();
261 void ChromeSigninClient::OnSignedIn(const std::string& account_id,
262 const std::string& gaia_id,
263 const std::string& username,
264 const std::string& password) {
265 ProfileManager* profile_manager = g_browser_process->profile_manager();
266 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
267 size_t index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
268 if (index != std::string::npos) {
269 cache.SetAuthInfoOfProfileAtIndex(index, gaia_id,
270 base::UTF8ToUTF16(username));
271 ProfileMetrics::UpdateReportedProfilesStatistics(profile_manager);
275 void ChromeSigninClient::PostSignedIn(const std::string& account_id,
276 const std::string& username,
277 const std::string& password) {
278 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
279 // Don't store password hash except when lock is available for the user.
280 if (!password.empty() && profiles::IsLockAvailable(profile_))
281 LocalAuth::SetLocalAuthCredentials(profile_, password);
282 #endif
285 bool ChromeSigninClient::UpdateAccountInfo(
286 AccountTrackerService::AccountInfo* out_account_info) {
287 return false;
290 void ChromeSigninClient::OnErrorChanged() {
291 // Some tests don't have a ProfileManager.
292 if (g_browser_process->profile_manager() == nullptr)
293 return;
295 ProfileInfoCache& cache = g_browser_process->profile_manager()->
296 GetProfileInfoCache();
297 size_t index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
298 if (index == std::string::npos)
299 return;
301 cache.SetProfileIsAuthErrorAtIndex(index,
302 signin_error_controller_->HasError());
305 void ChromeSigninClient::OnGetTokenInfoResponse(
306 scoped_ptr<base::DictionaryValue> token_info) {
307 if (!token_info->HasKey("error")) {
308 std::string handle;
309 if (token_info->GetString("token_handle", &handle)) {
310 ProfileInfoCache& info_cache =
311 g_browser_process->profile_manager()->GetProfileInfoCache();
312 size_t index = info_cache.GetIndexOfProfileWithPath(profile_->GetPath());
313 info_cache.SetPasswordChangeDetectionTokenAtIndex(index, handle);
314 } else {
315 NOTREACHED();
318 oauth_request_.reset();
321 void ChromeSigninClient::OnOAuthError() {
322 // Ignore the failure. It's not essential and we'll try again next time.
323 oauth_request_.reset();
326 void ChromeSigninClient::OnNetworkError(int response_code) {
327 // Ignore the failure. It's not essential and we'll try again next time.
328 oauth_request_.reset();
331 void ChromeSigninClient::OnGetTokenSuccess(
332 const OAuth2TokenService::Request* request,
333 const std::string& access_token,
334 const base::Time& expiration_time) {
335 // Exchange the access token for a handle that can be used for later
336 // verification that the token is still valid (i.e. the password has not
337 // been changed).
338 if (!oauth_client_) {
339 oauth_client_.reset(new gaia::GaiaOAuthClient(
340 profile_->GetRequestContext()));
342 oauth_client_->GetTokenInfo(access_token, 3 /* retries */, this);
345 void ChromeSigninClient::OnGetTokenFailure(
346 const OAuth2TokenService::Request* request,
347 const GoogleServiceAuthError& error) {
348 // Ignore the failure. It's not essential and we'll try again next time.
349 oauth_request_.reset();
352 #if !defined(OS_CHROMEOS)
353 void ChromeSigninClient::OnNetworkChanged(
354 net::NetworkChangeNotifier::ConnectionType type) {
355 if (type >= net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE)
356 return;
358 for (const base::Closure& callback : delayed_callbacks_)
359 callback.Run();
361 delayed_callbacks_.clear();
363 #endif
365 void ChromeSigninClient::DelayNetworkCall(const base::Closure& callback) {
366 #if defined(OS_CHROMEOS)
367 chromeos::DelayNetworkCall(
368 base::TimeDelta::FromMilliseconds(chromeos::kDefaultNetworkRetryDelayMS),
369 callback);
370 return;
371 #else
372 // Don't bother if we don't have any kind of network connection.
373 if (net::NetworkChangeNotifier::IsOffline()) {
374 delayed_callbacks_.push_back(callback);
375 } else {
376 callback.Run();
378 #endif
381 GaiaAuthFetcher* ChromeSigninClient::CreateGaiaAuthFetcher(
382 GaiaAuthConsumer* consumer,
383 const std::string& source,
384 net::URLRequestContextGetter* getter) {
385 return new GaiaAuthFetcher(consumer, source, getter);
388 void ChromeSigninClient::MaybeFetchSigninTokenHandle() {
389 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
390 // We get a "handle" that can be used to reference the signin token on the
391 // server. We fetch this if we don't have one so that later we can check
392 // it to know if the signin token to which it is attached has been revoked
393 // and thus distinguish between a password mismatch due to the password
394 // being changed and the user simply mis-typing it.
395 if (profiles::IsLockAvailable(profile_)) {
396 ProfileInfoCache& info_cache =
397 g_browser_process->profile_manager()->GetProfileInfoCache();
398 size_t index = info_cache.GetIndexOfProfileWithPath(profile_->GetPath());
399 std::string token = info_cache.GetPasswordChangeDetectionTokenAtIndex(
400 index);
401 std::string account = profile_->GetProfileUserName();
402 if (token.empty() && !oauth_request_) {
403 // If we don't have a token for detecting a password change, create one.
404 ProfileOAuth2TokenService* token_service =
405 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
406 OAuth2TokenService::ScopeSet scopes;
407 scopes.insert(GaiaConstants::kGoogleUserInfoEmail);
408 oauth_request_ = token_service->StartRequest(account, scopes, this);
411 #endif