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

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

Issue 23382008: Making OAuth2TokenService multi-login aware, updating callers, minor fixes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adding the AndroidPO2TS update Created 7 years, 3 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "chrome/browser/signin/profile_oauth2_token_service.h" 5 #include "chrome/browser/signin/profile_oauth2_token_service.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h" 8 #include "base/message_loop/message_loop.h"
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/time/time.h" 10 #include "base/time/time.h"
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 92
93 void ProfileOAuth2TokenService::Shutdown() { 93 void ProfileOAuth2TokenService::Shutdown() {
94 DCHECK(profile_) << "Shutdown() called without matching call to Initialize()"; 94 DCHECK(profile_) << "Shutdown() called without matching call to Initialize()";
95 CancelAllRequests(); 95 CancelAllRequests();
96 signin_global_error_->RemoveProvider(this); 96 signin_global_error_->RemoveProvider(this);
97 GlobalErrorServiceFactory::GetForProfile(profile_)->RemoveGlobalError( 97 GlobalErrorServiceFactory::GetForProfile(profile_)->RemoveGlobalError(
98 signin_global_error_.get()); 98 signin_global_error_.get());
99 signin_global_error_.reset(); 99 signin_global_error_.reset();
100 } 100 }
101 101
102 std::string ProfileOAuth2TokenService::GetRefreshToken() { 102 std::string ProfileOAuth2TokenService::GetRefreshToken(
103 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); 103 const std::string& account_id) {
104 if (!token_service || !token_service->HasOAuthLoginToken()) { 104 return refresh_tokens_[account_id];
105 return std::string();
106 }
107 return token_service->GetOAuth2LoginRefreshToken();
108 } 105 }
109 106
110 net::URLRequestContextGetter* ProfileOAuth2TokenService::GetRequestContext() { 107 net::URLRequestContextGetter* ProfileOAuth2TokenService::GetRequestContext() {
111 return profile_->GetRequestContext(); 108 return profile_->GetRequestContext();
112 } 109 }
113 110
114 void ProfileOAuth2TokenService::UpdateAuthError( 111 void ProfileOAuth2TokenService::UpdateAuthError(
112 const std::string& account_id,
115 const GoogleServiceAuthError& error) { 113 const GoogleServiceAuthError& error) {
114 // TODO(fgorski): SigninGlobalError needs to be made multi-login aware.
116 // Do not report connection errors as these are not actually auth errors. 115 // Do not report connection errors as these are not actually auth errors.
117 // We also want to avoid masking a "real" auth error just because we 116 // We also want to avoid masking a "real" auth error just because we
118 // subsequently get a transient network error. 117 // subsequently get a transient network error.
119 if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) 118 if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED)
120 return; 119 return;
121 120
122 if (error.state() != last_auth_error_.state()) { 121 if (error.state() != last_auth_error_.state()) {
123 last_auth_error_ = error; 122 last_auth_error_ = error;
124 signin_global_error_->AuthStatusChanged(); 123 signin_global_error_->AuthStatusChanged();
125 } 124 }
126 } 125 }
127 126
128 void ProfileOAuth2TokenService::Observe( 127 void ProfileOAuth2TokenService::Observe(
129 int type, 128 int type,
130 const content::NotificationSource& source, 129 const content::NotificationSource& source,
131 const content::NotificationDetails& details) { 130 const content::NotificationDetails& details) {
132 switch (type) { 131 switch (type) {
133 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { 132 case chrome::NOTIFICATION_TOKEN_AVAILABLE: {
134 TokenService::TokenAvailableDetails* tok_details = 133 TokenService::TokenAvailableDetails* tok_details =
135 content::Details<TokenService::TokenAvailableDetails>(details).ptr(); 134 content::Details<TokenService::TokenAvailableDetails>(details).ptr();
136 if (tok_details->service() == 135 if (tok_details->service() ==
137 GaiaConstants::kGaiaOAuth2LoginRefreshToken) { 136 GaiaConstants::kGaiaOAuth2LoginRefreshToken) {
138 // TODO(fgorski): Canceling all requests will not be correct in a 137 // TODO(fgorski): Canceling all requests will not be correct in a
139 // multi-login environment. We should cancel only the requests related 138 // multi-login environment. We should cancel only the requests related
140 // to the token being replaced (old token for the same account_id). 139 // to the token being replaced (old token for the same account_id).
141 // Previous refresh token is not available at this point, but since 140 // Previous refresh token is not available at this point, but since
142 // there are no other refresh tokens, we cancel all active requests. 141 // there are no other refresh tokens, we cancel all active requests.
143 CancelAllRequests(); 142 CancelAllRequests();
144 ClearCache(); 143 ClearCache();
145 UpdateAuthError(GoogleServiceAuthError::AuthErrorNone()); 144 UpdateAuthError(GetPrimaryAccountId(),
145 GoogleServiceAuthError::AuthErrorNone());
146 FireRefreshTokenAvailable(GetAccountId(profile_)); 146 FireRefreshTokenAvailable(GetAccountId(profile_));
147 } 147 }
148 break; 148 break;
149 } 149 }
150 case chrome::NOTIFICATION_TOKENS_CLEARED: { 150 case chrome::NOTIFICATION_TOKENS_CLEARED: {
151 CancelAllRequests(); 151 CancelAllRequests();
152 ClearCache(); 152 ClearCache();
153 UpdateAuthError(GoogleServiceAuthError::AuthErrorNone()); 153 UpdateAuthError(GetPrimaryAccountId(),
154 FireRefreshTokensCleared(); 154 GoogleServiceAuthError::AuthErrorNone());
155 break; 155 break;
156 } 156 }
157 case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: 157 case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED:
158 // During startup, if the user is signed in and the OAuth2 refresh token 158 // During startup, if the user is signed in and the OAuth2 refresh token
159 // is empty, flag it as an error by badging the menu. Otherwise, if the 159 // is empty, flag it as an error by badging the menu. Otherwise, if the
160 // user goes on to set up sync, they will have to make two attempts: 160 // user goes on to set up sync, they will have to make two attempts:
161 // One to surface the OAuth2 error, and a second one after signing in. 161 // One to surface the OAuth2 error, and a second one after signing in.
162 // See crbug.com/276650. 162 // See crbug.com/276650.
163 if (!GetAccountId(profile_).empty() && GetRefreshToken().empty()) { 163 if (!GetPrimaryAccountId().empty() &&
164 UpdateAuthError(GoogleServiceAuthError( 164 !RefreshTokenIsAvailable(GetPrimaryAccountId())) {
165 UpdateAuthError(GetPrimaryAccountId(), GoogleServiceAuthError(
165 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); 166 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
166 } 167 }
167 FireRefreshTokensLoaded(); 168 FireRefreshTokensLoaded();
168 break; 169 break;
169 default: 170 default:
170 NOTREACHED() << "Invalid notification type=" << type; 171 NOTREACHED() << "Invalid notification type=" << type;
171 break; 172 break;
172 } 173 }
173 } 174 }
174 175
175 GoogleServiceAuthError ProfileOAuth2TokenService::GetAuthStatus() const { 176 GoogleServiceAuthError ProfileOAuth2TokenService::GetAuthStatus() const {
176 return last_auth_error_; 177 return last_auth_error_;
177 } 178 }
178 179
179 void ProfileOAuth2TokenService::RegisterCacheEntry( 180 void ProfileOAuth2TokenService::RegisterCacheEntry(
180 const std::string& refresh_token, 181 const std::string& refresh_token,
181 const ScopeSet& scopes, 182 const ScopeSet& scopes,
182 const std::string& access_token, 183 const std::string& access_token,
183 const base::Time& expiration_date) { 184 const base::Time& expiration_date) {
184 if (ShouldCacheForRefreshToken(TokenServiceFactory::GetForProfile(profile_), 185 if (ShouldCacheForRefreshToken(refresh_token)) {
185 refresh_token)) {
186 OAuth2TokenService::RegisterCacheEntry(refresh_token, 186 OAuth2TokenService::RegisterCacheEntry(refresh_token,
187 scopes, 187 scopes,
188 access_token, 188 access_token,
189 expiration_date); 189 expiration_date);
190 } 190 }
191 } 191 }
192 192
193 bool ProfileOAuth2TokenService::ShouldCacheForRefreshToken( 193 bool ProfileOAuth2TokenService::ShouldCacheForRefreshToken(
194 TokenService *token_service,
195 const std::string& refresh_token) { 194 const std::string& refresh_token) {
196 if (!token_service || 195 // Check below ensures that only refresh tokens belonging to one of the logged
197 !token_service->HasOAuthLoginToken() || 196 // in accounts will allow for the access tokens to be cached.
198 token_service->GetOAuth2LoginRefreshToken().compare(refresh_token) != 0) { 197 // TODO(fgorski): Convert to CHECK/DCHECK if it should not be possible.
199 DLOG(INFO) << 198 // Consider a re-auth scenario.
200 "Received a token with a refresh token not maintained by TokenService."; 199 for (std::map<std::string, std::string>::const_iterator iter =
201 return false; 200 refresh_tokens_.begin(); iter != refresh_tokens_.end(); ++iter) {
201 if (iter->second == refresh_token)
202 return true;
202 } 203 }
203 return true; 204
205 DLOG(INFO) <<
206 "Received a token with a refresh token not maintained by TokenService.";
207 return false;
208 }
209
210 std::string ProfileOAuth2TokenService::GetPrimaryAccountId() {
211 SigninManagerBase* signin_manager =
212 SigninManagerFactory::GetForProfileIfExists(profile_);
213 return signin_manager ? signin_manager->GetAuthenticatedUsername() :
Roger Tawa OOO till Jul 10th 2013/08/29 15:41:40 Should probably DCHECK that SM is not null, at lea
fgorski 2013/08/29 23:04:14 Done.
214 std::string();
215 }
216
217 std::vector<std::string> ProfileOAuth2TokenService::GetAccounts() {
218 std::vector<std::string> account_ids;
219 for (std::map<std::string, std::string>::const_iterator iter =
220 refresh_tokens_.begin(); iter != refresh_tokens_.end(); ++iter) {
221 account_ids.push_back(iter->first);
222 }
223 return account_ids;
204 } 224 }
205 225
206 void ProfileOAuth2TokenService::UpdateCredentials( 226 void ProfileOAuth2TokenService::UpdateCredentials(
207 const std::string& account_id, 227 const std::string& account_id,
208 const std::string& refresh_token) { 228 const std::string& refresh_token) {
209 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 229 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
210 DCHECK(!refresh_token.empty()); 230 DCHECK(!refresh_token.empty());
211 231
212 bool refresh_token_present = refresh_tokens_.count(account_id) > 0; 232 bool refresh_token_present = refresh_tokens_.count(account_id) > 0;
213 if (!refresh_token_present || 233 if (!refresh_token_present ||
214 refresh_tokens_[account_id] != refresh_token) { 234 refresh_tokens_[account_id] != refresh_token) {
215 // If token present, and different from the new one, cancel its requests. 235 // If token present, and different from the new one, cancel its requests,
216 if (refresh_token_present) 236 // and clear the entries in cache related to that account.
237 if (refresh_token_present) {
217 CancelRequestsForToken(refresh_tokens_[account_id]); 238 CancelRequestsForToken(refresh_tokens_[account_id]);
239 // ClearCacheForAccount(account_id);
240 }
218 241
219 // Save the token in memory and in persistent store. 242 // Save the token in memory and in persistent store.
220 refresh_tokens_[account_id] = refresh_token; 243 refresh_tokens_[account_id] = refresh_token;
221 scoped_refptr<TokenWebData> token_web_data = 244 scoped_refptr<TokenWebData> token_web_data =
222 TokenWebData::FromBrowserContext(profile_); 245 TokenWebData::FromBrowserContext(profile_);
223 if (token_web_data.get()) 246 if (token_web_data.get())
224 token_web_data->SetTokenForService(ApplyAccountIdPrefix(account_id), 247 token_web_data->SetTokenForService(ApplyAccountIdPrefix(account_id),
225 refresh_token); 248 refresh_token);
226 249
250 UpdateAuthError(account_id, GoogleServiceAuthError::AuthErrorNone());
227 FireRefreshTokenAvailable(account_id); 251 FireRefreshTokenAvailable(account_id);
228 // TODO(fgorski): Notify diagnostic observers. 252 // TODO(fgorski): Notify diagnostic observers.
229 } 253 }
230 } 254 }
231 255
232 void ProfileOAuth2TokenService::RevokeCredentials( 256 void ProfileOAuth2TokenService::RevokeCredentials(
233 const std::string& account_id) { 257 const std::string& account_id) {
234 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 258 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
235 259
236 if (refresh_tokens_.count(account_id) > 0) { 260 if (refresh_tokens_.count(account_id) > 0) {
237 CancelRequestsForToken(refresh_tokens_[account_id]); 261 CancelRequestsForToken(refresh_tokens_[account_id]);
262 // TODO(fgorski): Call ClearCacheForAccount(account_id) from here.
238 refresh_tokens_.erase(account_id); 263 refresh_tokens_.erase(account_id);
239 scoped_refptr<TokenWebData> token_web_data = 264 scoped_refptr<TokenWebData> token_web_data =
240 TokenWebData::FromBrowserContext(profile_); 265 TokenWebData::FromBrowserContext(profile_);
241 if (token_web_data.get()) 266 if (token_web_data.get())
242 token_web_data->RemoveTokenForService(ApplyAccountIdPrefix(account_id)); 267 token_web_data->RemoveTokenForService(ApplyAccountIdPrefix(account_id));
243 FireRefreshTokenRevoked(account_id); 268 FireRefreshTokenRevoked(account_id);
244 269
245 // TODO(fgorski): Notify diagnostic observers. 270 // TODO(fgorski): Notify diagnostic observers.
246 } 271 }
247 } 272 }
248 273
249 void ProfileOAuth2TokenService::RevokeAllCredentials() { 274 void ProfileOAuth2TokenService::RevokeAllCredentials() {
250 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 275 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
251 276
252 CancelAllRequests(); 277 CancelAllRequests();
253 for (std::map<std::string, std::string>::const_iterator iter = 278 for (std::map<std::string, std::string>::const_iterator iter =
254 refresh_tokens_.begin(); 279 refresh_tokens_.begin();
255 iter != refresh_tokens_.end(); 280 iter != refresh_tokens_.end();
256 ++iter) { 281 ++iter) {
257 FireRefreshTokenRevoked(iter->first); 282 FireRefreshTokenRevoked(iter->first);
258 } 283 }
259 refresh_tokens_.clear(); 284 refresh_tokens_.clear();
260 285
261 scoped_refptr<TokenWebData> token_web_data = 286 scoped_refptr<TokenWebData> token_web_data =
262 TokenWebData::FromBrowserContext(profile_); 287 TokenWebData::FromBrowserContext(profile_);
263 if (token_web_data.get()) 288 if (token_web_data.get())
264 token_web_data->RemoveAllTokens(); 289 token_web_data->RemoveAllTokens();
265 FireRefreshTokensCleared();
266 290
267 // TODO(fgorski): Notify diagnostic observers. 291 // TODO(fgorski): Notify diagnostic observers.
268 } 292 }
269 293
270 void ProfileOAuth2TokenService::LoadCredentials() { 294 void ProfileOAuth2TokenService::LoadCredentials() {
271 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 295 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
272 DCHECK_EQ(0, web_data_service_request_); 296 DCHECK_EQ(0, web_data_service_request_);
273 297
274 CancelAllRequests(); 298 CancelAllRequests();
275 refresh_tokens_.clear(); 299 refresh_tokens_.clear();
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 } 347 }
324 } 348 }
325 349
326 if (!old_login_token.empty() && 350 if (!old_login_token.empty() &&
327 refresh_tokens_.count(GetAccountId(profile_)) == 0) { 351 refresh_tokens_.count(GetAccountId(profile_)) == 0) {
328 UpdateCredentials(GetAccountId(profile_), old_login_token); 352 UpdateCredentials(GetAccountId(profile_), old_login_token);
329 } 353 }
330 354
331 FireRefreshTokensLoaded(); 355 FireRefreshTokensLoaded();
332 } 356 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698