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

Side by Side Diff: chrome/browser/extensions/api/identity/identity_api.cc

Issue 14329014: Identity API: Add token cache and identity.invalidateAuthToken. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix invalidation crash and stale tokens for signed out users Created 7 years, 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/extensions/api/identity/identity_api.h" 5 #include "chrome/browser/extensions/api/identity/identity_api.h"
6 6
7 #include <set> 7 #include <set>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 30 matching lines...) Expand all
41 41
42 namespace identity_constants { 42 namespace identity_constants {
43 const char kInvalidClientId[] = "Invalid OAuth2 Client ID."; 43 const char kInvalidClientId[] = "Invalid OAuth2 Client ID.";
44 const char kInvalidScopes[] = "Invalid OAuth2 scopes."; 44 const char kInvalidScopes[] = "Invalid OAuth2 scopes.";
45 const char kAuthFailure[] = "OAuth2 request failed: "; 45 const char kAuthFailure[] = "OAuth2 request failed: ";
46 const char kNoGrant[] = "OAuth2 not granted or revoked."; 46 const char kNoGrant[] = "OAuth2 not granted or revoked.";
47 const char kUserRejected[] = "The user did not approve access."; 47 const char kUserRejected[] = "The user did not approve access.";
48 const char kUserNotSignedIn[] = "The user is not signed in."; 48 const char kUserNotSignedIn[] = "The user is not signed in.";
49 const char kInteractionRequired[] = "User interaction required."; 49 const char kInteractionRequired[] = "User interaction required.";
50 const char kInvalidRedirect[] = "Did not redirect to the right URL."; 50 const char kInvalidRedirect[] = "Did not redirect to the right URL.";
51
52 const int kCachedIssueAdviceTTLSeconds = 1;
51 } // namespace identity_constants 53 } // namespace identity_constants
52 54
53 namespace { 55 namespace {
54 56
55 static const char kChromiumDomainRedirectUrlPattern[] = 57 static const char kChromiumDomainRedirectUrlPattern[] =
56 "https://%s.chromiumapp.org/"; 58 "https://%s.chromiumapp.org/";
57 59
58 } // namespace 60 } // namespace
59 61
60 namespace GetAuthToken = api::experimental_identity::GetAuthToken; 62 namespace GetAuthToken = api::experimental_identity::GetAuthToken;
63 namespace InvalidateAuthToken = api::experimental_identity::InvalidateAuthToken;
61 namespace LaunchWebAuthFlow = api::experimental_identity::LaunchWebAuthFlow; 64 namespace LaunchWebAuthFlow = api::experimental_identity::LaunchWebAuthFlow;
62 namespace identity = api::experimental_identity; 65 namespace identity = api::experimental_identity;
63 66
64 IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction() 67 IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction()
65 : should_prompt_for_scopes_(false), 68 : should_prompt_for_scopes_(false),
66 should_prompt_for_signin_(false) {} 69 should_prompt_for_signin_(false) {}
67 70
68 IdentityGetAuthTokenFunction::~IdentityGetAuthTokenFunction() {} 71 IdentityGetAuthTokenFunction::~IdentityGetAuthTokenFunction() {}
69 72
70 bool IdentityGetAuthTokenFunction::RunImpl() { 73 bool IdentityGetAuthTokenFunction::RunImpl() {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 } 121 }
119 122
120 void IdentityGetAuthTokenFunction::CompleteFunctionWithError( 123 void IdentityGetAuthTokenFunction::CompleteFunctionWithError(
121 const std::string& error) { 124 const std::string& error) {
122 error_ = error; 125 error_ = error;
123 SendResponse(false); 126 SendResponse(false);
124 Release(); // Balanced in RunImpl. 127 Release(); // Balanced in RunImpl.
125 } 128 }
126 129
127 void IdentityGetAuthTokenFunction::StartSigninFlow() { 130 void IdentityGetAuthTokenFunction::StartSigninFlow() {
131 // All cached tokens are invalid because the user is not signed in.
132 IdentityAPI* id_api =
133 extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(profile_);
134 id_api->EraseAllCachedTokens();
128 // Display a login prompt. If the subsequent mint fails, don't display the 135 // Display a login prompt. If the subsequent mint fails, don't display the
129 // login prompt again. 136 // login prompt again.
130 should_prompt_for_signin_ = false; 137 should_prompt_for_signin_ = false;
131 ShowLoginPopup(); 138 ShowLoginPopup();
132 } 139 }
133 140
134 void IdentityGetAuthTokenFunction::StartMintTokenFlow( 141 void IdentityGetAuthTokenFunction::StartMintTokenFlow(
135 IdentityMintRequestQueue::MintType type) { 142 IdentityMintRequestQueue::MintType type) {
136 mint_token_flow_type_ = type; 143 mint_token_flow_type_ = type;
137 144
138 // Flows are serialized to prevent excessive traffic to GAIA, and 145 // Flows are serialized to prevent excessive traffic to GAIA, and
139 // to consolidate UI pop-ups. 146 // to consolidate UI pop-ups.
140 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension()); 147 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
141 std::set<std::string> scopes(oauth2_info.scopes.begin(), 148 std::set<std::string> scopes(oauth2_info.scopes.begin(),
142 oauth2_info.scopes.end()); 149 oauth2_info.scopes.end());
143 IdentityAPI* id_api = 150 IdentityAPI* id_api =
144 extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(profile_); 151 extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(profile_);
145 152
146 // If there is an interactive flow in progress, non-interactive 153 if (!should_prompt_for_scopes_) {
147 // requests should complete immediately since a consent UI is 154 // Caller requested no interaction.
148 // known to be required. 155
149 if (!should_prompt_for_scopes_ && !id_api->mint_queue()->empty( 156 if (type == IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE) {
150 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE, 157 // GAIA told us to do a consent UI.
151 GetExtension()->id(), scopes)) { 158 CompleteFunctionWithError(identity_constants::kNoGrant);
152 CompleteFunctionWithError(identity_constants::kNoGrant); 159 return;
153 return; 160 }
161 if (!id_api->mint_queue()->empty(
162 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE,
163 GetExtension()->id(), scopes)) {
164 // Another call is going through a consent UI.
165 CompleteFunctionWithError(identity_constants::kNoGrant);
166 return;
167 }
154 } 168 }
155 id_api->mint_queue()->RequestStart(type, 169 id_api->mint_queue()->RequestStart(type,
156 GetExtension()->id(), 170 GetExtension()->id(),
157 scopes, 171 scopes,
158 this); 172 this);
159 } 173 }
160 174
161 void IdentityGetAuthTokenFunction::CompleteMintTokenFlow() { 175 void IdentityGetAuthTokenFunction::CompleteMintTokenFlow() {
162 IdentityMintRequestQueue::MintType type = mint_token_flow_type_; 176 IdentityMintRequestQueue::MintType type = mint_token_flow_type_;
163 177
164 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension()); 178 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
165 std::set<std::string> scopes(oauth2_info.scopes.begin(), 179 std::set<std::string> scopes(oauth2_info.scopes.begin(),
166 oauth2_info.scopes.end()); 180 oauth2_info.scopes.end());
167 181
168 extensions::IdentityAPI::GetFactoryInstance()->GetForProfile( 182 extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(
169 profile_)->mint_queue()->RequestComplete(type, 183 profile_)->mint_queue()->RequestComplete(type,
170 GetExtension()->id(), 184 GetExtension()->id(),
171 scopes, 185 scopes,
172 this); 186 this);
173 } 187 }
174 188
175 void IdentityGetAuthTokenFunction::StartMintToken( 189 void IdentityGetAuthTokenFunction::StartMintToken(
176 IdentityMintRequestQueue::MintType type) { 190 IdentityMintRequestQueue::MintType type) {
177 switch (type) { 191 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
178 case IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE: 192 IdentityAPI* id_api = IdentityAPI::GetFactoryInstance()->GetForProfile(
179 StartGaiaRequest(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE); 193 profile());
180 break; 194 IdentityTokenCacheValue cache_entry = id_api->GetCachedToken(
195 GetExtension()->id(), oauth2_info.scopes);
196 IdentityTokenCacheValue::CacheValueStatus cache_status =
197 cache_entry.status();
181 198
182 case IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE: 199 if (type == IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE) {
200 switch (cache_status) {
201 case IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND:
202 StartGaiaRequest(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
203 break;
204
205 case IdentityTokenCacheValue::CACHE_STATUS_TOKEN:
206 CompleteMintTokenFlow();
207 CompleteFunctionWithResult(cache_entry.token());
208 break;
209
210 case IdentityTokenCacheValue::CACHE_STATUS_ADVICE:
211 CompleteMintTokenFlow();
212 should_prompt_for_signin_ = false;
213 issue_advice_ = cache_entry.issue_advice();
214 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
215 break;
216 }
217 } else {
218 DCHECK(type == IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
219
220 if (cache_status == IdentityTokenCacheValue::CACHE_STATUS_TOKEN) {
221 CompleteMintTokenFlow();
222 CompleteFunctionWithResult(cache_entry.token());
223 } else {
183 install_ui_.reset(new ExtensionInstallPrompt(GetAssociatedWebContents())); 224 install_ui_.reset(new ExtensionInstallPrompt(GetAssociatedWebContents()));
184 ShowOAuthApprovalDialog(issue_advice_); 225 ShowOAuthApprovalDialog(issue_advice_);
185 break; 226 }
186 227 }
187 default:
188 NOTREACHED() << "Unexepected mint type in StartMintToken: " << type;
189 break;
190 };
191 } 228 }
192 229
193 void IdentityGetAuthTokenFunction::OnMintTokenSuccess( 230 void IdentityGetAuthTokenFunction::OnMintTokenSuccess(
194 const std::string& access_token) { 231 const std::string& access_token, int time_to_live) {
232 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
233 IdentityTokenCacheValue token(access_token,
234 base::TimeDelta::FromSeconds(time_to_live));
235 IdentityAPI::GetFactoryInstance()->GetForProfile(profile())->SetCachedToken(
236 GetExtension()->id(), oauth2_info.scopes, token);
237
195 CompleteMintTokenFlow(); 238 CompleteMintTokenFlow();
196 CompleteFunctionWithResult(access_token); 239 CompleteFunctionWithResult(access_token);
197 } 240 }
198 241
199 void IdentityGetAuthTokenFunction::OnMintTokenFailure( 242 void IdentityGetAuthTokenFunction::OnMintTokenFailure(
200 const GoogleServiceAuthError& error) { 243 const GoogleServiceAuthError& error) {
201 CompleteMintTokenFlow(); 244 CompleteMintTokenFlow();
202 245
203 switch (error.state()) { 246 switch (error.state()) {
204 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: 247 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
(...skipping 11 matching lines...) Expand all
216 // Return error to caller. 259 // Return error to caller.
217 break; 260 break;
218 } 261 }
219 262
220 CompleteFunctionWithError( 263 CompleteFunctionWithError(
221 std::string(identity_constants::kAuthFailure) + error.ToString()); 264 std::string(identity_constants::kAuthFailure) + error.ToString());
222 } 265 }
223 266
224 void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess( 267 void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess(
225 const IssueAdviceInfo& issue_advice) { 268 const IssueAdviceInfo& issue_advice) {
269 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
270 IdentityAPI::GetFactoryInstance()->GetForProfile(profile())->SetCachedToken(
271 GetExtension()->id(), oauth2_info.scopes,
272 IdentityTokenCacheValue(issue_advice));
226 CompleteMintTokenFlow(); 273 CompleteMintTokenFlow();
227 274
228 should_prompt_for_signin_ = false; 275 should_prompt_for_signin_ = false;
229 // Existing grant was revoked and we used NO_FORCE, so we got info back 276 // Existing grant was revoked and we used NO_FORCE, so we got info back
230 // instead. 277 // instead. Start a consent UI if we can.
231 if (should_prompt_for_scopes_) { 278 issue_advice_ = issue_advice;
232 issue_advice_ = issue_advice; 279 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
233 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
234 } else {
235 CompleteFunctionWithError(identity_constants::kNoGrant);
236 }
237 } 280 }
238 281
239 void IdentityGetAuthTokenFunction::SigninSuccess(const std::string& token) { 282 void IdentityGetAuthTokenFunction::SigninSuccess(const std::string& token) {
240 refresh_token_ = token; 283 refresh_token_ = token;
241 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE); 284 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
242 } 285 }
243 286
244 void IdentityGetAuthTokenFunction::SigninFailed() { 287 void IdentityGetAuthTokenFunction::SigninFailed() {
245 CompleteFunctionWithError(identity_constants::kUserNotSignedIn); 288 CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
246 } 289 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 } 341 }
299 #endif 342 #endif
300 return mint_token_flow; 343 return mint_token_flow;
301 } 344 }
302 345
303 bool IdentityGetAuthTokenFunction::HasLoginToken() const { 346 bool IdentityGetAuthTokenFunction::HasLoginToken() const {
304 TokenService* token_service = TokenServiceFactory::GetForProfile(profile()); 347 TokenService* token_service = TokenServiceFactory::GetForProfile(profile());
305 return token_service->HasOAuthLoginToken(); 348 return token_service->HasOAuthLoginToken();
306 } 349 }
307 350
351 IdentityInvalidateAuthTokenFunction::IdentityInvalidateAuthTokenFunction() {}
352 IdentityInvalidateAuthTokenFunction::~IdentityInvalidateAuthTokenFunction() {}
353
354 bool IdentityInvalidateAuthTokenFunction::RunImpl() {
355 scoped_ptr<InvalidateAuthToken::Params> params(
356 InvalidateAuthToken::Params::Create(*args_));
357 EXTENSION_FUNCTION_VALIDATE(params.get());
358 const identity::InvalidTokenDetails& details = params->details;
359 IdentityAPI::GetFactoryInstance()->GetForProfile(profile())->EraseCachedToken(
360 GetExtension()->id(), details.token);
361 return true;
362 }
363
308 IdentityLaunchWebAuthFlowFunction::IdentityLaunchWebAuthFlowFunction() {} 364 IdentityLaunchWebAuthFlowFunction::IdentityLaunchWebAuthFlowFunction() {}
309 IdentityLaunchWebAuthFlowFunction::~IdentityLaunchWebAuthFlowFunction() {} 365 IdentityLaunchWebAuthFlowFunction::~IdentityLaunchWebAuthFlowFunction() {}
310 366
311 bool IdentityLaunchWebAuthFlowFunction::RunImpl() { 367 bool IdentityLaunchWebAuthFlowFunction::RunImpl() {
312 scoped_ptr<LaunchWebAuthFlow::Params> params( 368 scoped_ptr<LaunchWebAuthFlow::Params> params(
313 LaunchWebAuthFlow::Params::Create(*args_)); 369 LaunchWebAuthFlow::Params::Create(*args_));
314 EXTENSION_FUNCTION_VALIDATE(params.get()); 370 EXTENSION_FUNCTION_VALIDATE(params.get());
315 const identity::WebAuthFlowDetails& details = params->details; 371 const identity::WebAuthFlowDetails& details = params->details;
316 372
317 GURL auth_url(details.url); 373 GURL auth_url(details.url);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 446
391 void IdentityLaunchWebAuthFlowFunction::OnAuthFlowURLChange( 447 void IdentityLaunchWebAuthFlowFunction::OnAuthFlowURLChange(
392 const GURL& redirect_url) { 448 const GURL& redirect_url) {
393 if (IsFinalRedirectURL(redirect_url)) { 449 if (IsFinalRedirectURL(redirect_url)) {
394 SetResult(Value::CreateStringValue(redirect_url.spec())); 450 SetResult(Value::CreateStringValue(redirect_url.spec()));
395 SendResponse(true); 451 SendResponse(true);
396 Release(); // Balanced in RunImpl. 452 Release(); // Balanced in RunImpl.
397 } 453 }
398 } 454 }
399 455
456 IdentityTokenCacheValue::IdentityTokenCacheValue()
457 : status_(CACHE_STATUS_NOTFOUND) {
458 }
459
460 IdentityTokenCacheValue::IdentityTokenCacheValue(
461 const IssueAdviceInfo& issue_advice) : status_(CACHE_STATUS_ADVICE),
462 issue_advice_(issue_advice) {
463 expiration_time_ = base::Time::Now() + base::TimeDelta::FromSeconds(
464 identity_constants::kCachedIssueAdviceTTLSeconds);
465 }
466
467 IdentityTokenCacheValue::IdentityTokenCacheValue(
468 const std::string& token, base::TimeDelta time_to_live)
469 : status_(CACHE_STATUS_TOKEN),
470 token_(token) {
471 base::TimeDelta zero_delta;
472 if (time_to_live < zero_delta)
473 time_to_live = zero_delta;
474
475 expiration_time_ = base::Time::Now() + time_to_live;
476 }
477
478 IdentityTokenCacheValue::~IdentityTokenCacheValue() {
479 }
480
481 IdentityTokenCacheValue::CacheValueStatus
482 IdentityTokenCacheValue::status() const {
483 if (is_expired())
484 return IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND;
485 else
486 return status_;
487 }
488
489 const IssueAdviceInfo& IdentityTokenCacheValue::issue_advice() const {
490 return issue_advice_;
491 }
492
493 const std::string& IdentityTokenCacheValue::token() const {
494 return token_;
495 }
496
497 bool IdentityTokenCacheValue::is_expired() const {
498 return status_ == CACHE_STATUS_NOTFOUND ||
499 expiration_time_ < base::Time::Now();
500 }
501
400 IdentityAPI::IdentityAPI(Profile* profile) 502 IdentityAPI::IdentityAPI(Profile* profile)
401 : profile_(profile), 503 : profile_(profile),
402 signin_manager_(NULL), 504 signin_manager_(NULL),
403 error_(GoogleServiceAuthError::NONE) { 505 error_(GoogleServiceAuthError::NONE) {
404 (new OAuth2ManifestHandler)->Register(); 506 (new OAuth2ManifestHandler)->Register();
405 } 507 }
406 508
407 IdentityAPI::~IdentityAPI() { 509 IdentityAPI::~IdentityAPI() {
408 } 510 }
409 511
410 void IdentityAPI::Initialize() { 512 void IdentityAPI::Initialize() {
411 signin_manager_ = SigninManagerFactory::GetForProfile(profile_); 513 signin_manager_ = SigninManagerFactory::GetForProfile(profile_);
412 signin_manager_->signin_global_error()->AddProvider(this); 514 signin_manager_->signin_global_error()->AddProvider(this);
413 515
414 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); 516 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
415 registrar_.Add(this, 517 registrar_.Add(this,
416 chrome::NOTIFICATION_TOKEN_AVAILABLE, 518 chrome::NOTIFICATION_TOKEN_AVAILABLE,
417 content::Source<TokenService>(token_service)); 519 content::Source<TokenService>(token_service));
418 } 520 }
419 521
420 IdentityMintRequestQueue* IdentityAPI::mint_queue() { 522 IdentityMintRequestQueue* IdentityAPI::mint_queue() {
421 return &mint_queue_; 523 return &mint_queue_;
422 } 524 }
423 525
526 void IdentityAPI::SetCachedToken(const std::string& extension_id,
527 const std::vector<std::string> scopes,
528 const IdentityTokenCacheValue& token_data) {
529 std::set<std::string> scopeset(scopes.begin(), scopes.end());
530 TokenCacheKey key(extension_id, scopeset);
531
532 std::map<TokenCacheKey, IdentityTokenCacheValue>::iterator it =
533 token_cache_.find(key);
534 if (it != token_cache_.end() && it->second.status() <= token_data.status())
535 token_cache_.erase(it);
536
537 token_cache_.insert(std::make_pair(key, token_data));
538 }
539
540 void IdentityAPI::EraseCachedToken(const std::string& extension_id,
541 const std::string& token) {
542 std::map<TokenCacheKey, IdentityTokenCacheValue>::iterator it;
543 for (it = token_cache_.begin(); it != token_cache_.end(); ++it) {
544 if (it->first.extension_id == extension_id &&
545 it->second.status() == IdentityTokenCacheValue::CACHE_STATUS_TOKEN &&
546 it->second.token() == token) {
547 token_cache_.erase(it);
548 break;
549 }
550 }
551 }
552
553 void IdentityAPI::EraseAllCachedTokens() {
554 token_cache_.clear();
555 }
556
557 const IdentityTokenCacheValue& IdentityAPI::GetCachedToken(
558 const std::string& extension_id, const std::vector<std::string> scopes) {
559 std::set<std::string> scopeset(scopes.begin(), scopes.end());
560 TokenCacheKey key(extension_id, scopeset);
561 return token_cache_[key];
562 }
563
424 void IdentityAPI::ReportAuthError(const GoogleServiceAuthError& error) { 564 void IdentityAPI::ReportAuthError(const GoogleServiceAuthError& error) {
425 if (!signin_manager_) 565 if (!signin_manager_)
426 Initialize(); 566 Initialize();
427 567
428 error_ = error; 568 error_ = error;
429 signin_manager_->signin_global_error()->AuthStatusChanged(); 569 signin_manager_->signin_global_error()->AuthStatusChanged();
430 } 570 }
431 571
432 void IdentityAPI::Shutdown() { 572 void IdentityAPI::Shutdown() {
433 if (signin_manager_) 573 if (signin_manager_)
(...skipping 25 matching lines...) Expand all
459 } 599 }
460 } 600 }
461 601
462 template <> 602 template <>
463 void ProfileKeyedAPIFactory<IdentityAPI>::DeclareFactoryDependencies() { 603 void ProfileKeyedAPIFactory<IdentityAPI>::DeclareFactoryDependencies() {
464 DependsOn(ExtensionSystemFactory::GetInstance()); 604 DependsOn(ExtensionSystemFactory::GetInstance());
465 DependsOn(TokenServiceFactory::GetInstance()); 605 DependsOn(TokenServiceFactory::GetInstance());
466 DependsOn(SigninManagerFactory::GetInstance()); 606 DependsOn(SigninManagerFactory::GetInstance());
467 } 607 }
468 608
609 IdentityAPI::TokenCacheKey::TokenCacheKey(const std::string& extension_id,
610 const std::set<std::string> scopes)
611 : extension_id(extension_id),
612 scopes(scopes) {
613 }
614
615 IdentityAPI::TokenCacheKey::~TokenCacheKey() {
616 }
617
618 bool IdentityAPI::TokenCacheKey::operator<(
619 const IdentityAPI::TokenCacheKey& rhs) const {
620 if (extension_id < rhs.extension_id)
621 return true;
622 else if (rhs.extension_id < extension_id)
623 return false;
624
625 return scopes < rhs.scopes;
626 }
627
469 } // namespace extensions 628 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698