1 // Copyright 2015 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.
5 #include "ios/chrome/browser/signin/signin_client_impl.h"
7 #include "base/command_line.h"
9 #include "base/logging.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "components/content_settings/core/browser/cookie_settings.h"
13 #include "components/keyed_service/core/service_access_type.h"
14 #include "components/metrics/metrics_service.h"
15 #include "components/signin/core/browser/profile_oauth2_token_service.h"
16 #include "components/signin/core/browser/signin_cookie_changed_subscription.h"
17 #include "components/signin/core/browser/signin_header_helper.h"
18 #include "components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h"
19 #include "google_apis/gaia/gaia_constants.h"
20 #include "google_apis/gaia/gaia_urls.h"
21 #include "ios/chrome/browser/application_context.h"
22 #include "ios/chrome/browser/content_settings/cookie_settings_factory.h"
23 #include "ios/chrome/browser/signin/gaia_auth_fetcher_ios.h"
24 #include "ios/chrome/browser/web_data_service_factory.h"
25 #include "ios/chrome/common/channel_info.h"
26 #include "ios/public/provider/chrome/browser/browser_state/browser_state_info_cache.h"
27 #include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h"
28 #include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state_manager.h"
29 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
30 #include "net/url_request/url_request_context_getter.h"
33 SigninClientImpl::SigninClientImpl(
34 ios::ChromeBrowserState
* browser_state
,
35 SigninErrorController
* signin_error_controller
)
36 : OAuth2TokenService::Consumer("signin_client_impl"),
37 browser_state_(browser_state
),
38 signin_error_controller_(signin_error_controller
) {
39 signin_error_controller_
->AddObserver(this);
40 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
43 SigninClientImpl::~SigninClientImpl() {
44 signin_error_controller_
->RemoveObserver(this);
47 void SigninClientImpl::Shutdown() {
48 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
51 void SigninClientImpl::DoFinalInit() {
55 bool SigninClientImpl::AllowsSigninCookies(
56 ios::ChromeBrowserState
* browser_state
) {
57 scoped_refptr
<content_settings::CookieSettings
> cookie_settings
=
58 ios::CookieSettingsFactory::GetForBrowserState(browser_state
);
59 return signin::SettingsAllowSigninCookies(cookie_settings
.get());
62 PrefService
* SigninClientImpl::GetPrefs() {
63 return browser_state_
->GetPrefs();
66 scoped_refptr
<TokenWebData
> SigninClientImpl::GetDatabase() {
67 return ios::WebDataServiceFactory::GetTokenWebDataForBrowserState(
68 browser_state_
, ServiceAccessType::EXPLICIT_ACCESS
);
71 bool SigninClientImpl::CanRevokeCredentials() {
75 std::string
SigninClientImpl::GetSigninScopedDeviceId() {
76 return GetOrCreateScopedDeviceIdPref(GetPrefs());
79 void SigninClientImpl::OnSignedOut() {
80 ios::BrowserStateInfoCache
* cache
= GetApplicationContext()
81 ->GetChromeBrowserStateManager()
82 ->GetBrowserStateInfoCache();
83 size_t index
= cache
->GetIndexOfBrowserStateWithPath(
84 browser_state_
->GetOriginalChromeBrowserState()->GetStatePath());
86 // If sign out occurs because Sync setup was in progress and the browser state
87 // got deleted, then it is no longer in the cache.
88 if (index
== std::string::npos
)
91 cache
->SetLocalAuthCredentialsOfBrowserStateAtIndex(index
, std::string());
92 cache
->SetAuthInfoOfBrowserStateAtIndex(index
, std::string(),
94 cache
->SetBrowserStateSigninRequiredAtIndex(index
, false);
97 net::URLRequestContextGetter
* SigninClientImpl::GetURLRequestContext() {
98 return browser_state_
->GetRequestContext();
101 bool SigninClientImpl::ShouldMergeSigninCredentialsIntoCookieJar() {
105 std::string
SigninClientImpl::GetProductVersion() {
106 return GetVersionString();
109 bool SigninClientImpl::IsFirstRun() const {
113 base::Time
SigninClientImpl::GetInstallDate() {
114 return base::Time::FromTimeT(
115 GetApplicationContext()->GetMetricsService()->GetInstallDate());
118 bool SigninClientImpl::AreSigninCookiesAllowed() {
119 return AllowsSigninCookies(browser_state_
);
122 void SigninClientImpl::AddContentSettingsObserver(
123 content_settings::Observer
* observer
) {
124 browser_state_
->GetHostContentSettingsMap()->AddObserver(observer
);
127 void SigninClientImpl::RemoveContentSettingsObserver(
128 content_settings::Observer
* observer
) {
129 browser_state_
->GetHostContentSettingsMap()->RemoveObserver(observer
);
132 scoped_ptr
<SigninClient::CookieChangedSubscription
>
133 SigninClientImpl::AddCookieChangedCallback(
135 const std::string
& name
,
136 const net::CookieStore::CookieChangedCallback
& callback
) {
137 scoped_refptr
<net::URLRequestContextGetter
> context_getter
=
138 browser_state_
->GetRequestContext();
139 DCHECK(context_getter
.get());
140 scoped_ptr
<SigninCookieChangedSubscription
> subscription(
141 new SigninCookieChangedSubscription(context_getter
, url
, name
, callback
));
142 return subscription
.Pass();
145 void SigninClientImpl::OnSignedIn(const std::string
& account_id
,
146 const std::string
& gaia_id
,
147 const std::string
& username
,
148 const std::string
& password
) {
149 ios::ChromeBrowserStateManager
* browser_state_manager
=
150 GetApplicationContext()->GetChromeBrowserStateManager();
151 ios::BrowserStateInfoCache
* cache
=
152 browser_state_manager
->GetBrowserStateInfoCache();
153 size_t index
= cache
->GetIndexOfBrowserStateWithPath(
154 browser_state_
->GetOriginalChromeBrowserState()->GetStatePath());
155 if (index
!= std::string::npos
) {
156 cache
->SetAuthInfoOfBrowserStateAtIndex(index
, gaia_id
,
157 base::UTF8ToUTF16(username
));
161 bool SigninClientImpl::UpdateAccountInfo(
162 AccountTrackerService::AccountInfo
* out_account_info
) {
163 DCHECK(!out_account_info
->account_id
.empty());
164 AccountInfo account_info
= ios::GetChromeBrowserProvider()
165 ->GetProfileOAuth2TokenServiceIOSProvider()
166 ->GetAccountInfo(out_account_info
->account_id
);
167 if (account_info
.gaia
.empty()) {
168 // There is no account information for this account, so there is nothing
169 // to be updated here.
173 bool updated
= false;
174 if (out_account_info
->gaia
.empty()) {
175 out_account_info
->gaia
= account_info
.gaia
;
177 } else if (out_account_info
->gaia
!= account_info
.gaia
) {
178 // The GAIA id of an account never changes. Avoid updating the wrong
179 // account if this occurs somehow.
180 NOTREACHED() << "out_account_info->gaia = '" << out_account_info
->gaia
181 << "' ; account_info.gaia = '" << account_info
.gaia
<< "'";
184 if (out_account_info
->email
!= account_info
.email
) {
185 out_account_info
->email
= account_info
.email
;
191 void SigninClientImpl::OnErrorChanged() {
192 ios::BrowserStateInfoCache
* cache
= GetApplicationContext()
193 ->GetChromeBrowserStateManager()
194 ->GetBrowserStateInfoCache();
195 size_t index
= cache
->GetIndexOfBrowserStateWithPath(
196 browser_state_
->GetOriginalChromeBrowserState()->GetStatePath());
197 if (index
== std::string::npos
)
200 cache
->SetBrowserStateIsAuthErrorAtIndex(
201 index
, signin_error_controller_
->HasError());
204 void SigninClientImpl::OnGetTokenInfoResponse(
205 scoped_ptr
<base::DictionaryValue
> token_info
) {
206 if (!token_info
->HasKey("error")) {
208 if (token_info
->GetString("token_handle", &handle
)) {
209 ios::BrowserStateInfoCache
* cache
= GetApplicationContext()
210 ->GetChromeBrowserStateManager()
211 ->GetBrowserStateInfoCache();
212 size_t index
= cache
->GetIndexOfBrowserStateWithPath(
213 browser_state_
->GetOriginalChromeBrowserState()->GetStatePath());
214 cache
->SetPasswordChangeDetectionTokenAtIndex(index
, handle
);
219 oauth_request_
.reset();
222 void SigninClientImpl::OnOAuthError() {
223 // Ignore the failure. It's not essential and we'll try again next time.
224 oauth_request_
.reset();
227 void SigninClientImpl::OnNetworkError(int response_code
) {
228 // Ignore the failure. It's not essential and we'll try again next time.
229 oauth_request_
.reset();
232 void SigninClientImpl::OnGetTokenSuccess(
233 const OAuth2TokenService::Request
* request
,
234 const std::string
& access_token
,
235 const base::Time
& expiration_time
) {
236 // Exchange the access token for a handle that can be used for later
237 // verification that the token is still valid (i.e. the password has not
239 if (!oauth_client_
) {
241 new gaia::GaiaOAuthClient(browser_state_
->GetRequestContext()));
243 oauth_client_
->GetTokenInfo(access_token
, 3 /* retries */, this);
246 void SigninClientImpl::OnGetTokenFailure(
247 const OAuth2TokenService::Request
* request
,
248 const GoogleServiceAuthError
& error
) {
249 // Ignore the failure. It's not essential and we'll try again next time.
250 oauth_request_
.reset();
253 void SigninClientImpl::OnNetworkChanged(
254 net::NetworkChangeNotifier::ConnectionType type
) {
255 if (type
>= net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE
)
258 for (const base::Closure
& callback
: delayed_callbacks_
)
261 delayed_callbacks_
.clear();
264 void SigninClientImpl::DelayNetworkCall(const base::Closure
& callback
) {
265 // Don't bother if we don't have any kind of network connection.
266 if (net::NetworkChangeNotifier::IsOffline()) {
267 delayed_callbacks_
.push_back(callback
);
273 GaiaAuthFetcher
* SigninClientImpl::CreateGaiaAuthFetcher(
274 GaiaAuthConsumer
* consumer
,
275 const std::string
& source
,
276 net::URLRequestContextGetter
* getter
) {
277 return new GaiaAuthFetcherIOS(consumer
, source
, getter
, browser_state_
);