chrome_signin_client.cc revision e5d81f57cb97b3b6b7fccc9c5610d21eb81db09d
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 "chrome/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/managed_mode/managed_user_constants.h"
22#endif
23
24#if defined(OS_CHROMEOS)
25#include "chrome/browser/chromeos/login/user_manager.h"
26#endif
27
28using content::ChildProcessHost;
29using content::RenderProcessHost;
30
31namespace {
32
33const char kGoogleAccountsUrl[] = "https://accounts.google.com";
34
35}  // namespace
36
37ChromeSigninClient::ChromeSigninClient(Profile* profile)
38    : profile_(profile), signin_host_id_(ChildProcessHost::kInvalidUniqueID) {}
39
40ChromeSigninClient::~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
51bool ChromeSigninClient::ProfileAllowsSigninCookies(Profile* profile) {
52  CookieSettings* cookie_settings =
53      CookieSettings::Factory::GetForProfile(profile).get();
54  return SettingsAllowSigninCookies(cookie_settings);
55}
56
57// static
58bool ChromeSigninClient::SettingsAllowSigninCookies(
59    CookieSettings* cookie_settings) {
60  return cookie_settings &&
61         cookie_settings->IsSettingCookieAllowed(GURL(kGoogleAccountsUrl),
62                                                 GURL(kGoogleAccountsUrl));
63}
64
65void 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
77void ChromeSigninClient::ClearSigninProcess() {
78  signin_host_id_ = ChildProcessHost::kInvalidUniqueID;
79}
80
81bool ChromeSigninClient::IsSigninProcess(int process_id) const {
82  return process_id == signin_host_id_;
83}
84
85bool ChromeSigninClient::HasSigninProcess() const {
86  return signin_host_id_ != ChildProcessHost::kInvalidUniqueID;
87}
88
89void 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
99PrefService* ChromeSigninClient::GetPrefs() { return profile_->GetPrefs(); }
100
101scoped_refptr<TokenWebData> ChromeSigninClient::GetDatabase() {
102  return WebDataServiceFactory::GetTokenWebDataForProfile(
103      profile_, Profile::EXPLICIT_ACCESS);
104}
105
106bool 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_->IsManaged()) {
121    LOG(ERROR) << "Attempt to revoke supervised user refresh "
122               << "token detected, ignoring.";
123    return false;
124  }
125#endif
126  return true;
127}
128
129net::URLRequestContextGetter* ChromeSigninClient::GetURLRequestContext() {
130  return profile_->GetRequestContext();
131}
132
133bool 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
140std::string ChromeSigninClient::GetProductVersion() {
141  chrome::VersionInfo chrome_version;
142  if (!chrome_version.is_valid())
143    return "invalid";
144  return chrome_version.CreateVersionString();
145}
146
147void 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
161void 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
170void 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
187void 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
194void 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