Allow only one bookmark to be added for multiple fast starring
[chromium-blink-merge.git] / chrome / browser / signin / chrome_signin_client.cc
blobf72d1ee3a45e4dd748f1fefb99cd21eed3a3a99a
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/web_data_service_factory.h"
19 #include "chrome/common/channel_info.h"
20 #include "components/content_settings/core/browser/cookie_settings.h"
21 #include "components/metrics/metrics_service.h"
22 #include "components/signin/core/browser/profile_oauth2_token_service.h"
23 #include "components/signin/core/browser/signin_cookie_changed_subscription.h"
24 #include "components/signin/core/browser/signin_header_helper.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 ChromeSigninClient::ChromeSigninClient(
48 Profile* profile, SigninErrorController* signin_error_controller)
49 : OAuth2TokenService::Consumer("chrome_signin_client"),
50 profile_(profile),
51 signin_error_controller_(signin_error_controller) {
52 signin_error_controller_->AddObserver(this);
53 #if !defined(OS_CHROMEOS)
54 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
55 #else
56 // UserManager may not exist in unit_tests.
57 if (!user_manager::UserManager::IsInitialized())
58 return;
60 const user_manager::User* user =
61 chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
62 if (!user)
63 return;
64 auto* user_manager = user_manager::UserManager::Get();
65 const std::string& user_id = user->GetUserID();
66 if (user_manager->GetKnownUserDeviceId(user_id).empty()) {
67 const std::string legacy_device_id =
68 GetPrefs()->GetString(prefs::kGoogleServicesSigninScopedDeviceId);
69 if (!legacy_device_id.empty()) {
70 // Need to move device ID from the old location to the new one, if it has
71 // not been done yet.
72 user_manager->SetKnownUserDeviceId(user_id, legacy_device_id);
73 } else {
74 user_manager->SetKnownUserDeviceId(
75 user_id,
76 GenerateSigninScopedDeviceID(
77 user_manager->IsUserNonCryptohomeDataEphemeral(user_id)));
80 GetPrefs()->SetString(prefs::kGoogleServicesSigninScopedDeviceId,
81 std::string());
82 #endif
85 ChromeSigninClient::~ChromeSigninClient() {
86 signin_error_controller_->RemoveObserver(this);
89 void ChromeSigninClient::Shutdown() {
90 #if !defined(OS_CHROMEOS)
91 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
92 #endif
95 void ChromeSigninClient::DoFinalInit() {
96 MaybeFetchSigninTokenHandle();
99 // static
100 bool ChromeSigninClient::ProfileAllowsSigninCookies(Profile* profile) {
101 content_settings::CookieSettings* cookie_settings =
102 CookieSettingsFactory::GetForProfile(profile).get();
103 return signin::SettingsAllowSigninCookies(cookie_settings);
106 PrefService* ChromeSigninClient::GetPrefs() { return profile_->GetPrefs(); }
108 scoped_refptr<TokenWebData> ChromeSigninClient::GetDatabase() {
109 return WebDataServiceFactory::GetTokenWebDataForProfile(
110 profile_, ServiceAccessType::EXPLICIT_ACCESS);
113 bool ChromeSigninClient::CanRevokeCredentials() {
114 #if defined(OS_CHROMEOS)
115 // UserManager may not exist in unit_tests.
116 if (user_manager::UserManager::IsInitialized() &&
117 user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser()) {
118 // Don't allow revoking credentials for Chrome OS supervised users.
119 // See http://crbug.com/332032
120 LOG(ERROR) << "Attempt to revoke supervised user refresh "
121 << "token detected, ignoring.";
122 return false;
124 #else
125 // Don't allow revoking credentials for legacy supervised users.
126 // See http://crbug.com/332032
127 if (profile_->IsLegacySupervised()) {
128 LOG(ERROR) << "Attempt to revoke supervised user refresh "
129 << "token detected, ignoring.";
130 return false;
132 #endif
133 return true;
136 std::string ChromeSigninClient::GetSigninScopedDeviceId() {
137 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
138 switches::kDisableSigninScopedDeviceId)) {
139 return std::string();
142 #if !defined(OS_CHROMEOS)
143 return SigninClient::GetOrCreateScopedDeviceIdPref(GetPrefs());
144 #else
145 // UserManager may not exist in unit_tests.
146 if (!user_manager::UserManager::IsInitialized())
147 return std::string();
149 const user_manager::User* user =
150 chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
151 if (!user)
152 return std::string();
154 const std::string signin_scoped_device_id =
155 user_manager::UserManager::Get()->GetKnownUserDeviceId(user->GetUserID());
156 LOG_IF(ERROR, signin_scoped_device_id.empty())
157 << "Device ID is not set for user.";
158 return signin_scoped_device_id;
159 #endif
162 void ChromeSigninClient::OnSignedOut() {
163 ProfileInfoCache& cache =
164 g_browser_process->profile_manager()->GetProfileInfoCache();
165 size_t index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
167 // If sign out occurs because Sync setup was in progress and the Profile got
168 // deleted, then the profile's no longer in the ProfileInfoCache.
169 if (index == std::string::npos)
170 return;
172 cache.SetLocalAuthCredentialsOfProfileAtIndex(index, std::string());
173 cache.SetAuthInfoOfProfileAtIndex(index, std::string(), base::string16());
174 cache.SetProfileSigninRequiredAtIndex(index, false);
177 net::URLRequestContextGetter* ChromeSigninClient::GetURLRequestContext() {
178 return profile_->GetRequestContext();
181 bool ChromeSigninClient::ShouldMergeSigninCredentialsIntoCookieJar() {
182 return !switches::IsEnableAccountConsistency();
185 std::string ChromeSigninClient::GetProductVersion() {
186 return chrome::GetVersionString();
189 bool ChromeSigninClient::IsFirstRun() const {
190 #if defined(OS_ANDROID)
191 return false;
192 #else
193 return first_run::IsChromeFirstRun();
194 #endif
197 base::Time ChromeSigninClient::GetInstallDate() {
198 return base::Time::FromTimeT(
199 g_browser_process->metrics_service()->GetInstallDate());
202 bool ChromeSigninClient::AreSigninCookiesAllowed() {
203 return ProfileAllowsSigninCookies(profile_);
206 void ChromeSigninClient::AddContentSettingsObserver(
207 content_settings::Observer* observer) {
208 profile_->GetHostContentSettingsMap()->AddObserver(observer);
211 void ChromeSigninClient::RemoveContentSettingsObserver(
212 content_settings::Observer* observer) {
213 profile_->GetHostContentSettingsMap()->RemoveObserver(observer);
216 scoped_ptr<SigninClient::CookieChangedSubscription>
217 ChromeSigninClient::AddCookieChangedCallback(
218 const GURL& url,
219 const std::string& name,
220 const net::CookieStore::CookieChangedCallback& callback) {
221 scoped_refptr<net::URLRequestContextGetter> context_getter =
222 profile_->GetRequestContext();
223 DCHECK(context_getter.get());
224 scoped_ptr<SigninCookieChangedSubscription> subscription(
225 new SigninCookieChangedSubscription(context_getter, url, name, callback));
226 return subscription.Pass();
229 void ChromeSigninClient::OnSignedIn(const std::string& account_id,
230 const std::string& gaia_id,
231 const std::string& username,
232 const std::string& password) {
233 ProfileManager* profile_manager = g_browser_process->profile_manager();
234 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
235 size_t index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
236 if (index != std::string::npos) {
237 cache.SetAuthInfoOfProfileAtIndex(index, gaia_id,
238 base::UTF8ToUTF16(username));
239 ProfileMetrics::UpdateReportedProfilesStatistics(profile_manager);
243 void ChromeSigninClient::PostSignedIn(const std::string& account_id,
244 const std::string& username,
245 const std::string& password) {
246 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
247 // Don't store password hash except when lock is available for the user.
248 if (!password.empty() && profiles::IsLockAvailable(profile_))
249 LocalAuth::SetLocalAuthCredentials(profile_, password);
250 #endif
253 bool ChromeSigninClient::UpdateAccountInfo(
254 AccountTrackerService::AccountInfo* out_account_info) {
255 return false;
258 void ChromeSigninClient::OnErrorChanged() {
259 // Some tests don't have a ProfileManager.
260 if (g_browser_process->profile_manager() == nullptr)
261 return;
263 ProfileInfoCache& cache = g_browser_process->profile_manager()->
264 GetProfileInfoCache();
265 size_t index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
266 if (index == std::string::npos)
267 return;
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")) {
276 std::string handle;
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);
282 } else {
283 NOTREACHED();
286 oauth_request_.reset();
289 void ChromeSigninClient::OnOAuthError() {
290 // Ignore the failure. It's not essential and we'll try again next time.
291 oauth_request_.reset();
294 void ChromeSigninClient::OnNetworkError(int response_code) {
295 // Ignore the failure. It's not essential and we'll try again next time.
296 oauth_request_.reset();
299 void ChromeSigninClient::OnGetTokenSuccess(
300 const OAuth2TokenService::Request* request,
301 const std::string& access_token,
302 const base::Time& expiration_time) {
303 // Exchange the access token for a handle that can be used for later
304 // verification that the token is still valid (i.e. the password has not
305 // been changed).
306 if (!oauth_client_) {
307 oauth_client_.reset(new gaia::GaiaOAuthClient(
308 profile_->GetRequestContext()));
310 oauth_client_->GetTokenInfo(access_token, 3 /* retries */, this);
313 void ChromeSigninClient::OnGetTokenFailure(
314 const OAuth2TokenService::Request* request,
315 const GoogleServiceAuthError& error) {
316 // Ignore the failure. It's not essential and we'll try again next time.
317 oauth_request_.reset();
320 #if !defined(OS_CHROMEOS)
321 void ChromeSigninClient::OnNetworkChanged(
322 net::NetworkChangeNotifier::ConnectionType type) {
323 if (type >= net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE)
324 return;
326 for (const base::Closure& callback : delayed_callbacks_)
327 callback.Run();
329 delayed_callbacks_.clear();
331 #endif
333 void ChromeSigninClient::DelayNetworkCall(const base::Closure& callback) {
334 #if defined(OS_CHROMEOS)
335 chromeos::DelayNetworkCall(
336 base::TimeDelta::FromMilliseconds(chromeos::kDefaultNetworkRetryDelayMS),
337 callback);
338 return;
339 #else
340 // Don't bother if we don't have any kind of network connection.
341 if (net::NetworkChangeNotifier::IsOffline()) {
342 delayed_callbacks_.push_back(callback);
343 } else {
344 callback.Run();
346 #endif
349 GaiaAuthFetcher* ChromeSigninClient::CreateGaiaAuthFetcher(
350 GaiaAuthConsumer* consumer,
351 const std::string& source,
352 net::URLRequestContextGetter* getter) {
353 return new GaiaAuthFetcher(consumer, source, getter);
356 void ChromeSigninClient::MaybeFetchSigninTokenHandle() {
357 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
358 // We get a "handle" that can be used to reference the signin token on the
359 // server. We fetch this if we don't have one so that later we can check
360 // it to know if the signin token to which it is attached has been revoked
361 // and thus distinguish between a password mismatch due to the password
362 // being changed and the user simply mis-typing it.
363 if (profiles::IsLockAvailable(profile_)) {
364 ProfileInfoCache& info_cache =
365 g_browser_process->profile_manager()->GetProfileInfoCache();
366 size_t index = info_cache.GetIndexOfProfileWithPath(profile_->GetPath());
367 std::string token = info_cache.GetPasswordChangeDetectionTokenAtIndex(
368 index);
369 std::string account = profile_->GetProfileUserName();
370 if (token.empty() && !oauth_request_) {
371 // If we don't have a token for detecting a password change, create one.
372 ProfileOAuth2TokenService* token_service =
373 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
374 OAuth2TokenService::ScopeSet scopes;
375 scopes.insert(GaiaConstants::kGoogleUserInfoEmail);
376 oauth_request_ = token_service->StartRequest(account, scopes, this);
379 #endif