Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc

Issue 1143323005: Refactor AO2TS to make it easier to componentize. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: update for google_apis_unittests Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/signin/core/browser/mutable_profile_oauth2_token_service.h" 5 #include "chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.h"
6 6
7 #include "base/profiler/scoped_tracker.h" 7 #include "base/profiler/scoped_tracker.h"
8 #include "components/signin/core/browser/signin_client.h" 8 #include "components/signin/core/browser/signin_client.h"
9 #include "components/signin/core/browser/signin_metrics.h" 9 #include "components/signin/core/browser/signin_metrics.h"
10 #include "components/signin/core/browser/webdata/token_web_data.h" 10 #include "components/signin/core/browser/webdata/token_web_data.h"
11 #include "components/webdata/common/web_data_service_base.h" 11 #include "components/webdata/common/web_data_service_base.h"
12 #include "google_apis/gaia/gaia_auth_fetcher.h" 12 #include "google_apis/gaia/gaia_auth_fetcher.h"
13 #include "google_apis/gaia/gaia_auth_util.h" 13 #include "google_apis/gaia/gaia_auth_util.h"
14 #include "google_apis/gaia/gaia_constants.h" 14 #include "google_apis/gaia/gaia_constants.h"
15 #include "google_apis/gaia/oauth2_access_token_fetcher_immediate_error.h" 15 #include "google_apis/gaia/oauth2_access_token_fetcher_immediate_error.h"
(...skipping 19 matching lines...) Expand all
35 35
36 std::string RemoveAccountIdPrefix(const std::string& prefixed_account_id) { 36 std::string RemoveAccountIdPrefix(const std::string& prefixed_account_id) {
37 return prefixed_account_id.substr(kAccountIdPrefixLength); 37 return prefixed_account_id.substr(kAccountIdPrefixLength);
38 } 38 }
39 39
40 } // namespace 40 } // namespace
41 41
42 // This class sends a request to GAIA to revoke the given refresh token from 42 // This class sends a request to GAIA to revoke the given refresh token from
43 // the server. This is a best effort attempt only. This class deletes itself 43 // the server. This is a best effort attempt only. This class deletes itself
44 // when done sucessfully or otherwise. 44 // when done sucessfully or otherwise.
45 class MutableProfileOAuth2TokenService::RevokeServerRefreshToken 45 class MutableProfileOAuth2TokenServiceDelegate::RevokeServerRefreshToken
46 : public GaiaAuthConsumer { 46 : public GaiaAuthConsumer {
47 public: 47 public:
48 RevokeServerRefreshToken(MutableProfileOAuth2TokenService* token_service, 48 RevokeServerRefreshToken(
49 const std::string& account_id); 49 MutableProfileOAuth2TokenServiceDelegate* token_service_delegate,
50 const std::string& account_id);
50 ~RevokeServerRefreshToken() override; 51 ~RevokeServerRefreshToken() override;
51 52
52 private: 53 private:
53 // GaiaAuthConsumer overrides: 54 // GaiaAuthConsumer overrides:
54 void OnOAuth2RevokeTokenCompleted() override; 55 void OnOAuth2RevokeTokenCompleted() override;
55 56
56 MutableProfileOAuth2TokenService* token_service_; 57 MutableProfileOAuth2TokenServiceDelegate* token_service_delegate_;
57 GaiaAuthFetcher fetcher_; 58 GaiaAuthFetcher fetcher_;
58 59
59 DISALLOW_COPY_AND_ASSIGN(RevokeServerRefreshToken); 60 DISALLOW_COPY_AND_ASSIGN(RevokeServerRefreshToken);
60 }; 61 };
61 62
62 MutableProfileOAuth2TokenService:: 63 MutableProfileOAuth2TokenServiceDelegate::RevokeServerRefreshToken::
63 RevokeServerRefreshToken::RevokeServerRefreshToken( 64 RevokeServerRefreshToken(
64 MutableProfileOAuth2TokenService* token_service, 65 MutableProfileOAuth2TokenServiceDelegate* token_service_delegate,
65 const std::string& refresh_token) 66 const std::string& refresh_token)
66 : token_service_(token_service), 67 : token_service_delegate_(token_service_delegate),
67 fetcher_(this, GaiaConstants::kChromeSource, 68 fetcher_(this,
68 token_service_->GetRequestContext()) { 69 GaiaConstants::kChromeSource,
70 token_service_delegate_->GetRequestContext()) {
69 fetcher_.StartRevokeOAuth2Token(refresh_token); 71 fetcher_.StartRevokeOAuth2Token(refresh_token);
70 } 72 }
71 73
72 MutableProfileOAuth2TokenService:: 74 MutableProfileOAuth2TokenServiceDelegate::RevokeServerRefreshToken::
73 RevokeServerRefreshToken::~RevokeServerRefreshToken() {} 75 ~RevokeServerRefreshToken() {
76 }
74 77
75 void MutableProfileOAuth2TokenService:: 78 void MutableProfileOAuth2TokenServiceDelegate::RevokeServerRefreshToken::
76 RevokeServerRefreshToken::OnOAuth2RevokeTokenCompleted() { 79 OnOAuth2RevokeTokenCompleted() {
77 // |this| pointer will be deleted when removed from the vector, so don't 80 // |this| pointer will be deleted when removed from the vector, so don't
78 // access any members after call to erase(). 81 // access any members after call to erase().
79 token_service_->server_revokes_.erase( 82 token_service_delegate_->server_revokes_.erase(
80 std::find(token_service_->server_revokes_.begin(), 83 std::find(token_service_delegate_->server_revokes_.begin(),
81 token_service_->server_revokes_.end(), 84 token_service_delegate_->server_revokes_.end(), this));
82 this));
83 } 85 }
84 86
85 MutableProfileOAuth2TokenService::AccountInfo::AccountInfo( 87 MutableProfileOAuth2TokenServiceDelegate::AccountInfo::AccountInfo(
86 SigninErrorController* signin_error_controller, 88 SigninErrorController* signin_error_controller,
87 const std::string& account_id, 89 const std::string& account_id,
88 const std::string& refresh_token) 90 const std::string& refresh_token)
89 : signin_error_controller_(signin_error_controller), 91 : signin_error_controller_(signin_error_controller),
90 account_id_(account_id), 92 account_id_(account_id),
91 refresh_token_(refresh_token), 93 refresh_token_(refresh_token),
92 last_auth_error_(GoogleServiceAuthError::NONE) { 94 last_auth_error_(GoogleServiceAuthError::NONE) {
93 DCHECK(signin_error_controller_); 95 DCHECK(signin_error_controller_);
94 DCHECK(!account_id_.empty()); 96 DCHECK(!account_id_.empty());
95 signin_error_controller_->AddProvider(this); 97 signin_error_controller_->AddProvider(this);
96 } 98 }
97 99
98 MutableProfileOAuth2TokenService::AccountInfo::~AccountInfo() { 100 MutableProfileOAuth2TokenServiceDelegate::AccountInfo::~AccountInfo() {
99 signin_error_controller_->RemoveProvider(this); 101 signin_error_controller_->RemoveProvider(this);
100 } 102 }
101 103
102 void MutableProfileOAuth2TokenService::AccountInfo::SetLastAuthError( 104 void MutableProfileOAuth2TokenServiceDelegate::AccountInfo::SetLastAuthError(
103 const GoogleServiceAuthError& error) { 105 const GoogleServiceAuthError& error) {
104 if (error.state() != last_auth_error_.state()) { 106 if (error.state() != last_auth_error_.state()) {
105 last_auth_error_ = error; 107 last_auth_error_ = error;
106 signin_error_controller_->AuthStatusChanged(); 108 signin_error_controller_->AuthStatusChanged();
107 } 109 }
108 } 110 }
109 111
110 std::string 112 std::string
111 MutableProfileOAuth2TokenService::AccountInfo::GetAccountId() const { 113 MutableProfileOAuth2TokenServiceDelegate::AccountInfo::GetAccountId() const {
112 return account_id_; 114 return account_id_;
113 } 115 }
114 116
115 GoogleServiceAuthError 117 GoogleServiceAuthError
116 MutableProfileOAuth2TokenService::AccountInfo::GetAuthStatus() const { 118 MutableProfileOAuth2TokenServiceDelegate::AccountInfo::GetAuthStatus() const {
117 return last_auth_error_; 119 return last_auth_error_;
118 } 120 }
119 121
120 MutableProfileOAuth2TokenService::MutableProfileOAuth2TokenService() 122 MutableProfileOAuth2TokenServiceDelegate::
123 MutableProfileOAuth2TokenServiceDelegate(
124 SigninClient* client,
125 SigninErrorController* signin_error_controller)
121 : web_data_service_request_(0), 126 : web_data_service_request_(0),
122 backoff_entry_(&backoff_policy_), 127 backoff_entry_(&backoff_policy_),
123 backoff_error_(GoogleServiceAuthError::NONE) { 128 backoff_error_(GoogleServiceAuthError::NONE) {
124 VLOG(1) << "MutablePO2TS::MutablePO2TS"; 129 VLOG(1) << "MutablePO2TS::MutablePO2TS";
130 DCHECK(client);
131 DCHECK(signin_error_controller);
132 client_ = client;
133 signin_error_controller_ = signin_error_controller;
Roger Tawa OOO till Jul 10th 2015/05/28 14:54:43 Move lines 132 and 133 to the initializer list at
gogerald1 2015/06/03 18:12:58 Done.
125 // It's okay to fill the backoff policy after being used in construction. 134 // It's okay to fill the backoff policy after being used in construction.
126 backoff_policy_.num_errors_to_ignore = 0; 135 backoff_policy_.num_errors_to_ignore = 0;
127 backoff_policy_.initial_delay_ms = 1000; 136 backoff_policy_.initial_delay_ms = 1000;
128 backoff_policy_.multiply_factor = 2.0; 137 backoff_policy_.multiply_factor = 2.0;
129 backoff_policy_.jitter_factor = 0.2; 138 backoff_policy_.jitter_factor = 0.2;
130 backoff_policy_.maximum_backoff_ms = 15 * 60 * 1000; 139 backoff_policy_.maximum_backoff_ms = 15 * 60 * 1000;
131 backoff_policy_.entry_lifetime_ms = -1; 140 backoff_policy_.entry_lifetime_ms = -1;
132 backoff_policy_.always_use_initial_delay = false; 141 backoff_policy_.always_use_initial_delay = false;
133 } 142 }
134 143
135 MutableProfileOAuth2TokenService::~MutableProfileOAuth2TokenService() { 144 MutableProfileOAuth2TokenServiceDelegate::
145 ~MutableProfileOAuth2TokenServiceDelegate() {
136 VLOG(1) << "MutablePO2TS::~MutablePO2TS"; 146 VLOG(1) << "MutablePO2TS::~MutablePO2TS";
137 DCHECK(server_revokes_.empty()); 147 DCHECK(server_revokes_.empty());
138 } 148 }
139 149
140 void MutableProfileOAuth2TokenService::Shutdown() {
141 VLOG(1) << "MutablePO2TS::Shutdown";
142 server_revokes_.clear();
143 CancelWebTokenFetch();
144 CancelAllRequests();
145 refresh_tokens_.clear();
146
147 ProfileOAuth2TokenService::Shutdown();
148 }
149
150 bool MutableProfileOAuth2TokenService::RefreshTokenIsAvailable(
151 const std::string& account_id) const {
152 return !GetRefreshToken(account_id).empty();
153 }
154
155 std::string MutableProfileOAuth2TokenService::GetRefreshToken(
156 const std::string& account_id) const {
157 AccountInfoMap::const_iterator iter = refresh_tokens_.find(account_id);
158 if (iter != refresh_tokens_.end())
159 return iter->second->refresh_token();
160 return std::string();
161 }
162
163 bool MutableProfileOAuth2TokenService::HasPersistentError(
164 const std::string& account_id) {
165 return refresh_tokens_[account_id]->GetAuthStatus().IsPersistentError();
166 }
167
168 OAuth2AccessTokenFetcher* 150 OAuth2AccessTokenFetcher*
169 MutableProfileOAuth2TokenService::CreateAccessTokenFetcher( 151 MutableProfileOAuth2TokenServiceDelegate::CreateAccessTokenFetcher(
170 const std::string& account_id, 152 const std::string& account_id,
171 net::URLRequestContextGetter* getter, 153 net::URLRequestContextGetter* getter,
172 OAuth2AccessTokenConsumer* consumer) { 154 OAuth2AccessTokenConsumer* consumer) {
173 ValidateAccountId(account_id); 155 ValidateAccountId(account_id);
174 if (HasPersistentError(account_id)) { 156 if (refresh_tokens_[account_id]->GetAuthStatus().IsPersistentError()) {
Roger Tawa OOO till Jul 10th 2015/05/28 14:54:43 Better to leave the call to HasPersistentError().
gogerald1 2015/06/03 18:12:58 The reason I am thinking to keep this function is
Roger Tawa OOO till Jul 10th 2015/06/04 18:19:55 Acknowledged.
175 VLOG(1) << "Request for token has been rejected due to persistent error #" 157 VLOG(1) << "Request for token has been rejected due to persistent error #"
176 << refresh_tokens_[account_id]->GetAuthStatus().state(); 158 << refresh_tokens_[account_id]->GetAuthStatus().state();
177 return new OAuth2AccessTokenFetcherImmediateError( 159 return new OAuth2AccessTokenFetcherImmediateError(
178 consumer, refresh_tokens_[account_id]->GetAuthStatus()); 160 consumer, refresh_tokens_[account_id]->GetAuthStatus());
179 } 161 }
180 if (backoff_entry_.ShouldRejectRequest()) { 162 if (backoff_entry_.ShouldRejectRequest()) {
181 VLOG(1) << "Request for token has been rejected due to backoff rules from" 163 VLOG(1) << "Request for token has been rejected due to backoff rules from"
182 << " previous error #" << backoff_error_.state(); 164 << " previous error #" << backoff_error_.state();
183 return new OAuth2AccessTokenFetcherImmediateError(consumer, backoff_error_); 165 return new OAuth2AccessTokenFetcherImmediateError(consumer, backoff_error_);
184 } 166 }
185 std::string refresh_token = GetRefreshToken(account_id); 167 std::string refresh_token = GetRefreshToken(account_id);
186 DCHECK(!refresh_token.empty()); 168 DCHECK(!refresh_token.empty());
187 return new OAuth2AccessTokenFetcherImpl(consumer, getter, refresh_token); 169 return new OAuth2AccessTokenFetcherImpl(consumer, getter, refresh_token);
188 } 170 }
189 171
190 net::URLRequestContextGetter* 172 void MutableProfileOAuth2TokenServiceDelegate::UpdateAuthError(
191 MutableProfileOAuth2TokenService::GetRequestContext() { 173 const std::string& account_id,
192 return client()->GetURLRequestContext(); 174 const GoogleServiceAuthError& error) {
175 VLOG(1) << "MutablePO2TS::UpdateAuthError. Error: " << error.state();
176 backoff_entry_.InformOfRequest(!error.IsTransientError());
177 ValidateAccountId(account_id);
178
179 // Do not report connection errors as these are not actually auth errors.
180 // We also want to avoid masking a "real" auth error just because we
181 // subsequently get a transient network error. We do keep it around though
182 // to report for future requests being denied for "backoff" reasons.
183 if (error.IsTransientError()) {
184 backoff_error_ = error;
185 return;
186 }
187
188 if (refresh_tokens_.count(account_id) == 0) {
189 // This could happen if the preferences have been corrupted (see
190 // http://crbug.com/321370). In a Debug build that would be a bug, but in a
191 // Release build we want to deal with it gracefully.
192 NOTREACHED();
193 return;
194 }
195 refresh_tokens_[account_id]->SetLastAuthError(error);
193 } 196 }
194 197
195 void MutableProfileOAuth2TokenService::LoadCredentials( 198 bool MutableProfileOAuth2TokenServiceDelegate::RefreshTokenIsAvailable(
199 const std::string& account_id) const {
200 VLOG(1) << "MutablePO2TS::RefreshTokenIsAvailable";
201 return !GetRefreshToken(account_id).empty();
202 }
203
204 std::string MutableProfileOAuth2TokenServiceDelegate::GetRefreshToken(
205 const std::string& account_id) const {
206 AccountInfoMap::const_iterator iter = refresh_tokens_.find(account_id);
207 if (iter != refresh_tokens_.end())
208 return iter->second->refresh_token();
209 return std::string();
210 }
211
212 std::vector<std::string>
213 MutableProfileOAuth2TokenServiceDelegate::GetAccounts() {
214 std::vector<std::string> account_ids;
215 for (AccountInfoMap::const_iterator iter = refresh_tokens_.begin();
216 iter != refresh_tokens_.end(); ++iter) {
217 account_ids.push_back(iter->first);
218 }
219 return account_ids;
220 }
221
222 net::URLRequestContextGetter*
223 MutableProfileOAuth2TokenServiceDelegate::GetRequestContext() const {
224 return client_->GetURLRequestContext();
225 }
226
227 void MutableProfileOAuth2TokenServiceDelegate::LoadCredentials(
196 const std::string& primary_account_id) { 228 const std::string& primary_account_id) {
197 DCHECK(!primary_account_id.empty()); 229 DCHECK(!primary_account_id.empty());
198 ValidateAccountId(primary_account_id); 230 ValidateAccountId(primary_account_id);
199 DCHECK(loading_primary_account_id_.empty()); 231 DCHECK(loading_primary_account_id_.empty());
200 DCHECK_EQ(0, web_data_service_request_); 232 DCHECK_EQ(0, web_data_service_request_);
201 233
202 CancelAllRequests(); 234 refresh_tokens_.clear();
203 refresh_tokens().clear();
204 235
205 // If the account_id is an email address, then canonicalize it. This 236 // If the account_id is an email address, then canonicalize it. This
206 // is to support legacy account_ids, and will not be needed after 237 // is to support legacy account_ids, and will not be needed after
207 // switching to gaia-ids. 238 // switching to gaia-ids.
208 if (primary_account_id.find('@') != std::string::npos) { 239 if (primary_account_id.find('@') != std::string::npos) {
209 loading_primary_account_id_ = gaia::CanonicalizeEmail(primary_account_id); 240 loading_primary_account_id_ = gaia::CanonicalizeEmail(primary_account_id);
210 } else { 241 } else {
211 loading_primary_account_id_ = primary_account_id; 242 loading_primary_account_id_ = primary_account_id;
212 } 243 }
213 244
214 scoped_refptr<TokenWebData> token_web_data = client()->GetDatabase(); 245 scoped_refptr<TokenWebData> token_web_data = client_->GetDatabase();
215 if (token_web_data.get()) 246 if (token_web_data.get())
216 web_data_service_request_ = token_web_data->GetAllTokens(this); 247 web_data_service_request_ = token_web_data->GetAllTokens(this);
217 } 248 }
218 249
219 void MutableProfileOAuth2TokenService::OnWebDataServiceRequestDone( 250 void MutableProfileOAuth2TokenServiceDelegate::OnWebDataServiceRequestDone(
220 WebDataServiceBase::Handle handle, 251 WebDataServiceBase::Handle handle,
221 const WDTypedResult* result) { 252 const WDTypedResult* result) {
222 VLOG(1) << "MutablePO2TS::OnWebDataServiceRequestDone. Result type: " 253 VLOG(1) << "MutablePO2TS::OnWebDataServiceRequestDone. Result type: "
223 << (result == nullptr ? -1 : (int)result->GetType()); 254 << (result == nullptr ? -1 : (int)result->GetType());
224 255
225 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is 256 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
226 // fixed. 257 // fixed.
227 tracked_objects::ScopedTracker tracking_profile( 258 tracked_objects::ScopedTracker tracking_profile(
228 FROM_HERE_WITH_EXPLICIT_FUNCTION( 259 FROM_HERE_WITH_EXPLICIT_FUNCTION(
229 "422460 MutableProfileOAuth2Token...::OnWebDataServiceRequestDone")); 260 "422460 MutableProfileOAuth2Token...::OnWebDataServiceRequestDone"));
230 261
231 DCHECK_EQ(web_data_service_request_, handle); 262 DCHECK_EQ(web_data_service_request_, handle);
232 web_data_service_request_ = 0; 263 web_data_service_request_ = 0;
233 264
234 if (result) { 265 if (result) {
235 DCHECK(result->GetType() == TOKEN_RESULT); 266 DCHECK(result->GetType() == TOKEN_RESULT);
236 const WDResult<std::map<std::string, std::string> > * token_result = 267 const WDResult<std::map<std::string, std::string>>* token_result =
237 static_cast<const WDResult<std::map<std::string, std::string> > * > ( 268 static_cast<const WDResult<std::map<std::string, std::string>>*>(
238 result); 269 result);
239 LoadAllCredentialsIntoMemory(token_result->GetValue()); 270 LoadAllCredentialsIntoMemory(token_result->GetValue());
240 } 271 }
241 272
242 // Make sure that we have an entry for |loading_primary_account_id_| in the 273 // Make sure that we have an entry for |loading_primary_account_id_| in the
243 // map. The entry could be missing if there is a corruption in the token DB 274 // map. The entry could be missing if there is a corruption in the token DB
244 // while this profile is connected to an account. 275 // while this profile is connected to an account.
245 DCHECK(!loading_primary_account_id_.empty()); 276 DCHECK(!loading_primary_account_id_.empty());
246 if (refresh_tokens().count(loading_primary_account_id_) == 0) { 277 if (refresh_tokens_.count(loading_primary_account_id_) == 0) {
247 refresh_tokens()[loading_primary_account_id_].reset( 278 refresh_tokens_[loading_primary_account_id_].reset(new AccountInfo(
248 new AccountInfo(signin_error_controller(), 279 signin_error_controller_, loading_primary_account_id_, std::string()));
249 loading_primary_account_id_,
250 std::string()));
251 } 280 }
252 281
253 // If we don't have a refresh token for a known account, signal an error. 282 // If we don't have a refresh token for a known account, signal an error.
254 for (AccountInfoMap::const_iterator i = refresh_tokens_.begin(); 283 for (AccountInfoMap::const_iterator i = refresh_tokens_.begin();
255 i != refresh_tokens_.end(); ++i) { 284 i != refresh_tokens_.end(); ++i) {
256 if (!RefreshTokenIsAvailable(i->first)) { 285 if (RefreshTokenIsAvailable(i->first)) {
257 UpdateAuthError( 286 UpdateAuthError(i->first,
258 i->first, 287 GoogleServiceAuthError(
259 GoogleServiceAuthError( 288 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
260 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
261 break; 289 break;
262 } 290 }
263 } 291 }
264 292
265 loading_primary_account_id_.clear(); 293 loading_primary_account_id_.clear();
266 } 294 }
267 295
268 void MutableProfileOAuth2TokenService::LoadAllCredentialsIntoMemory( 296 void MutableProfileOAuth2TokenServiceDelegate::LoadAllCredentialsIntoMemory(
269 const std::map<std::string, std::string>& db_tokens) { 297 const std::map<std::string, std::string>& db_tokens) {
270 std::string old_login_token; 298 std::string old_login_token;
271 299
272 { 300 {
273 ScopedBatchChange batch(this); 301 ScopedBatchChange batch(this);
274 302
275 VLOG(1) << "MutablePO2TS::LoadAllCredentialsIntoMemory; " 303 VLOG(1) << "MutablePO2TS::LoadAllCredentialsIntoMemory; "
276 << db_tokens.size() << " Credential(s)."; 304 << db_tokens.size() << " Credential(s).";
277 for (std::map<std::string, std::string>::const_iterator iter = 305 for (std::map<std::string, std::string>::const_iterator iter =
278 db_tokens.begin(); 306 db_tokens.begin();
279 iter != db_tokens.end(); 307 iter != db_tokens.end(); ++iter) {
280 ++iter) {
281 std::string prefixed_account_id = iter->first; 308 std::string prefixed_account_id = iter->first;
282 std::string refresh_token = iter->second; 309 std::string refresh_token = iter->second;
283 310
284 if (IsLegacyRefreshTokenId(prefixed_account_id) && !refresh_token.empty()) 311 if (IsLegacyRefreshTokenId(prefixed_account_id) && !refresh_token.empty())
285 old_login_token = refresh_token; 312 old_login_token = refresh_token;
286 313
287 if (IsLegacyServiceId(prefixed_account_id)) { 314 if (IsLegacyServiceId(prefixed_account_id)) {
288 scoped_refptr<TokenWebData> token_web_data = client()->GetDatabase(); 315 scoped_refptr<TokenWebData> token_web_data = client_->GetDatabase();
289 if (token_web_data.get()) 316 if (token_web_data.get())
290 token_web_data->RemoveTokenForService(prefixed_account_id); 317 token_web_data->RemoveTokenForService(prefixed_account_id);
291 } else { 318 } else {
292 DCHECK(!refresh_token.empty()); 319 DCHECK(!refresh_token.empty());
293 std::string account_id = RemoveAccountIdPrefix(prefixed_account_id); 320 std::string account_id = RemoveAccountIdPrefix(prefixed_account_id);
294 321
295 // If the account_id is an email address, then canonicalize it. This 322 // If the account_id is an email address, then canonicalize it. This
296 // is to support legacy account_ids, and will not be needed after 323 // is to support legacy account_ids, and will not be needed after
297 // switching to gaia-ids. 324 // switching to gaia-ids.
298 if (account_id.find('@') != std::string::npos) 325 if (account_id.find('@') != std::string::npos)
299 account_id = gaia::CanonicalizeEmail(account_id); 326 account_id = gaia::CanonicalizeEmail(account_id);
300 327
301 refresh_tokens()[account_id].reset( 328 refresh_tokens_[account_id].reset(new AccountInfo(
302 new AccountInfo(signin_error_controller(), 329 signin_error_controller_, account_id, refresh_token));
303 account_id,
304 refresh_token));
305 FireRefreshTokenAvailable(account_id); 330 FireRefreshTokenAvailable(account_id);
306 } 331 }
307 } 332 }
308 333
309 if (!old_login_token.empty()) { 334 if (!old_login_token.empty()) {
310 DCHECK(!loading_primary_account_id_.empty()); 335 DCHECK(!loading_primary_account_id_.empty());
311 if (refresh_tokens().count(loading_primary_account_id_) == 0) 336 if (refresh_tokens_.count(loading_primary_account_id_) == 0)
312 UpdateCredentials(loading_primary_account_id_, old_login_token); 337 UpdateCredentials(loading_primary_account_id_, old_login_token);
313 } 338 }
314 } 339 }
315 340
316 FireRefreshTokensLoaded(); 341 FireRefreshTokensLoaded();
317 } 342 }
318 343
319 void MutableProfileOAuth2TokenService::UpdateAuthError( 344 void MutableProfileOAuth2TokenServiceDelegate::UpdateCredentials(
320 const std::string& account_id,
321 const GoogleServiceAuthError& error) {
322 VLOG(1) << "MutablePO2TS::UpdateAuthError. Error: " << error.state();
323 backoff_entry_.InformOfRequest(!error.IsTransientError());
324 ValidateAccountId(account_id);
325
326 // Do not report connection errors as these are not actually auth errors.
327 // We also want to avoid masking a "real" auth error just because we
328 // subsequently get a transient network error. We do keep it around though
329 // to report for future requests being denied for "backoff" reasons.
330 if (error.IsTransientError()) {
331 backoff_error_ = error;
332 return;
333 }
334
335 if (refresh_tokens_.count(account_id) == 0) {
336 // This could happen if the preferences have been corrupted (see
337 // http://crbug.com/321370). In a Debug build that would be a bug, but in a
338 // Release build we want to deal with it gracefully.
339 NOTREACHED();
340 return;
341 }
342 refresh_tokens_[account_id]->SetLastAuthError(error);
343 }
344
345 std::vector<std::string> MutableProfileOAuth2TokenService::GetAccounts() {
346 std::vector<std::string> account_ids;
347 for (AccountInfoMap::const_iterator iter = refresh_tokens_.begin();
348 iter != refresh_tokens_.end(); ++iter) {
349 account_ids.push_back(iter->first);
350 }
351 return account_ids;
352 }
353
354 void MutableProfileOAuth2TokenService::UpdateCredentials(
355 const std::string& account_id, 345 const std::string& account_id,
356 const std::string& refresh_token) { 346 const std::string& refresh_token) {
357 DCHECK(thread_checker_.CalledOnValidThread()); 347 DCHECK(thread_checker_.CalledOnValidThread());
358 DCHECK(!account_id.empty()); 348 DCHECK(!account_id.empty());
359 DCHECK(!refresh_token.empty()); 349 DCHECK(!refresh_token.empty());
360 ValidateAccountId(account_id); 350 ValidateAccountId(account_id);
361 351
362 signin_metrics::LogSigninAddAccount(); 352 signin_metrics::LogSigninAddAccount();
363 353
364 bool refresh_token_present = refresh_tokens_.count(account_id) > 0; 354 bool refresh_token_present = refresh_tokens_.count(account_id) > 0;
365 if (!refresh_token_present || 355 if (!refresh_token_present ||
366 refresh_tokens_[account_id]->refresh_token() != refresh_token) { 356 refresh_tokens_[account_id]->refresh_token() != refresh_token) {
367 ScopedBatchChange batch(this); 357 ScopedBatchChange batch(this);
368 358
369 // If token present, and different from the new one, cancel its requests, 359 // If token present, and different from the new one, cancel its requests,
370 // and clear the entries in cache related to that account. 360 // and clear the entries in cache related to that account.
371 if (refresh_token_present) { 361 if (refresh_token_present) {
372 VLOG(1) << "MutablePO2TS::UpdateCredentials; Refresh Token was present. " 362 VLOG(1) << "MutablePO2TS::UpdateCredentials; Refresh Token was present. "
373 << "account_id=" << account_id; 363 << "account_id=" << account_id;
374 std::string revoke_reason = refresh_token_present ? "token differs" : 364 std::string revoke_reason =
375 "token is missing"; 365 refresh_token_present ? "token differs" : "token is missing";
376 LOG(WARNING) << "Revoking refresh token on server. " 366 LOG(WARNING) << "Revoking refresh token on server. "
377 << "Reason: token update, " << revoke_reason; 367 << "Reason: token update, " << revoke_reason;
378 RevokeCredentialsOnServer(refresh_tokens_[account_id]->refresh_token()); 368 RevokeCredentialsOnServer(refresh_tokens_[account_id]->refresh_token());
379 CancelRequestsForAccount(account_id);
380 ClearCacheForAccount(account_id);
381 refresh_tokens_[account_id]->set_refresh_token(refresh_token); 369 refresh_tokens_[account_id]->set_refresh_token(refresh_token);
382 } else { 370 } else {
383 VLOG(1) << "MutablePO2TS::UpdateCredentials; Refresh Token was absent. " 371 VLOG(1) << "MutablePO2TS::UpdateCredentials; Refresh Token was absent. "
384 << "account_id=" << account_id; 372 << "account_id=" << account_id;
385 refresh_tokens_[account_id].reset( 373 refresh_tokens_[account_id].reset(
386 new AccountInfo(signin_error_controller(), 374 new AccountInfo(signin_error_controller_, account_id, refresh_token));
387 account_id,
388 refresh_token));
389 } 375 }
390 376
391 // Save the token in memory and in persistent store. 377 // Save the token in memory and in persistent store.
392 PersistCredentials(account_id, refresh_token); 378 PersistCredentials(account_id, refresh_token);
393 379
394 UpdateAuthError(account_id, GoogleServiceAuthError::AuthErrorNone()); 380 UpdateAuthError(account_id, GoogleServiceAuthError::AuthErrorNone());
395 FireRefreshTokenAvailable(account_id); 381 FireRefreshTokenAvailable(account_id);
396 } 382 }
397 } 383 }
398 384
399 void MutableProfileOAuth2TokenService::RevokeCredentials( 385 void MutableProfileOAuth2TokenServiceDelegate::PersistCredentials(
400 const std::string& account_id) {
401 ValidateAccountId(account_id);
402 DCHECK(thread_checker_.CalledOnValidThread());
403
404 if (refresh_tokens_.count(account_id) > 0) {
405 VLOG(1) << "MutablePO2TS::RevokeCredentials for account_id=" << account_id;
406 ScopedBatchChange batch(this);
407 RevokeCredentialsOnServer(refresh_tokens_[account_id]->refresh_token());
408 CancelRequestsForAccount(account_id);
409 ClearCacheForAccount(account_id);
410 refresh_tokens_.erase(account_id);
411 ClearPersistedCredentials(account_id);
412 FireRefreshTokenRevoked(account_id);
413 }
414 }
415
416 void MutableProfileOAuth2TokenService::PersistCredentials(
417 const std::string& account_id, 386 const std::string& account_id,
418 const std::string& refresh_token) { 387 const std::string& refresh_token) {
419 scoped_refptr<TokenWebData> token_web_data = client()->GetDatabase(); 388 scoped_refptr<TokenWebData> token_web_data = client_->GetDatabase();
420 if (token_web_data.get()) { 389 if (token_web_data.get()) {
421 VLOG(1) << "MutablePO2TS::PersistCredentials for account_id=" << account_id; 390 VLOG(1) << "MutablePO2TS::PersistCredentials for account_id=" << account_id;
422 token_web_data->SetTokenForService(ApplyAccountIdPrefix(account_id), 391 token_web_data->SetTokenForService(ApplyAccountIdPrefix(account_id),
423 refresh_token); 392 refresh_token);
424 } 393 }
425 } 394 }
426 395
427 void MutableProfileOAuth2TokenService::ClearPersistedCredentials( 396 void MutableProfileOAuth2TokenServiceDelegate::RevokeAllCredentials() {
428 const std::string& account_id) { 397 if (!client_->CanRevokeCredentials())
429 scoped_refptr<TokenWebData> token_web_data = client()->GetDatabase();
430 if (token_web_data.get()) {
431 VLOG(1) << "MutablePO2TS::ClearPersistedCredentials for account_id="
432 << account_id;
433 token_web_data->RemoveTokenForService(ApplyAccountIdPrefix(account_id));
434 }
435 }
436
437 void MutableProfileOAuth2TokenService::RevokeAllCredentials() {
438 if (!client()->CanRevokeCredentials())
439 return; 398 return;
440 DCHECK(thread_checker_.CalledOnValidThread()); 399 DCHECK(thread_checker_.CalledOnValidThread());
441 400
442 ScopedBatchChange batch(this); 401 ScopedBatchChange batch(this);
443 402
444 VLOG(1) << "MutablePO2TS::RevokeAllCredentials"; 403 VLOG(1) << "MutablePO2TS::RevokeAllCredentials";
445 CancelWebTokenFetch(); 404 CancelWebTokenFetch();
446 CancelAllRequests();
447 ClearCache();
448 AccountInfoMap tokens = refresh_tokens_; 405 AccountInfoMap tokens = refresh_tokens_;
449 for (AccountInfoMap::iterator i = tokens.begin(); i != tokens.end(); ++i) 406 for (AccountInfoMap::iterator i = tokens.begin(); i != tokens.end(); ++i)
450 RevokeCredentials(i->first); 407 RevokeCredentials(i->first);
451 408
452 DCHECK_EQ(0u, refresh_tokens_.size()); 409 DCHECK_EQ(0u, refresh_tokens_.size());
453 } 410 }
454 411
455 void MutableProfileOAuth2TokenService::RevokeCredentialsOnServer( 412 void MutableProfileOAuth2TokenServiceDelegate::RevokeCredentials(
413 const std::string& account_id) {
414 ValidateAccountId(account_id);
415 DCHECK(thread_checker_.CalledOnValidThread());
416
417 if (refresh_tokens_.count(account_id) > 0) {
418 VLOG(1) << "MutablePO2TS::RevokeCredentials for account_id=" << account_id;
419 ScopedBatchChange batch(this);
420 RevokeCredentialsOnServer(refresh_tokens_[account_id]->refresh_token());
421 refresh_tokens_.erase(account_id);
422 ClearPersistedCredentials(account_id);
423 FireRefreshTokenRevoked(account_id);
424 }
425 }
426
427 void MutableProfileOAuth2TokenServiceDelegate::ClearPersistedCredentials(
428 const std::string& account_id) {
429 scoped_refptr<TokenWebData> token_web_data = client_->GetDatabase();
430 if (token_web_data.get()) {
431 VLOG(1) << "MutablePO2TS::ClearPersistedCredentials for account_id="
432 << account_id;
433 token_web_data->RemoveTokenForService(ApplyAccountIdPrefix(account_id));
434 }
435 }
436
437 void MutableProfileOAuth2TokenServiceDelegate::RevokeCredentialsOnServer(
456 const std::string& refresh_token) { 438 const std::string& refresh_token) {
457 // Keep track or all server revoke requests. This way they can be deleted 439 // Keep track or all server revoke requests. This way they can be deleted
458 // before the token service is shutdown and won't outlive the profile. 440 // before the token service is shutdown and won't outlive the profile.
459 server_revokes_.push_back( 441 server_revokes_.push_back(new RevokeServerRefreshToken(this, refresh_token));
460 new RevokeServerRefreshToken(this, refresh_token));
461 } 442 }
462 443
463 void MutableProfileOAuth2TokenService::CancelWebTokenFetch() { 444 void MutableProfileOAuth2TokenServiceDelegate::CancelWebTokenFetch() {
464 if (web_data_service_request_ != 0) { 445 if (web_data_service_request_ != 0) {
465 scoped_refptr<TokenWebData> token_web_data = client()->GetDatabase(); 446 scoped_refptr<TokenWebData> token_web_data = client_->GetDatabase();
466 DCHECK(token_web_data.get()); 447 DCHECK(token_web_data.get());
467 token_web_data->CancelRequest(web_data_service_request_); 448 token_web_data->CancelRequest(web_data_service_request_);
468 web_data_service_request_ = 0; 449 web_data_service_request_ = 0;
469 } 450 }
470 } 451 }
452
453 void MutableProfileOAuth2TokenServiceDelegate::Shutdown() {
454 VLOG(1) << "MutablePO2TS::Shutdown";
455 server_revokes_.clear();
456 CancelWebTokenFetch();
457 refresh_tokens_.clear();
458 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698