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