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 "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 
     37 ChromeSigninClient::ChromeSigninClient(Profile* profile)
     38     : profile_(profile), signin_host_id_(ChildProcessHost::kInvalidUniqueID) {}
     39 
     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
     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
     58 bool ChromeSigninClient::SettingsAllowSigninCookies(
     59     CookieSettings* cookie_settings) {
     60   return cookie_settings &&
     61          cookie_settings->IsSettingCookieAllowed(GURL(kGoogleAccountsUrl),
     62                                                  GURL(kGoogleAccountsUrl));
     63 }
     64 
     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 
     77 void ChromeSigninClient::ClearSigninProcess() {
     78   signin_host_id_ = ChildProcessHost::kInvalidUniqueID;
     79 }
     80 
     81 bool ChromeSigninClient::IsSigninProcess(int process_id) const {
     82   return process_id == signin_host_id_;
     83 }
     84 
     85 bool ChromeSigninClient::HasSigninProcess() const {
     86   return signin_host_id_ != ChildProcessHost::kInvalidUniqueID;
     87 }
     88 
     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 
     99 PrefService* ChromeSigninClient::GetPrefs() { return profile_->GetPrefs(); }
    100 
    101 scoped_refptr<TokenWebData> ChromeSigninClient::GetDatabase() {
    102   return WebDataServiceFactory::GetTokenWebDataForProfile(
    103       profile_, Profile::EXPLICIT_ACCESS);
    104 }
    105 
    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 
    129 net::URLRequestContextGetter* ChromeSigninClient::GetURLRequestContext() {
    130   return profile_->GetRequestContext();
    131 }
    132 
    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 
    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 
    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 
    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 
    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 
    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 
    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