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

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

Issue 2668203004: Move impl of identity.GetAuthToken() extension API to its own file (Closed)
Patch Set: Created 3 years, 10 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 (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 <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <set> 10 #include <set>
(...skipping 29 matching lines...) Expand all
40 #include "extensions/browser/event_router.h" 40 #include "extensions/browser/event_router.h"
41 #include "extensions/browser/extension_function_dispatcher.h" 41 #include "extensions/browser/extension_function_dispatcher.h"
42 #include "extensions/common/extension.h" 42 #include "extensions/common/extension.h"
43 #include "extensions/common/extension_l10n_util.h" 43 #include "extensions/common/extension_l10n_util.h"
44 #include "extensions/common/manifest_handlers/oauth2_manifest_handler.h" 44 #include "extensions/common/manifest_handlers/oauth2_manifest_handler.h"
45 #include "extensions/common/permissions/permission_set.h" 45 #include "extensions/common/permissions/permission_set.h"
46 #include "extensions/common/permissions/permissions_data.h" 46 #include "extensions/common/permissions/permissions_data.h"
47 #include "google_apis/gaia/gaia_urls.h" 47 #include "google_apis/gaia/gaia_urls.h"
48 #include "url/gurl.h" 48 #include "url/gurl.h"
49 49
50 #if defined(OS_CHROMEOS)
51 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
52 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
53 #include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
54 #include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h "
55 #include "components/user_manager/user_manager.h"
56 #include "google_apis/gaia/gaia_constants.h"
57 #endif
58
59 namespace extensions { 50 namespace extensions {
60 51
61 namespace {
62
63 #if defined(OS_CHROMEOS)
64 // The list of apps that are allowed to use the Identity API to retrieve the
65 // token from the device robot account in a public session.
66 const char* const kPublicSessionAllowedOrigins[] = {
67 // Chrome Remote Desktop - Chromium branding.
68 "chrome-extension://ljacajndfccfgnfohlgkdphmbnpkjflk/",
69 // Chrome Remote Desktop - Official branding.
70 "chrome-extension://gbchcmhmhahfdphkhkmpfmihenigjmpp/"};
71 #endif
72
73 std::string GetPrimaryAccountId(content::BrowserContext* context) {
74 SigninManagerBase* signin_manager =
75 SigninManagerFactory::GetForProfile(Profile::FromBrowserContext(context));
76 return signin_manager->GetAuthenticatedAccountId();
77 }
78
79 } // namespace
80
81 namespace identity = api::identity; 52 namespace identity = api::identity;
82 53
83 IdentityTokenCacheValue::IdentityTokenCacheValue() 54 IdentityTokenCacheValue::IdentityTokenCacheValue()
84 : status_(CACHE_STATUS_NOTFOUND) {} 55 : status_(CACHE_STATUS_NOTFOUND) {}
85 56
86 IdentityTokenCacheValue::IdentityTokenCacheValue( 57 IdentityTokenCacheValue::IdentityTokenCacheValue(
87 const IssueAdviceInfo& issue_advice) 58 const IssueAdviceInfo& issue_advice)
88 : status_(CACHE_STATUS_ADVICE), issue_advice_(issue_advice) { 59 : status_(CACHE_STATUS_ADVICE), issue_advice_(issue_advice) {
89 expiration_time_ = 60 expiration_time_ =
90 base::Time::Now() + base::TimeDelta::FromSeconds( 61 base::Time::Now() + base::TimeDelta::FromSeconds(
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 const IdentityTokenCacheValue& IdentityAPI::GetCachedToken( 150 const IdentityTokenCacheValue& IdentityAPI::GetCachedToken(
180 const ExtensionTokenKey& key) { 151 const ExtensionTokenKey& key) {
181 return token_cache_[key]; 152 return token_cache_[key];
182 } 153 }
183 154
184 const IdentityAPI::CachedTokens& IdentityAPI::GetAllCachedTokens() { 155 const IdentityAPI::CachedTokens& IdentityAPI::GetAllCachedTokens() {
185 return token_cache_; 156 return token_cache_;
186 } 157 }
187 158
188 std::vector<std::string> IdentityAPI::GetAccounts() const { 159 std::vector<std::string> IdentityAPI::GetAccounts() const {
189 const std::string primary_account_id = GetPrimaryAccountId(browser_context_);
190 const std::vector<gaia::AccountIds> ids = account_tracker_.GetAccounts(); 160 const std::vector<gaia::AccountIds> ids = account_tracker_.GetAccounts();
191 std::vector<std::string> gaia_ids; 161 std::vector<std::string> gaia_ids;
192 162
193 if (switches::IsExtensionsMultiAccount()) { 163 if (switches::IsExtensionsMultiAccount()) {
194 for (std::vector<gaia::AccountIds>::const_iterator it = ids.begin(); 164 for (std::vector<gaia::AccountIds>::const_iterator it = ids.begin();
195 it != ids.end(); 165 it != ids.end();
196 ++it) { 166 ++it) {
197 gaia_ids.push_back(it->gaia); 167 gaia_ids.push_back(it->gaia);
198 } 168 }
199 } else if (ids.size() >= 1) { 169 } else if (ids.size() >= 1) {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 it != gaia_ids.end(); 245 it != gaia_ids.end();
276 ++it) { 246 ++it) {
277 api::identity::AccountInfo account_info; 247 api::identity::AccountInfo account_info;
278 account_info.id = *it; 248 account_info.id = *it;
279 infos->Append(account_info.ToValue()); 249 infos->Append(account_info.ToValue());
280 } 250 }
281 251
282 return RespondNow(OneArgument(std::move(infos))); 252 return RespondNow(OneArgument(std::move(infos)));
283 } 253 }
284 254
285 IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction()
286 : OAuth2TokenService::Consumer("extensions_identity_api"),
287 interactive_(false),
288 should_prompt_for_scopes_(false),
289 should_prompt_for_signin_(false) {
290 }
291
292 IdentityGetAuthTokenFunction::~IdentityGetAuthTokenFunction() {
293 TRACE_EVENT_ASYNC_END0("identity", "IdentityGetAuthTokenFunction", this);
294 }
295
296 bool IdentityGetAuthTokenFunction::RunAsync() {
297 TRACE_EVENT_ASYNC_BEGIN1("identity",
298 "IdentityGetAuthTokenFunction",
299 this,
300 "extension",
301 extension()->id());
302
303 if (GetProfile()->IsOffTheRecord()) {
304 error_ = identity_constants::kOffTheRecord;
305 return false;
306 }
307
308 std::unique_ptr<identity::GetAuthToken::Params> params(
309 identity::GetAuthToken::Params::Create(*args_));
310 EXTENSION_FUNCTION_VALIDATE(params.get());
311 interactive_ = params->details.get() &&
312 params->details->interactive.get() &&
313 *params->details->interactive;
314
315 should_prompt_for_scopes_ = interactive_;
316 should_prompt_for_signin_ = interactive_;
317
318 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension());
319
320 // Check that the necessary information is present in the manifest.
321 oauth2_client_id_ = GetOAuth2ClientId();
322 if (oauth2_client_id_.empty()) {
323 error_ = identity_constants::kInvalidClientId;
324 return false;
325 }
326
327 std::set<std::string> scopes(oauth2_info.scopes.begin(),
328 oauth2_info.scopes.end());
329
330 std::string account_key = GetPrimaryAccountId(GetProfile());
331
332 if (params->details.get()) {
333 if (params->details->account.get()) {
334 std::string detail_key =
335 extensions::IdentityAPI::GetFactoryInstance()
336 ->Get(GetProfile())
337 ->FindAccountKeyByGaiaId(params->details->account->id);
338
339 if (detail_key != account_key) {
340 if (detail_key.empty() || !switches::IsExtensionsMultiAccount()) {
341 // TODO(courage): should this be a different error?
342 error_ = identity_constants::kUserNotSignedIn;
343 return false;
344 }
345
346 account_key = detail_key;
347 }
348 }
349
350 if (params->details->scopes.get()) {
351 scopes = std::set<std::string>(params->details->scopes->begin(),
352 params->details->scopes->end());
353 }
354 }
355
356 if (scopes.size() == 0) {
357 error_ = identity_constants::kInvalidScopes;
358 return false;
359 }
360
361 token_key_.reset(
362 new ExtensionTokenKey(extension()->id(), account_key, scopes));
363
364 // From here on out, results must be returned asynchronously.
365 StartAsyncRun();
366
367 #if defined(OS_CHROMEOS)
368 policy::BrowserPolicyConnectorChromeOS* connector =
369 g_browser_process->platform_part()->browser_policy_connector_chromeos();
370 bool is_kiosk = user_manager::UserManager::Get()->IsLoggedInAsKioskApp();
371 bool is_public_session =
372 user_manager::UserManager::Get()->IsLoggedInAsPublicAccount();
373
374 if (connector->IsEnterpriseManaged() && (is_kiosk || is_public_session)) {
375 if (is_public_session && !IsOriginWhitelistedInPublicSession()) {
376 CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
377 return true;
378 }
379
380 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
381 return true;
382 }
383 #endif
384
385 if (!HasLoginToken()) {
386 if (!should_prompt_for_signin_) {
387 CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
388 return true;
389 }
390 // Display a login prompt.
391 StartSigninFlow();
392 } else {
393 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
394 }
395
396 return true;
397 }
398
399 void IdentityGetAuthTokenFunction::StartAsyncRun() {
400 // Balanced in CompleteAsyncRun
401 AddRef();
402 extensions::IdentityAPI::GetFactoryInstance()
403 ->Get(GetProfile())
404 ->set_get_auth_token_function(this);
405 }
406
407 void IdentityGetAuthTokenFunction::CompleteAsyncRun(bool success) {
408 extensions::IdentityAPI::GetFactoryInstance()
409 ->Get(GetProfile())
410 ->set_get_auth_token_function(nullptr);
411
412 SendResponse(success);
413 Release(); // Balanced in StartAsyncRun
414 }
415
416 void IdentityGetAuthTokenFunction::CompleteFunctionWithResult(
417 const std::string& access_token) {
418 SetResult(base::MakeUnique<base::StringValue>(access_token));
419 CompleteAsyncRun(true);
420 }
421
422 void IdentityGetAuthTokenFunction::CompleteFunctionWithError(
423 const std::string& error) {
424 TRACE_EVENT_ASYNC_STEP_PAST1("identity",
425 "IdentityGetAuthTokenFunction",
426 this,
427 "CompleteFunctionWithError",
428 "error",
429 error);
430 error_ = error;
431 CompleteAsyncRun(false);
432 }
433
434 void IdentityGetAuthTokenFunction::StartSigninFlow() {
435 // All cached tokens are invalid because the user is not signed in.
436 IdentityAPI* id_api =
437 extensions::IdentityAPI::GetFactoryInstance()->Get(GetProfile());
438 id_api->EraseAllCachedTokens();
439 // Display a login prompt. If the subsequent mint fails, don't display the
440 // login prompt again.
441 should_prompt_for_signin_ = false;
442 ShowLoginPopup();
443 }
444
445 void IdentityGetAuthTokenFunction::StartMintTokenFlow(
446 IdentityMintRequestQueue::MintType type) {
447 mint_token_flow_type_ = type;
448
449 // Flows are serialized to prevent excessive traffic to GAIA, and
450 // to consolidate UI pop-ups.
451 IdentityAPI* id_api =
452 extensions::IdentityAPI::GetFactoryInstance()->Get(GetProfile());
453
454 if (!should_prompt_for_scopes_) {
455 // Caller requested no interaction.
456
457 if (type == IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE) {
458 // GAIA told us to do a consent UI.
459 CompleteFunctionWithError(identity_constants::kNoGrant);
460 return;
461 }
462 if (!id_api->mint_queue()->empty(
463 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE, *token_key_)) {
464 // Another call is going through a consent UI.
465 CompleteFunctionWithError(identity_constants::kNoGrant);
466 return;
467 }
468 }
469 id_api->mint_queue()->RequestStart(type, *token_key_, this);
470 }
471
472 void IdentityGetAuthTokenFunction::CompleteMintTokenFlow() {
473 IdentityMintRequestQueue::MintType type = mint_token_flow_type_;
474
475 extensions::IdentityAPI::GetFactoryInstance()
476 ->Get(GetProfile())
477 ->mint_queue()
478 ->RequestComplete(type, *token_key_, this);
479 }
480
481 void IdentityGetAuthTokenFunction::StartMintToken(
482 IdentityMintRequestQueue::MintType type) {
483 TRACE_EVENT_ASYNC_STEP_PAST1("identity",
484 "IdentityGetAuthTokenFunction",
485 this,
486 "StartMintToken",
487 "type",
488 type);
489
490 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension());
491 IdentityAPI* id_api = IdentityAPI::GetFactoryInstance()->Get(GetProfile());
492 IdentityTokenCacheValue cache_entry = id_api->GetCachedToken(*token_key_);
493 IdentityTokenCacheValue::CacheValueStatus cache_status =
494 cache_entry.status();
495
496 if (type == IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE) {
497 switch (cache_status) {
498 case IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND:
499 #if defined(OS_CHROMEOS)
500 // Always force minting token for ChromeOS kiosk app and public session.
501 if (user_manager::UserManager::Get()->IsLoggedInAsPublicAccount() &&
502 !IsOriginWhitelistedInPublicSession()) {
503 CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
504 return;
505 }
506
507 if (user_manager::UserManager::Get()->IsLoggedInAsKioskApp() ||
508 user_manager::UserManager::Get()->IsLoggedInAsPublicAccount()) {
509 gaia_mint_token_mode_ = OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE;
510 policy::BrowserPolicyConnectorChromeOS* connector =
511 g_browser_process->platform_part()
512 ->browser_policy_connector_chromeos();
513 if (connector->IsEnterpriseManaged()) {
514 StartDeviceLoginAccessTokenRequest();
515 } else {
516 StartLoginAccessTokenRequest();
517 }
518 return;
519 }
520 #endif
521
522 if (oauth2_info.auto_approve)
523 // oauth2_info.auto_approve is protected by a whitelist in
524 // _manifest_features.json hence only selected extensions take
525 // advantage of forcefully minting the token.
526 gaia_mint_token_mode_ = OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE;
527 else
528 gaia_mint_token_mode_ = OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE;
529 StartLoginAccessTokenRequest();
530 break;
531
532 case IdentityTokenCacheValue::CACHE_STATUS_TOKEN:
533 CompleteMintTokenFlow();
534 CompleteFunctionWithResult(cache_entry.token());
535 break;
536
537 case IdentityTokenCacheValue::CACHE_STATUS_ADVICE:
538 CompleteMintTokenFlow();
539 should_prompt_for_signin_ = false;
540 issue_advice_ = cache_entry.issue_advice();
541 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
542 break;
543 }
544 } else {
545 DCHECK(type == IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
546
547 if (cache_status == IdentityTokenCacheValue::CACHE_STATUS_TOKEN) {
548 CompleteMintTokenFlow();
549 CompleteFunctionWithResult(cache_entry.token());
550 } else {
551 ShowOAuthApprovalDialog(issue_advice_);
552 }
553 }
554 }
555
556 void IdentityGetAuthTokenFunction::OnMintTokenSuccess(
557 const std::string& access_token, int time_to_live) {
558 TRACE_EVENT_ASYNC_STEP_PAST0("identity",
559 "IdentityGetAuthTokenFunction",
560 this,
561 "OnMintTokenSuccess");
562
563 IdentityTokenCacheValue token(access_token,
564 base::TimeDelta::FromSeconds(time_to_live));
565 IdentityAPI::GetFactoryInstance()->Get(GetProfile())->SetCachedToken(
566 *token_key_, token);
567
568 CompleteMintTokenFlow();
569 CompleteFunctionWithResult(access_token);
570 }
571
572 void IdentityGetAuthTokenFunction::OnMintTokenFailure(
573 const GoogleServiceAuthError& error) {
574 TRACE_EVENT_ASYNC_STEP_PAST1("identity",
575 "IdentityGetAuthTokenFunction",
576 this,
577 "OnMintTokenFailure",
578 "error",
579 error.ToString());
580 CompleteMintTokenFlow();
581 switch (error.state()) {
582 case GoogleServiceAuthError::SERVICE_ERROR:
583 if (interactive_) {
584 StartSigninFlow();
585 return;
586 }
587 break;
588 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
589 case GoogleServiceAuthError::ACCOUNT_DELETED:
590 case GoogleServiceAuthError::ACCOUNT_DISABLED:
591 // TODO(courage): flush ticket and retry once
592 if (should_prompt_for_signin_) {
593 // Display a login prompt and try again (once).
594 StartSigninFlow();
595 return;
596 }
597 break;
598 default:
599 // Return error to caller.
600 break;
601 }
602
603 CompleteFunctionWithError(
604 std::string(identity_constants::kAuthFailure) + error.ToString());
605 }
606
607 void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess(
608 const IssueAdviceInfo& issue_advice) {
609 TRACE_EVENT_ASYNC_STEP_PAST0("identity",
610 "IdentityGetAuthTokenFunction",
611 this,
612 "OnIssueAdviceSuccess");
613
614 IdentityAPI::GetFactoryInstance()->Get(GetProfile())->SetCachedToken(
615 *token_key_, IdentityTokenCacheValue(issue_advice));
616 CompleteMintTokenFlow();
617
618 should_prompt_for_signin_ = false;
619 // Existing grant was revoked and we used NO_FORCE, so we got info back
620 // instead. Start a consent UI if we can.
621 issue_advice_ = issue_advice;
622 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
623 }
624
625 void IdentityGetAuthTokenFunction::SigninSuccess() {
626 TRACE_EVENT_ASYNC_STEP_PAST0("identity",
627 "IdentityGetAuthTokenFunction",
628 this,
629 "SigninSuccess");
630
631 // If there was no account associated this profile before the
632 // sign-in, we may not have an account_id in the token_key yet.
633 if (token_key_->account_id.empty()) {
634 token_key_->account_id = GetPrimaryAccountId(GetProfile());
635 }
636
637 StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
638 }
639
640 void IdentityGetAuthTokenFunction::SigninFailed() {
641 TRACE_EVENT_ASYNC_STEP_PAST0("identity",
642 "IdentityGetAuthTokenFunction",
643 this,
644 "SigninFailed");
645 CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
646 }
647
648 void IdentityGetAuthTokenFunction::OnGaiaFlowFailure(
649 GaiaWebAuthFlow::Failure failure,
650 GoogleServiceAuthError service_error,
651 const std::string& oauth_error) {
652 CompleteMintTokenFlow();
653 std::string error;
654
655 switch (failure) {
656 case GaiaWebAuthFlow::WINDOW_CLOSED:
657 error = identity_constants::kUserRejected;
658 break;
659
660 case GaiaWebAuthFlow::INVALID_REDIRECT:
661 error = identity_constants::kInvalidRedirect;
662 break;
663
664 case GaiaWebAuthFlow::SERVICE_AUTH_ERROR:
665 // If this is really an authentication error and not just a transient
666 // network error, and this is an interactive request for a signed-in
667 // user, then we show signin UI instead of failing.
668 if (service_error.state() != GoogleServiceAuthError::CONNECTION_FAILED &&
669 service_error.state() !=
670 GoogleServiceAuthError::SERVICE_UNAVAILABLE &&
671 interactive_ && HasLoginToken()) {
672 StartSigninFlow();
673 return;
674 }
675 error = std::string(identity_constants::kAuthFailure) +
676 service_error.ToString();
677 break;
678
679 case GaiaWebAuthFlow::OAUTH_ERROR:
680 error = MapOAuth2ErrorToDescription(oauth_error);
681 break;
682
683 case GaiaWebAuthFlow::LOAD_FAILED:
684 error = identity_constants::kPageLoadFailure;
685 break;
686
687 default:
688 NOTREACHED() << "Unexpected error from gaia web auth flow: " << failure;
689 error = identity_constants::kInvalidRedirect;
690 break;
691 }
692
693 CompleteFunctionWithError(error);
694 }
695
696 void IdentityGetAuthTokenFunction::OnGaiaFlowCompleted(
697 const std::string& access_token,
698 const std::string& expiration) {
699 TRACE_EVENT_ASYNC_STEP_PAST0("identity",
700 "IdentityGetAuthTokenFunction",
701 this,
702 "OnGaiaFlowCompleted");
703 int time_to_live;
704 if (!expiration.empty() && base::StringToInt(expiration, &time_to_live)) {
705 IdentityTokenCacheValue token_value(
706 access_token, base::TimeDelta::FromSeconds(time_to_live));
707 IdentityAPI::GetFactoryInstance()->Get(GetProfile())->SetCachedToken(
708 *token_key_, token_value);
709 }
710
711 CompleteMintTokenFlow();
712 CompleteFunctionWithResult(access_token);
713 }
714
715 void IdentityGetAuthTokenFunction::OnGetTokenSuccess(
716 const OAuth2TokenService::Request* request,
717 const std::string& access_token,
718 const base::Time& expiration_time) {
719 TRACE_EVENT_ASYNC_STEP_PAST1("identity",
720 "IdentityGetAuthTokenFunction",
721 this,
722 "OnGetTokenSuccess",
723 "account",
724 request->GetAccountId());
725 login_token_request_.reset();
726 StartGaiaRequest(access_token);
727 }
728
729 void IdentityGetAuthTokenFunction::OnGetTokenFailure(
730 const OAuth2TokenService::Request* request,
731 const GoogleServiceAuthError& error) {
732 TRACE_EVENT_ASYNC_STEP_PAST1("identity",
733 "IdentityGetAuthTokenFunction",
734 this,
735 "OnGetTokenFailure",
736 "error",
737 error.ToString());
738 login_token_request_.reset();
739 OnGaiaFlowFailure(GaiaWebAuthFlow::SERVICE_AUTH_ERROR, error, std::string());
740 }
741
742 void IdentityGetAuthTokenFunction::Shutdown() {
743 gaia_web_auth_flow_.reset();
744 signin_flow_.reset();
745 login_token_request_.reset();
746 extensions::IdentityAPI::GetFactoryInstance()
747 ->Get(GetProfile())
748 ->mint_queue()
749 ->RequestCancel(*token_key_, this);
750 CompleteFunctionWithError(identity_constants::kCanceled);
751 }
752
753 #if defined(OS_CHROMEOS)
754 void IdentityGetAuthTokenFunction::StartDeviceLoginAccessTokenRequest() {
755 chromeos::DeviceOAuth2TokenService* service =
756 chromeos::DeviceOAuth2TokenServiceFactory::Get();
757 // Since robot account refresh tokens are scoped down to [any-api] only,
758 // request access token for [any-api] instead of login.
759 OAuth2TokenService::ScopeSet scopes;
760 scopes.insert(GaiaConstants::kAnyApiOAuth2Scope);
761 login_token_request_ =
762 service->StartRequest(service->GetRobotAccountId(),
763 scopes,
764 this);
765 }
766
767 bool IdentityGetAuthTokenFunction::IsOriginWhitelistedInPublicSession() {
768 DCHECK(extension());
769 GURL extension_url = extension()->url();
770 for (size_t i = 0; i < arraysize(kPublicSessionAllowedOrigins); i++) {
771 URLPattern allowed_origin(URLPattern::SCHEME_ALL,
772 kPublicSessionAllowedOrigins[i]);
773 if (allowed_origin.MatchesSecurityOrigin(extension_url)) {
774 return true;
775 }
776 }
777 return false;
778 }
779 #endif
780
781 void IdentityGetAuthTokenFunction::StartLoginAccessTokenRequest() {
782 ProfileOAuth2TokenService* service =
783 ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile());
784 #if defined(OS_CHROMEOS)
785 if (chrome::IsRunningInForcedAppMode()) {
786 std::string app_client_id;
787 std::string app_client_secret;
788 if (chromeos::UserSessionManager::GetInstance()->
789 GetAppModeChromeClientOAuthInfo(&app_client_id,
790 &app_client_secret)) {
791 login_token_request_ =
792 service->StartRequestForClient(token_key_->account_id,
793 app_client_id,
794 app_client_secret,
795 OAuth2TokenService::ScopeSet(),
796 this);
797 return;
798 }
799 }
800 #endif
801 login_token_request_ = service->StartRequest(
802 token_key_->account_id, OAuth2TokenService::ScopeSet(), this);
803 }
804
805 void IdentityGetAuthTokenFunction::StartGaiaRequest(
806 const std::string& login_access_token) {
807 DCHECK(!login_access_token.empty());
808 mint_token_flow_.reset(CreateMintTokenFlow());
809 mint_token_flow_->Start(GetProfile()->GetRequestContext(),
810 login_access_token);
811 }
812
813 void IdentityGetAuthTokenFunction::ShowLoginPopup() {
814 signin_flow_.reset(new IdentitySigninFlow(this, GetProfile()));
815 signin_flow_->Start();
816 }
817
818 void IdentityGetAuthTokenFunction::ShowOAuthApprovalDialog(
819 const IssueAdviceInfo& issue_advice) {
820 const std::string locale = extension_l10n_util::CurrentLocaleOrDefault();
821
822 gaia_web_auth_flow_.reset(new GaiaWebAuthFlow(
823 this, GetProfile(), token_key_.get(), oauth2_client_id_, locale));
824 gaia_web_auth_flow_->Start();
825 }
826
827 OAuth2MintTokenFlow* IdentityGetAuthTokenFunction::CreateMintTokenFlow() {
828 SigninClient* signin_client =
829 ChromeSigninClientFactory::GetForProfile(GetProfile());
830 std::string signin_scoped_device_id =
831 signin_client->GetSigninScopedDeviceId();
832 OAuth2MintTokenFlow* mint_token_flow = new OAuth2MintTokenFlow(
833 this,
834 OAuth2MintTokenFlow::Parameters(
835 extension()->id(),
836 oauth2_client_id_,
837 std::vector<std::string>(token_key_->scopes.begin(),
838 token_key_->scopes.end()),
839 signin_scoped_device_id,
840 gaia_mint_token_mode_));
841 return mint_token_flow;
842 }
843
844 bool IdentityGetAuthTokenFunction::HasLoginToken() const {
845 ProfileOAuth2TokenService* token_service =
846 ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile());
847 return token_service->RefreshTokenIsAvailable(token_key_->account_id);
848 }
849
850 std::string IdentityGetAuthTokenFunction::MapOAuth2ErrorToDescription(
851 const std::string& error) {
852 const char kOAuth2ErrorAccessDenied[] = "access_denied";
853 const char kOAuth2ErrorInvalidScope[] = "invalid_scope";
854
855 if (error == kOAuth2ErrorAccessDenied)
856 return std::string(identity_constants::kUserRejected);
857 else if (error == kOAuth2ErrorInvalidScope)
858 return std::string(identity_constants::kInvalidScopes);
859 else
860 return std::string(identity_constants::kAuthFailure) + error;
861 }
862
863 std::string IdentityGetAuthTokenFunction::GetOAuth2ClientId() const {
864 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension());
865 std::string client_id = oauth2_info.client_id;
866
867 // Component apps using auto_approve may use Chrome's client ID by
868 // omitting the field.
869 if (client_id.empty() && extension()->location() == Manifest::COMPONENT &&
870 oauth2_info.auto_approve) {
871 client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
872 }
873 return client_id;
874 }
875
876 } // namespace extensions 255 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/api/identity/identity_api.h ('k') | chrome/browser/extensions/api/identity/identity_apitest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698