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

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

Issue 99173004: Identity API: add multi-account support to token cache and request queues (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years 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 <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 if (oauth2_client_id_.empty()) { 96 if (oauth2_client_id_.empty()) {
97 error_ = identity_constants::kInvalidClientId; 97 error_ = identity_constants::kInvalidClientId;
98 return false; 98 return false;
99 } 99 }
100 100
101 if (oauth2_info.scopes.size() == 0) { 101 if (oauth2_info.scopes.size() == 0) {
102 error_ = identity_constants::kInvalidScopes; 102 error_ = identity_constants::kInvalidScopes;
103 return false; 103 return false;
104 } 104 }
105 105
106 ProfileOAuth2TokenService* token_service =
107 ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile());
108
109 std::set<std::string> scopes(oauth2_info.scopes.begin(),
110 oauth2_info.scopes.end());
111 token_key_.reset(new ExtensionTokenKey(
112 GetExtension()->id(), token_service->GetPrimaryAccountId(), scopes));
113
106 // Balanced in CompleteFunctionWithResult|CompleteFunctionWithError 114 // Balanced in CompleteFunctionWithResult|CompleteFunctionWithError
107 AddRef(); 115 AddRef();
108 116
109 #if defined(OS_CHROMEOS) 117 #if defined(OS_CHROMEOS)
110 if (chromeos::UserManager::Get()->IsLoggedInAsKioskApp() && 118 if (chromeos::UserManager::Get()->IsLoggedInAsKioskApp() &&
111 g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) { 119 g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
112 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE); 120 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
113 return true; 121 return true;
114 } 122 }
115 #endif 123 #endif
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 should_prompt_for_signin_ = false; 162 should_prompt_for_signin_ = false;
155 ShowLoginPopup(); 163 ShowLoginPopup();
156 } 164 }
157 165
158 void IdentityGetAuthTokenFunction::StartMintTokenFlow( 166 void IdentityGetAuthTokenFunction::StartMintTokenFlow(
159 IdentityMintRequestQueue::MintType type) { 167 IdentityMintRequestQueue::MintType type) {
160 mint_token_flow_type_ = type; 168 mint_token_flow_type_ = type;
161 169
162 // Flows are serialized to prevent excessive traffic to GAIA, and 170 // Flows are serialized to prevent excessive traffic to GAIA, and
163 // to consolidate UI pop-ups. 171 // to consolidate UI pop-ups.
164 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
165 std::set<std::string> scopes(oauth2_info.scopes.begin(),
166 oauth2_info.scopes.end());
167 IdentityAPI* id_api = 172 IdentityAPI* id_api =
168 extensions::IdentityAPI::GetFactoryInstance()->GetForProfile( 173 extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(
169 GetProfile()); 174 GetProfile());
170 175
171 if (!should_prompt_for_scopes_) { 176 if (!should_prompt_for_scopes_) {
172 // Caller requested no interaction. 177 // Caller requested no interaction.
173 178
174 if (type == IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE) { 179 if (type == IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE) {
175 // GAIA told us to do a consent UI. 180 // GAIA told us to do a consent UI.
176 CompleteFunctionWithError(identity_constants::kNoGrant); 181 CompleteFunctionWithError(identity_constants::kNoGrant);
177 return; 182 return;
178 } 183 }
179 if (!id_api->mint_queue()->empty( 184 if (!id_api->mint_queue()->empty(
180 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE, 185 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE, *token_key_)) {
181 GetExtension()->id(), scopes)) {
182 // Another call is going through a consent UI. 186 // Another call is going through a consent UI.
183 CompleteFunctionWithError(identity_constants::kNoGrant); 187 CompleteFunctionWithError(identity_constants::kNoGrant);
184 return; 188 return;
185 } 189 }
186 } 190 }
187 id_api->mint_queue()->RequestStart(type, 191 id_api->mint_queue()->RequestStart(type, *token_key_, this);
188 GetExtension()->id(),
189 scopes,
190 this);
191 } 192 }
192 193
193 void IdentityGetAuthTokenFunction::CompleteMintTokenFlow() { 194 void IdentityGetAuthTokenFunction::CompleteMintTokenFlow() {
194 IdentityMintRequestQueue::MintType type = mint_token_flow_type_; 195 IdentityMintRequestQueue::MintType type = mint_token_flow_type_;
195 196
196 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension()); 197 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
197 std::set<std::string> scopes(oauth2_info.scopes.begin(), 198 std::set<std::string> scopes(oauth2_info.scopes.begin(),
198 oauth2_info.scopes.end()); 199 oauth2_info.scopes.end());
199 200
200 extensions::IdentityAPI::GetFactoryInstance() 201 extensions::IdentityAPI::GetFactoryInstance()
201 ->GetForProfile(GetProfile()) 202 ->GetForProfile(GetProfile())
202 ->mint_queue() 203 ->mint_queue()
203 ->RequestComplete(type, GetExtension()->id(), scopes, this); 204 ->RequestComplete(type, *token_key_, this);
204 } 205 }
205 206
206 void IdentityGetAuthTokenFunction::StartMintToken( 207 void IdentityGetAuthTokenFunction::StartMintToken(
207 IdentityMintRequestQueue::MintType type) { 208 IdentityMintRequestQueue::MintType type) {
208 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension()); 209 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
209 IdentityAPI* id_api = 210 IdentityAPI* id_api =
210 IdentityAPI::GetFactoryInstance()->GetForProfile(GetProfile()); 211 IdentityAPI::GetFactoryInstance()->GetForProfile(GetProfile());
211 IdentityTokenCacheValue cache_entry = id_api->GetCachedToken( 212 IdentityTokenCacheValue cache_entry = id_api->GetCachedToken(*token_key_);
212 GetExtension()->id(), oauth2_info.scopes);
213 IdentityTokenCacheValue::CacheValueStatus cache_status = 213 IdentityTokenCacheValue::CacheValueStatus cache_status =
214 cache_entry.status(); 214 cache_entry.status();
215 215
216 if (type == IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE) { 216 if (type == IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE) {
217 switch (cache_status) { 217 switch (cache_status) {
218 case IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND: 218 case IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND:
219 #if defined(OS_CHROMEOS) 219 #if defined(OS_CHROMEOS)
220 // Always force minting token for ChromeOS kiosk app. 220 // Always force minting token for ChromeOS kiosk app.
221 if (chromeos::UserManager::Get()->IsLoggedInAsKioskApp()) { 221 if (chromeos::UserManager::Get()->IsLoggedInAsKioskApp()) {
222 gaia_mint_token_mode_ = OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE; 222 gaia_mint_token_mode_ = OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 CompleteMintTokenFlow(); 259 CompleteMintTokenFlow();
260 CompleteFunctionWithResult(cache_entry.token()); 260 CompleteFunctionWithResult(cache_entry.token());
261 } else { 261 } else {
262 ShowOAuthApprovalDialog(issue_advice_); 262 ShowOAuthApprovalDialog(issue_advice_);
263 } 263 }
264 } 264 }
265 } 265 }
266 266
267 void IdentityGetAuthTokenFunction::OnMintTokenSuccess( 267 void IdentityGetAuthTokenFunction::OnMintTokenSuccess(
268 const std::string& access_token, int time_to_live) { 268 const std::string& access_token, int time_to_live) {
269 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
270 IdentityTokenCacheValue token(access_token, 269 IdentityTokenCacheValue token(access_token,
271 base::TimeDelta::FromSeconds(time_to_live)); 270 base::TimeDelta::FromSeconds(time_to_live));
272 IdentityAPI::GetFactoryInstance() 271 IdentityAPI::GetFactoryInstance()
273 ->GetForProfile(GetProfile()) 272 ->GetForProfile(GetProfile())
274 ->SetCachedToken(GetExtension()->id(), oauth2_info.scopes, token); 273 ->SetCachedToken(*token_key_, token);
275 274
276 CompleteMintTokenFlow(); 275 CompleteMintTokenFlow();
277 CompleteFunctionWithResult(access_token); 276 CompleteFunctionWithResult(access_token);
278 } 277 }
279 278
280 void IdentityGetAuthTokenFunction::OnMintTokenFailure( 279 void IdentityGetAuthTokenFunction::OnMintTokenFailure(
281 const GoogleServiceAuthError& error) { 280 const GoogleServiceAuthError& error) {
282 CompleteMintTokenFlow(); 281 CompleteMintTokenFlow();
283 282
284 switch (error.state()) { 283 switch (error.state()) {
(...skipping 14 matching lines...) Expand all
299 // Return error to caller. 298 // Return error to caller.
300 break; 299 break;
301 } 300 }
302 301
303 CompleteFunctionWithError( 302 CompleteFunctionWithError(
304 std::string(identity_constants::kAuthFailure) + error.ToString()); 303 std::string(identity_constants::kAuthFailure) + error.ToString());
305 } 304 }
306 305
307 void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess( 306 void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess(
308 const IssueAdviceInfo& issue_advice) { 307 const IssueAdviceInfo& issue_advice) {
309 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
310 IdentityAPI::GetFactoryInstance() 308 IdentityAPI::GetFactoryInstance()
311 ->GetForProfile(GetProfile()) 309 ->GetForProfile(GetProfile())
312 ->SetCachedToken(GetExtension()->id(), 310 ->SetCachedToken(*token_key_,
313 oauth2_info.scopes,
314 IdentityTokenCacheValue(issue_advice)); 311 IdentityTokenCacheValue(issue_advice));
315 CompleteMintTokenFlow(); 312 CompleteMintTokenFlow();
316 313
317 should_prompt_for_signin_ = false; 314 should_prompt_for_signin_ = false;
318 // Existing grant was revoked and we used NO_FORCE, so we got info back 315 // Existing grant was revoked and we used NO_FORCE, so we got info back
319 // instead. Start a consent UI if we can. 316 // instead. Start a consent UI if we can.
320 issue_advice_ = issue_advice; 317 issue_advice_ = issue_advice;
321 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE); 318 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
322 } 319 }
323 320
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 363
367 CompleteFunctionWithError(error); 364 CompleteFunctionWithError(error);
368 } 365 }
369 366
370 void IdentityGetAuthTokenFunction::OnGaiaFlowCompleted( 367 void IdentityGetAuthTokenFunction::OnGaiaFlowCompleted(
371 const std::string& access_token, 368 const std::string& access_token,
372 const std::string& expiration) { 369 const std::string& expiration) {
373 370
374 int time_to_live; 371 int time_to_live;
375 if (!expiration.empty() && base::StringToInt(expiration, &time_to_live)) { 372 if (!expiration.empty() && base::StringToInt(expiration, &time_to_live)) {
376 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
377 IdentityTokenCacheValue token_value( 373 IdentityTokenCacheValue token_value(
378 access_token, base::TimeDelta::FromSeconds(time_to_live)); 374 access_token, base::TimeDelta::FromSeconds(time_to_live));
379 IdentityAPI::GetFactoryInstance() 375 IdentityAPI::GetFactoryInstance()
380 ->GetForProfile(GetProfile()) 376 ->GetForProfile(GetProfile())
381 ->SetCachedToken(GetExtension()->id(), oauth2_info.scopes, token_value); 377 ->SetCachedToken(*token_key_, token_value);
382 } 378 }
383 379
384 CompleteMintTokenFlow(); 380 CompleteMintTokenFlow();
385 CompleteFunctionWithResult(access_token); 381 CompleteFunctionWithResult(access_token);
386 } 382 }
387 383
388 void IdentityGetAuthTokenFunction::OnGetTokenSuccess( 384 void IdentityGetAuthTokenFunction::OnGetTokenSuccess(
389 const OAuth2TokenService::Request* request, 385 const OAuth2TokenService::Request* request,
390 const std::string& access_token, 386 const std::string& access_token,
391 const base::Time& expiration_time) { 387 const base::Time& expiration_time) {
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 account_tracker_(profile) { 671 account_tracker_(profile) {
676 account_tracker_.AddObserver(this); 672 account_tracker_.AddObserver(this);
677 } 673 }
678 674
679 IdentityAPI::~IdentityAPI() {} 675 IdentityAPI::~IdentityAPI() {}
680 676
681 IdentityMintRequestQueue* IdentityAPI::mint_queue() { 677 IdentityMintRequestQueue* IdentityAPI::mint_queue() {
682 return &mint_queue_; 678 return &mint_queue_;
683 } 679 }
684 680
685 void IdentityAPI::SetCachedToken(const std::string& extension_id, 681 void IdentityAPI::SetCachedToken(const ExtensionTokenKey& key,
686 const std::vector<std::string> scopes,
687 const IdentityTokenCacheValue& token_data) { 682 const IdentityTokenCacheValue& token_data) {
688 std::set<std::string> scopeset(scopes.begin(), scopes.end());
689 TokenCacheKey key(extension_id, scopeset);
690
691 CachedTokens::iterator it = token_cache_.find(key); 683 CachedTokens::iterator it = token_cache_.find(key);
692 if (it != token_cache_.end() && it->second.status() <= token_data.status()) 684 if (it != token_cache_.end() && it->second.status() <= token_data.status())
693 token_cache_.erase(it); 685 token_cache_.erase(it);
694 686
695 token_cache_.insert(std::make_pair(key, token_data)); 687 token_cache_.insert(std::make_pair(key, token_data));
696 } 688 }
697 689
698 void IdentityAPI::EraseCachedToken(const std::string& extension_id, 690 void IdentityAPI::EraseCachedToken(const std::string& extension_id,
699 const std::string& token) { 691 const std::string& token) {
700 CachedTokens::iterator it; 692 CachedTokens::iterator it;
701 for (it = token_cache_.begin(); it != token_cache_.end(); ++it) { 693 for (it = token_cache_.begin(); it != token_cache_.end(); ++it) {
702 if (it->first.extension_id == extension_id && 694 if (it->first.extension_id == extension_id &&
703 it->second.status() == IdentityTokenCacheValue::CACHE_STATUS_TOKEN && 695 it->second.status() == IdentityTokenCacheValue::CACHE_STATUS_TOKEN &&
704 it->second.token() == token) { 696 it->second.token() == token) {
705 token_cache_.erase(it); 697 token_cache_.erase(it);
706 break; 698 break;
707 } 699 }
708 } 700 }
709 } 701 }
710 702
711 void IdentityAPI::EraseAllCachedTokens() { 703 void IdentityAPI::EraseAllCachedTokens() {
712 token_cache_.clear(); 704 token_cache_.clear();
713 } 705 }
714 706
715 const IdentityTokenCacheValue& IdentityAPI::GetCachedToken( 707 const IdentityTokenCacheValue& IdentityAPI::GetCachedToken(
716 const std::string& extension_id, const std::vector<std::string> scopes) { 708 const ExtensionTokenKey& key) {
717 std::set<std::string> scopeset(scopes.begin(), scopes.end());
718 TokenCacheKey key(extension_id, scopeset);
719 return token_cache_[key]; 709 return token_cache_[key];
720 } 710 }
721 711
722 const IdentityAPI::CachedTokens& IdentityAPI::GetAllCachedTokens() { 712 const IdentityAPI::CachedTokens& IdentityAPI::GetAllCachedTokens() {
723 return token_cache_; 713 return token_cache_;
724 } 714 }
725 715
726 void IdentityAPI::ReportAuthError(const GoogleServiceAuthError& error) { 716 void IdentityAPI::ReportAuthError(const GoogleServiceAuthError& error) {
727 ProfileOAuth2TokenService* token_service = 717 ProfileOAuth2TokenService* token_service =
728 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); 718 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
(...skipping 29 matching lines...) Expand all
758 748
759 ExtensionSystem::Get(profile_)->event_router()->BroadcastEvent(event.Pass()); 749 ExtensionSystem::Get(profile_)->event_router()->BroadcastEvent(event.Pass());
760 } 750 }
761 751
762 template <> 752 template <>
763 void ProfileKeyedAPIFactory<IdentityAPI>::DeclareFactoryDependencies() { 753 void ProfileKeyedAPIFactory<IdentityAPI>::DeclareFactoryDependencies() {
764 DependsOn(ExtensionSystemFactory::GetInstance()); 754 DependsOn(ExtensionSystemFactory::GetInstance());
765 DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance()); 755 DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance());
766 } 756 }
767 757
768 IdentityAPI::TokenCacheKey::TokenCacheKey(const std::string& extension_id,
769 const std::set<std::string> scopes)
770 : extension_id(extension_id),
771 scopes(scopes) {
772 }
773
774 IdentityAPI::TokenCacheKey::~TokenCacheKey() {
775 }
776
777 bool IdentityAPI::TokenCacheKey::operator<(
778 const IdentityAPI::TokenCacheKey& rhs) const {
779 if (extension_id < rhs.extension_id)
780 return true;
781 else if (rhs.extension_id < extension_id)
782 return false;
783
784 return scopes < rhs.scopes;
785 }
786
787 } // namespace extensions 758 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698