| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |