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 "base/command_line.h" 8 #include "base/guid.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/signin/local_auth.h" 15 #include "chrome/browser/webdata/web_data_service_factory.h" 16 #include "chrome/common/chrome_version_info.h" 17 #include "components/metrics/metrics_service.h" 18 #include "components/signin/core/common/profile_management_switches.h" 19 #include "components/signin/core/common/signin_pref_names.h" 20 #include "components/signin/core/common/signin_switches.h" 21 #include "content/public/browser/notification_details.h" 22 #include "content/public/browser/notification_source.h" 23 #include "content/public/browser/render_process_host.h" 24 #include "content/public/common/child_process_host.h" 25 #include "url/gurl.h" 26 27 #if defined(ENABLE_MANAGED_USERS) 28 #include "chrome/browser/supervised_user/supervised_user_constants.h" 29 #endif 30 31 #if defined(OS_CHROMEOS) 32 #include "components/user_manager/user_manager.h" 33 #endif 34 35 #if !defined(OS_ANDROID) 36 #include "chrome/browser/first_run/first_run.h" 37 #endif 38 39 using content::ChildProcessHost; 40 using content::RenderProcessHost; 41 42 namespace { 43 44 const char kGoogleAccountsUrl[] = "https://accounts.google.com"; 45 46 } // namespace 47 48 ChromeSigninClient::ChromeSigninClient(Profile* profile) 49 : profile_(profile), signin_host_id_(ChildProcessHost::kInvalidUniqueID) { 50 callbacks_.set_removal_callback( 51 base::Bind(&ChromeSigninClient::UnregisterForCookieChangedNotification, 52 base::Unretained(this))); 53 } 54 55 ChromeSigninClient::~ChromeSigninClient() { 56 UnregisterForCookieChangedNotification(); 57 58 std::set<RenderProcessHost*>::iterator i; 59 for (i = signin_hosts_observed_.begin(); i != signin_hosts_observed_.end(); 60 ++i) { 61 (*i)->RemoveObserver(this); 62 } 63 } 64 65 // static 66 bool ChromeSigninClient::ProfileAllowsSigninCookies(Profile* profile) { 67 CookieSettings* cookie_settings = 68 CookieSettings::Factory::GetForProfile(profile).get(); 69 return SettingsAllowSigninCookies(cookie_settings); 70 } 71 72 // static 73 bool ChromeSigninClient::SettingsAllowSigninCookies( 74 CookieSettings* cookie_settings) { 75 return cookie_settings && 76 cookie_settings->IsSettingCookieAllowed(GURL(kGoogleAccountsUrl), 77 GURL(kGoogleAccountsUrl)); 78 } 79 80 void ChromeSigninClient::SetSigninProcess(int process_id) { 81 if (process_id == signin_host_id_) 82 return; 83 DLOG_IF(WARNING, signin_host_id_ != ChildProcessHost::kInvalidUniqueID) 84 << "Replacing in-use signin process."; 85 signin_host_id_ = process_id; 86 RenderProcessHost* host = RenderProcessHost::FromID(process_id); 87 DCHECK(host); 88 host->AddObserver(this); 89 signin_hosts_observed_.insert(host); 90 } 91 92 void ChromeSigninClient::ClearSigninProcess() { 93 signin_host_id_ = ChildProcessHost::kInvalidUniqueID; 94 } 95 96 bool ChromeSigninClient::IsSigninProcess(int process_id) const { 97 return process_id != ChildProcessHost::kInvalidUniqueID && 98 process_id == signin_host_id_; 99 } 100 101 bool ChromeSigninClient::HasSigninProcess() const { 102 return signin_host_id_ != ChildProcessHost::kInvalidUniqueID; 103 } 104 105 void ChromeSigninClient::RenderProcessHostDestroyed(RenderProcessHost* host) { 106 // It's possible we're listening to a "stale" renderer because it was replaced 107 // with a new process by process-per-site. In either case, stop observing it, 108 // but only reset signin_host_id_ tracking if this was from the current signin 109 // process. 110 signin_hosts_observed_.erase(host); 111 if (signin_host_id_ == host->GetID()) 112 signin_host_id_ = ChildProcessHost::kInvalidUniqueID; 113 } 114 115 PrefService* ChromeSigninClient::GetPrefs() { return profile_->GetPrefs(); } 116 117 scoped_refptr<TokenWebData> ChromeSigninClient::GetDatabase() { 118 return WebDataServiceFactory::GetTokenWebDataForProfile( 119 profile_, Profile::EXPLICIT_ACCESS); 120 } 121 122 bool ChromeSigninClient::CanRevokeCredentials() { 123 #if defined(OS_CHROMEOS) 124 // UserManager may not exist in unit_tests. 125 if (user_manager::UserManager::IsInitialized() && 126 user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser()) { 127 // Don't allow revoking credentials for Chrome OS supervised users. 128 // See http://crbug.com/332032 129 LOG(ERROR) << "Attempt to revoke supervised user refresh " 130 << "token detected, ignoring."; 131 return false; 132 } 133 #else 134 // Don't allow revoking credentials for supervised users. 135 // See http://crbug.com/332032 136 if (profile_->IsSupervised()) { 137 LOG(ERROR) << "Attempt to revoke supervised user refresh " 138 << "token detected, ignoring."; 139 return false; 140 } 141 #endif 142 return true; 143 } 144 145 std::string ChromeSigninClient::GetSigninScopedDeviceId() { 146 if (CommandLine::ForCurrentProcess()->HasSwitch( 147 switches::kDisableSigninScopedDeviceId)) { 148 return std::string(); 149 } 150 151 std::string signin_scoped_device_id = 152 GetPrefs()->GetString(prefs::kGoogleServicesSigninScopedDeviceId); 153 if (signin_scoped_device_id.empty()) { 154 // If device_id doesn't exist then generate new and save in prefs. 155 signin_scoped_device_id = base::GenerateGUID(); 156 DCHECK(!signin_scoped_device_id.empty()); 157 GetPrefs()->SetString(prefs::kGoogleServicesSigninScopedDeviceId, 158 signin_scoped_device_id); 159 } 160 return signin_scoped_device_id; 161 } 162 163 void ChromeSigninClient::ClearSigninScopedDeviceId() { 164 GetPrefs()->ClearPref(prefs::kGoogleServicesSigninScopedDeviceId); 165 } 166 167 net::URLRequestContextGetter* ChromeSigninClient::GetURLRequestContext() { 168 return profile_->GetRequestContext(); 169 } 170 171 bool ChromeSigninClient::ShouldMergeSigninCredentialsIntoCookieJar() { 172 // If inline sign in is enabled, but account consistency is not, the user's 173 // credentials should be merge into the cookie jar. 174 return !switches::IsEnableWebBasedSignin() && 175 !switches::IsEnableAccountConsistency(); 176 } 177 178 std::string ChromeSigninClient::GetProductVersion() { 179 chrome::VersionInfo chrome_version; 180 if (!chrome_version.is_valid()) 181 return "invalid"; 182 return chrome_version.CreateVersionString(); 183 } 184 185 bool ChromeSigninClient::IsFirstRun() const { 186 #if defined(OS_ANDROID) 187 return false; 188 #else 189 return first_run::IsChromeFirstRun(); 190 #endif 191 } 192 193 base::Time ChromeSigninClient::GetInstallDate() { 194 return base::Time::FromTimeT( 195 g_browser_process->metrics_service()->GetInstallDate()); 196 } 197 198 scoped_ptr<SigninClient::CookieChangedCallbackList::Subscription> 199 ChromeSigninClient::AddCookieChangedCallback( 200 const CookieChangedCallback& callback) { 201 scoped_ptr<SigninClient::CookieChangedCallbackList::Subscription> 202 subscription = callbacks_.Add(callback); 203 RegisterForCookieChangedNotification(); 204 return subscription.Pass(); 205 } 206 207 void ChromeSigninClient::GoogleSigninSucceeded(const std::string& account_id, 208 const std::string& username, 209 const std::string& password) { 210 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS) 211 // Don't store password hash except for users of new profile management. 212 if (switches::IsNewProfileManagement()) 213 chrome::SetLocalAuthCredentials(profile_, password); 214 #endif 215 } 216 217 void ChromeSigninClient::Observe(int type, 218 const content::NotificationSource& source, 219 const content::NotificationDetails& details) { 220 switch (type) { 221 case chrome::NOTIFICATION_COOKIE_CHANGED: { 222 DCHECK(!callbacks_.empty()); 223 const net::CanonicalCookie* cookie = 224 content::Details<ChromeCookieDetails>(details).ptr()->cookie; 225 callbacks_.Notify(cookie); 226 break; 227 } 228 default: 229 NOTREACHED(); 230 break; 231 } 232 } 233 234 void ChromeSigninClient::RegisterForCookieChangedNotification() { 235 if (callbacks_.empty()) 236 return; 237 content::Source<Profile> source(profile_); 238 if (!registrar_.IsRegistered( 239 this, chrome::NOTIFICATION_COOKIE_CHANGED, source)) 240 registrar_.Add(this, chrome::NOTIFICATION_COOKIE_CHANGED, source); 241 } 242 243 void ChromeSigninClient::UnregisterForCookieChangedNotification() { 244 if (!callbacks_.empty()) 245 return; 246 // Note that it's allowed to call this method multiple times without an 247 // intervening call to |RegisterForCookieChangedNotification()|. 248 content::Source<Profile> source(profile_); 249 if (!registrar_.IsRegistered( 250 this, chrome::NOTIFICATION_COOKIE_CHANGED, source)) 251 return; 252 registrar_.Remove(this, chrome::NOTIFICATION_COOKIE_CHANGED, source); 253 } 254