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 |