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"
9 #include "base/prefs/pref_service.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/chrome_notification_types.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/signin/local_auth.h"
17 #include "chrome/browser/webdata/web_data_service_factory.h"
18 #include "chrome/common/chrome_version_info.h"
19 #include "components/metrics/metrics_service.h"
20 #include "components/signin/core/common/profile_management_switches.h"
21 #include "components/signin/core/common/signin_pref_names.h"
22 #include "components/signin/core/common/signin_switches.h"
23 #include "content/public/browser/notification_details.h"
24 #include "content/public/browser/notification_source.h"
25 #include "content/public/browser/render_process_host.h"
26 #include "content/public/common/child_process_host.h"
29 #if defined(ENABLE_MANAGED_USERS)
30 #include "chrome/browser/supervised_user/supervised_user_constants.h"
33 #if defined(OS_CHROMEOS)
34 #include "components/user_manager/user_manager.h"
37 #if !defined(OS_ANDROID)
38 #include "chrome/browser/first_run/first_run.h"
41 using content::ChildProcessHost
;
42 using content::RenderProcessHost
;
46 const char kGoogleAccountsUrl
[] = "https://accounts.google.com";
50 ChromeSigninClient::ChromeSigninClient(Profile
* profile
)
51 : profile_(profile
), signin_host_id_(ChildProcessHost::kInvalidUniqueID
) {
52 callbacks_
.set_removal_callback(
53 base::Bind(&ChromeSigninClient::UnregisterForCookieChangedNotification
,
54 base::Unretained(this)));
57 ChromeSigninClient::~ChromeSigninClient() {
58 UnregisterForCookieChangedNotification();
60 std::set
<RenderProcessHost
*>::iterator i
;
61 for (i
= signin_hosts_observed_
.begin(); i
!= signin_hosts_observed_
.end();
63 (*i
)->RemoveObserver(this);
68 bool ChromeSigninClient::ProfileAllowsSigninCookies(Profile
* profile
) {
69 CookieSettings
* cookie_settings
=
70 CookieSettings::Factory::GetForProfile(profile
).get();
71 return SettingsAllowSigninCookies(cookie_settings
);
75 bool ChromeSigninClient::SettingsAllowSigninCookies(
76 CookieSettings
* cookie_settings
) {
77 return cookie_settings
&&
78 cookie_settings
->IsSettingCookieAllowed(GURL(kGoogleAccountsUrl
),
79 GURL(kGoogleAccountsUrl
));
82 void ChromeSigninClient::SetSigninProcess(int process_id
) {
83 if (process_id
== signin_host_id_
)
85 DLOG_IF(WARNING
, signin_host_id_
!= ChildProcessHost::kInvalidUniqueID
)
86 << "Replacing in-use signin process.";
87 signin_host_id_
= process_id
;
88 RenderProcessHost
* host
= RenderProcessHost::FromID(process_id
);
90 host
->AddObserver(this);
91 signin_hosts_observed_
.insert(host
);
94 void ChromeSigninClient::ClearSigninProcess() {
95 signin_host_id_
= ChildProcessHost::kInvalidUniqueID
;
98 bool ChromeSigninClient::IsSigninProcess(int process_id
) const {
99 return process_id
!= ChildProcessHost::kInvalidUniqueID
&&
100 process_id
== signin_host_id_
;
103 bool ChromeSigninClient::HasSigninProcess() const {
104 return signin_host_id_
!= ChildProcessHost::kInvalidUniqueID
;
107 void ChromeSigninClient::RenderProcessHostDestroyed(RenderProcessHost
* host
) {
108 // It's possible we're listening to a "stale" renderer because it was replaced
109 // with a new process by process-per-site. In either case, stop observing it,
110 // but only reset signin_host_id_ tracking if this was from the current signin
112 signin_hosts_observed_
.erase(host
);
113 if (signin_host_id_
== host
->GetID())
114 signin_host_id_
= ChildProcessHost::kInvalidUniqueID
;
117 PrefService
* ChromeSigninClient::GetPrefs() { return profile_
->GetPrefs(); }
119 scoped_refptr
<TokenWebData
> ChromeSigninClient::GetDatabase() {
120 return WebDataServiceFactory::GetTokenWebDataForProfile(
121 profile_
, Profile::EXPLICIT_ACCESS
);
124 bool ChromeSigninClient::CanRevokeCredentials() {
125 #if defined(OS_CHROMEOS)
126 // UserManager may not exist in unit_tests.
127 if (user_manager::UserManager::IsInitialized() &&
128 user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser()) {
129 // Don't allow revoking credentials for Chrome OS supervised users.
130 // See http://crbug.com/332032
131 LOG(ERROR
) << "Attempt to revoke supervised user refresh "
132 << "token detected, ignoring.";
136 // Don't allow revoking credentials for supervised users.
137 // See http://crbug.com/332032
138 if (profile_
->IsSupervised()) {
139 LOG(ERROR
) << "Attempt to revoke supervised user refresh "
140 << "token detected, ignoring.";
147 std::string
ChromeSigninClient::GetSigninScopedDeviceId() {
148 if (CommandLine::ForCurrentProcess()->HasSwitch(
149 switches::kDisableSigninScopedDeviceId
)) {
150 return std::string();
153 std::string signin_scoped_device_id
=
154 GetPrefs()->GetString(prefs::kGoogleServicesSigninScopedDeviceId
);
155 if (signin_scoped_device_id
.empty()) {
156 // If device_id doesn't exist then generate new and save in prefs.
157 signin_scoped_device_id
= base::GenerateGUID();
158 DCHECK(!signin_scoped_device_id
.empty());
159 GetPrefs()->SetString(prefs::kGoogleServicesSigninScopedDeviceId
,
160 signin_scoped_device_id
);
162 return signin_scoped_device_id
;
165 void ChromeSigninClient::OnSignedOut() {
166 GetPrefs()->ClearPref(prefs::kGoogleServicesSigninScopedDeviceId
);
167 ProfileInfoCache
& cache
=
168 g_browser_process
->profile_manager()->GetProfileInfoCache();
169 size_t index
= cache
.GetIndexOfProfileWithPath(profile_
->GetPath());
170 cache
.SetLocalAuthCredentialsOfProfileAtIndex(index
, std::string());
173 net::URLRequestContextGetter
* ChromeSigninClient::GetURLRequestContext() {
174 return profile_
->GetRequestContext();
177 bool ChromeSigninClient::ShouldMergeSigninCredentialsIntoCookieJar() {
178 // If inline sign in is enabled, but account consistency is not, the user's
179 // credentials should be merge into the cookie jar.
180 return !switches::IsEnableWebBasedSignin() &&
181 !switches::IsEnableAccountConsistency();
184 std::string
ChromeSigninClient::GetProductVersion() {
185 chrome::VersionInfo chrome_version
;
186 return chrome_version
.CreateVersionString();
189 bool ChromeSigninClient::IsFirstRun() const {
190 #if defined(OS_ANDROID)
193 return first_run::IsChromeFirstRun();
197 base::Time
ChromeSigninClient::GetInstallDate() {
198 return base::Time::FromTimeT(
199 g_browser_process
->metrics_service()->GetInstallDate());
202 scoped_ptr
<SigninClient::CookieChangedCallbackList::Subscription
>
203 ChromeSigninClient::AddCookieChangedCallback(
204 const CookieChangedCallback
& callback
) {
205 scoped_ptr
<SigninClient::CookieChangedCallbackList::Subscription
>
206 subscription
= callbacks_
.Add(callback
);
207 RegisterForCookieChangedNotification();
208 return subscription
.Pass();
211 void ChromeSigninClient::GoogleSigninSucceeded(const std::string
& account_id
,
212 const std::string
& username
,
213 const std::string
& password
) {
214 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
215 // Don't store password hash except for users of new profile management.
216 if (switches::IsNewProfileManagement())
217 chrome::SetLocalAuthCredentials(profile_
, password
);
221 void ChromeSigninClient::Observe(int type
,
222 const content::NotificationSource
& source
,
223 const content::NotificationDetails
& details
) {
225 case chrome::NOTIFICATION_COOKIE_CHANGED
: {
226 DCHECK(!callbacks_
.empty());
227 const net::CanonicalCookie
* cookie
=
228 content::Details
<ChromeCookieDetails
>(details
).ptr()->cookie
;
229 callbacks_
.Notify(cookie
);
238 void ChromeSigninClient::RegisterForCookieChangedNotification() {
239 if (callbacks_
.empty())
241 content::Source
<Profile
> source(profile_
);
242 if (!registrar_
.IsRegistered(
243 this, chrome::NOTIFICATION_COOKIE_CHANGED
, source
))
244 registrar_
.Add(this, chrome::NOTIFICATION_COOKIE_CHANGED
, source
);
247 void ChromeSigninClient::UnregisterForCookieChangedNotification() {
248 if (!callbacks_
.empty())
250 // Note that it's allowed to call this method multiple times without an
251 // intervening call to |RegisterForCookieChangedNotification()|.
252 content::Source
<Profile
> source(profile_
);
253 if (!registrar_
.IsRegistered(
254 this, chrome::NOTIFICATION_COOKIE_CHANGED
, source
))
256 registrar_
.Remove(this, chrome::NOTIFICATION_COOKIE_CHANGED
, source
);