Home | History | Annotate | Download | only in signin
      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