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.
4
5 #include "chrome/browser/signin/chrome_signin_client.h"
6
7 #include "chrome/browser/chrome_notification_types.h"
8 #include "chrome/browser/content_settings/cookie_settings.h"
9 #include "chrome/browser/net/chrome_cookie_notification_details.h"
10 #include "chrome/browser/signin/local_auth.h"
11 #include "chrome/browser/webdata/web_data_service_factory.h"
12 #include "chrome/common/chrome_version_info.h"
13 #include "components/signin/core/common/profile_management_switches.h"
14 #include "content/public/browser/notification_details.h"
15 #include "content/public/browser/notification_source.h"
16 #include "content/public/browser/render_process_host.h"
17 #include "content/public/common/child_process_host.h"
18 #include "url/gurl.h"
19
20 #if defined(ENABLE_MANAGED_USERS)
21 #include "chrome/browser/supervised_user/supervised_user_constants.h"
22 #endif
23
24 #if defined(OS_CHROMEOS)
25 #include "chrome/browser/chromeos/login/users/user_manager.h"
26 #endif
27
28 using content::ChildProcessHost;
29 using content::RenderProcessHost;
30
31 namespace {
32
33 const char kGoogleAccountsUrl[] = "https://accounts.google.com";
34
35 } // namespace
36
ChromeSigninClient(Profile * profile)37 ChromeSigninClient::ChromeSigninClient(Profile* profile)
38 : profile_(profile), signin_host_id_(ChildProcessHost::kInvalidUniqueID) {}
39
~ChromeSigninClient()40 ChromeSigninClient::~ChromeSigninClient() {
41 UnregisterForCookieChangedNotification();
42
43 std::set<RenderProcessHost*>::iterator i;
44 for (i = signin_hosts_observed_.begin(); i != signin_hosts_observed_.end();
45 ++i) {
46 (*i)->RemoveObserver(this);
47 }
48 }
49
50 // static
ProfileAllowsSigninCookies(Profile * profile)51 bool ChromeSigninClient::ProfileAllowsSigninCookies(Profile* profile) {
52 CookieSettings* cookie_settings =
53 CookieSettings::Factory::GetForProfile(profile).get();
54 return SettingsAllowSigninCookies(cookie_settings);
55 }
56
57 // static
SettingsAllowSigninCookies(CookieSettings * cookie_settings)58 bool ChromeSigninClient::SettingsAllowSigninCookies(
59 CookieSettings* cookie_settings) {
60 return cookie_settings &&
61 cookie_settings->IsSettingCookieAllowed(GURL(kGoogleAccountsUrl),
62 GURL(kGoogleAccountsUrl));
63 }
64
SetSigninProcess(int process_id)65 void ChromeSigninClient::SetSigninProcess(int process_id) {
66 if (process_id == signin_host_id_)
67 return;
68 DLOG_IF(WARNING, signin_host_id_ != ChildProcessHost::kInvalidUniqueID)
69 << "Replacing in-use signin process.";
70 signin_host_id_ = process_id;
71 RenderProcessHost* host = RenderProcessHost::FromID(process_id);
72 DCHECK(host);
73 host->AddObserver(this);
74 signin_hosts_observed_.insert(host);
75 }
76
ClearSigninProcess()77 void ChromeSigninClient::ClearSigninProcess() {
78 signin_host_id_ = ChildProcessHost::kInvalidUniqueID;
79 }
80
IsSigninProcess(int process_id) const81 bool ChromeSigninClient::IsSigninProcess(int process_id) const {
82 return process_id == signin_host_id_;
83 }
84
HasSigninProcess() const85 bool ChromeSigninClient::HasSigninProcess() const {
86 return signin_host_id_ != ChildProcessHost::kInvalidUniqueID;
87 }
88
RenderProcessHostDestroyed(RenderProcessHost * host)89 void ChromeSigninClient::RenderProcessHostDestroyed(RenderProcessHost* host) {
90 // It's possible we're listening to a "stale" renderer because it was replaced
91 // with a new process by process-per-site. In either case, stop observing it,
92 // but only reset signin_host_id_ tracking if this was from the current signin
93 // process.
94 signin_hosts_observed_.erase(host);
95 if (signin_host_id_ == host->GetID())
96 signin_host_id_ = ChildProcessHost::kInvalidUniqueID;
97 }
98
GetPrefs()99 PrefService* ChromeSigninClient::GetPrefs() { return profile_->GetPrefs(); }
100
GetDatabase()101 scoped_refptr<TokenWebData> ChromeSigninClient::GetDatabase() {
102 return WebDataServiceFactory::GetTokenWebDataForProfile(
103 profile_, Profile::EXPLICIT_ACCESS);
104 }
105
CanRevokeCredentials()106 bool ChromeSigninClient::CanRevokeCredentials() {
107 #if defined(OS_CHROMEOS)
108 // UserManager may not exist in unit_tests.
109 if (chromeos::UserManager::IsInitialized() &&
110 chromeos::UserManager::Get()->IsLoggedInAsLocallyManagedUser()) {
111 // Don't allow revoking credentials for Chrome OS supervised users.
112 // See http://crbug.com/332032
113 LOG(ERROR) << "Attempt to revoke supervised user refresh "
114 << "token detected, ignoring.";
115 return false;
116 }
117 #else
118 // Don't allow revoking credentials for supervised users.
119 // See http://crbug.com/332032
120 if (profile_->IsSupervised()) {
121 LOG(ERROR) << "Attempt to revoke supervised user refresh "
122 << "token detected, ignoring.";
123 return false;
124 }
125 #endif
126 return true;
127 }
128
GetURLRequestContext()129 net::URLRequestContextGetter* ChromeSigninClient::GetURLRequestContext() {
130 return profile_->GetRequestContext();
131 }
132
ShouldMergeSigninCredentialsIntoCookieJar()133 bool ChromeSigninClient::ShouldMergeSigninCredentialsIntoCookieJar() {
134 // If inline sign in is enabled, but new profile management is not, the user's
135 // credentials should be merge into the cookie jar.
136 return !switches::IsEnableWebBasedSignin() &&
137 !switches::IsNewProfileManagement();
138 }
139
GetProductVersion()140 std::string ChromeSigninClient::GetProductVersion() {
141 chrome::VersionInfo chrome_version;
142 if (!chrome_version.is_valid())
143 return "invalid";
144 return chrome_version.CreateVersionString();
145 }
146
SetCookieChangedCallback(const CookieChangedCallback & callback)147 void ChromeSigninClient::SetCookieChangedCallback(
148 const CookieChangedCallback& callback) {
149 if (callback_.Equals(callback))
150 return;
151
152 // There should be only one callback active at a time.
153 DCHECK(callback.is_null() || callback_.is_null());
154 callback_ = callback;
155 if (!callback_.is_null())
156 RegisterForCookieChangedNotification();
157 else
158 UnregisterForCookieChangedNotification();
159 }
160
GoogleSigninSucceeded(const std::string & username,const std::string & password)161 void ChromeSigninClient::GoogleSigninSucceeded(const std::string& username,
162 const std::string& password) {
163 #if !defined(OS_ANDROID)
164 // Don't store password hash except for users of new profile features.
165 if (switches::IsNewProfileManagement())
166 chrome::SetLocalAuthCredentials(profile_, password);
167 #endif
168 }
169
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)170 void ChromeSigninClient::Observe(int type,
171 const content::NotificationSource& source,
172 const content::NotificationDetails& details) {
173 switch (type) {
174 case chrome::NOTIFICATION_COOKIE_CHANGED: {
175 DCHECK(!callback_.is_null());
176 const net::CanonicalCookie* cookie =
177 content::Details<ChromeCookieDetails>(details).ptr()->cookie;
178 callback_.Run(cookie);
179 break;
180 }
181 default:
182 NOTREACHED();
183 break;
184 }
185 }
186
RegisterForCookieChangedNotification()187 void ChromeSigninClient::RegisterForCookieChangedNotification() {
188 content::Source<Profile> source(profile_);
189 DCHECK(!registrar_.IsRegistered(
190 this, chrome::NOTIFICATION_COOKIE_CHANGED, source));
191 registrar_.Add(this, chrome::NOTIFICATION_COOKIE_CHANGED, source);
192 }
193
UnregisterForCookieChangedNotification()194 void ChromeSigninClient::UnregisterForCookieChangedNotification() {
195 // Note that it's allowed to call this method multiple times without an
196 // intervening call to |RegisterForCookieChangedNotification()|.
197 content::Source<Profile> source(profile_);
198 if (!registrar_.IsRegistered(
199 this, chrome::NOTIFICATION_COOKIE_CHANGED, source))
200 return;
201 registrar_.Remove(this, chrome::NOTIFICATION_COOKIE_CHANGED, source);
202 }
203