Index: chrome/browser/extensions/api/identity/identity_api.cc |
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc |
index f51f71c4bf3aba49d56c4bc3d50c6933c489174f..479728cb0ee2e8d383f361988b24ff6f129dc5b1 100644 |
--- a/chrome/browser/extensions/api/identity/identity_api.cc |
+++ b/chrome/browser/extensions/api/identity/identity_api.cc |
@@ -4,6 +4,10 @@ |
#include "chrome/browser/extensions/api/identity/identity_api.h" |
+#include <set> |
+#include <string> |
+#include <vector> |
+ |
#include "base/lazy_instance.h" |
#include "base/stringprintf.h" |
#include "base/values.h" |
@@ -60,6 +64,7 @@ namespace identity = api::experimental_identity; |
IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction() |
: should_prompt_for_scopes_(false), |
should_prompt_for_signin_(false) {} |
+ |
IdentityGetAuthTokenFunction::~IdentityGetAuthTokenFunction() {} |
bool IdentityGetAuthTokenFunction::RunImpl() { |
@@ -85,8 +90,7 @@ bool IdentityGetAuthTokenFunction::RunImpl() { |
return false; |
} |
- // Balanced in OnIssueAdviceSuccess|OnMintTokenSuccess|OnMintTokenFailure| |
- // InstallUIAbort|SigninFailed. |
+ // Balanced in CompleteFunctionWithResult|CompleteFunctionWithError |
AddRef(); |
if (!HasLoginToken()) { |
@@ -95,28 +99,107 @@ bool IdentityGetAuthTokenFunction::RunImpl() { |
Release(); |
return false; |
} |
- // Display a login prompt. If the subsequent mint fails, don't display the |
- // prompt again. |
- should_prompt_for_signin_ = false; |
- ShowLoginPopup(); |
+ // Display a login prompt. |
+ StartSigninFlow(); |
} else { |
TokenService* token_service = TokenServiceFactory::GetForProfile(profile()); |
refresh_token_ = token_service->GetOAuth2LoginRefreshToken(); |
- StartFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE); |
+ StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE); |
} |
return true; |
} |
-void IdentityGetAuthTokenFunction::OnMintTokenSuccess( |
+void IdentityGetAuthTokenFunction::CompleteFunctionWithResult( |
const std::string& access_token) { |
SetResult(Value::CreateStringValue(access_token)); |
SendResponse(true); |
Release(); // Balanced in RunImpl. |
} |
+void IdentityGetAuthTokenFunction::CompleteFunctionWithError( |
+ const std::string& error) { |
+ error_ = error; |
+ SendResponse(false); |
+ Release(); // Balanced in RunImpl. |
+} |
+ |
+void IdentityGetAuthTokenFunction::StartSigninFlow() { |
+ // Display a login prompt. If the subsequent mint fails, don't display the |
+ // login prompt again. |
+ should_prompt_for_signin_ = false; |
+ ShowLoginPopup(); |
+} |
+ |
+void IdentityGetAuthTokenFunction::StartMintTokenFlow( |
+ IdentityMintRequestQueue::MintType type) { |
+ mint_token_flow_type_ = type; |
+ |
+ // Flows are serialized to prevent excessive traffic to GAIA, and |
+ // to consolidate UI pop-ups. |
+ const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension()); |
+ std::set<std::string> scopes(oauth2_info.scopes.begin(), |
+ oauth2_info.scopes.end()); |
+ IdentityAPI* id_api = |
+ extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(profile_); |
+ |
+ // If there is an interactive flow in progress, non-interactive |
+ // requests should complete immediately since a consent UI is |
+ // known to be required. |
+ if (!should_prompt_for_scopes_ && !id_api->mint_queue()->empty( |
+ IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE, |
+ GetExtension()->id(), scopes)) { |
+ CompleteFunctionWithError(identity_constants::kNoGrant); |
+ return; |
+ } |
+ id_api->mint_queue()->RequestStart(type, |
+ GetExtension()->id(), |
+ scopes, |
+ this); |
+} |
+ |
+void IdentityGetAuthTokenFunction::CompleteMintTokenFlow() { |
+ IdentityMintRequestQueue::MintType type = mint_token_flow_type_; |
+ |
+ const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension()); |
+ std::set<std::string> scopes(oauth2_info.scopes.begin(), |
+ oauth2_info.scopes.end()); |
+ |
+ extensions::IdentityAPI::GetFactoryInstance()->GetForProfile( |
+ profile_)->mint_queue()->RequestComplete(type, |
+ GetExtension()->id(), |
+ scopes, |
+ this); |
+} |
+ |
+void IdentityGetAuthTokenFunction::StartMintToken( |
+ IdentityMintRequestQueue::MintType type) { |
+ switch (type) { |
+ case IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE: |
+ StartGaiaRequest(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE); |
+ break; |
+ |
+ case IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE: |
+ install_ui_.reset(new ExtensionInstallPrompt(GetAssociatedWebContents())); |
+ ShowOAuthApprovalDialog(issue_advice_); |
+ break; |
+ |
+ default: |
+ NOTREACHED() << "Unexepected mint type in StartMintToken: " << type; |
+ break; |
+ }; |
+} |
+ |
+void IdentityGetAuthTokenFunction::OnMintTokenSuccess( |
+ const std::string& access_token) { |
+ CompleteMintTokenFlow(); |
+ CompleteFunctionWithResult(access_token); |
+} |
+ |
void IdentityGetAuthTokenFunction::OnMintTokenFailure( |
const GoogleServiceAuthError& error) { |
+ CompleteMintTokenFlow(); |
+ |
switch (error.state()) { |
case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: |
case GoogleServiceAuthError::ACCOUNT_DELETED: |
@@ -125,8 +208,7 @@ void IdentityGetAuthTokenFunction::OnMintTokenFailure( |
profile())->ReportAuthError(error); |
if (should_prompt_for_signin_) { |
// Display a login prompt and try again (once). |
- should_prompt_for_signin_ = false; |
- ShowLoginPopup(); |
+ StartSigninFlow(); |
return; |
} |
break; |
@@ -135,52 +217,48 @@ void IdentityGetAuthTokenFunction::OnMintTokenFailure( |
break; |
} |
- error_ = std::string(identity_constants::kAuthFailure) + error.ToString(); |
- SendResponse(false); |
- Release(); // Balanced in RunImpl. |
+ CompleteFunctionWithError( |
+ std::string(identity_constants::kAuthFailure) + error.ToString()); |
} |
void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess( |
const IssueAdviceInfo& issue_advice) { |
+ CompleteMintTokenFlow(); |
+ |
should_prompt_for_signin_ = false; |
// Existing grant was revoked and we used NO_FORCE, so we got info back |
// instead. |
if (should_prompt_for_scopes_) { |
- install_ui_.reset(new ExtensionInstallPrompt(GetAssociatedWebContents())); |
- ShowOAuthApprovalDialog(issue_advice); |
+ issue_advice_ = issue_advice; |
+ StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE); |
} else { |
- error_ = identity_constants::kNoGrant; |
- SendResponse(false); |
- Release(); // Balanced in RunImpl. |
+ CompleteFunctionWithError(identity_constants::kNoGrant); |
} |
} |
void IdentityGetAuthTokenFunction::SigninSuccess(const std::string& token) { |
refresh_token_ = token; |
- StartFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE); |
+ StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE); |
} |
void IdentityGetAuthTokenFunction::SigninFailed() { |
- error_ = identity_constants::kUserNotSignedIn; |
- SendResponse(false); |
- Release(); |
+ CompleteFunctionWithError(identity_constants::kUserNotSignedIn); |
} |
void IdentityGetAuthTokenFunction::InstallUIProceed() { |
DCHECK(install_ui_->record_oauth2_grant()); |
// The user has accepted the scopes, so we may now force (recording a grant |
// and receiving a token). |
- StartFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE); |
+ StartGaiaRequest(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE); |
} |
void IdentityGetAuthTokenFunction::InstallUIAbort(bool user_initiated) { |
- error_ = identity_constants::kUserRejected; |
- SendResponse(false); |
- Release(); // Balanced in RunImpl. |
+ CompleteMintTokenFlow(); |
+ CompleteFunctionWithError(identity_constants::kUserRejected); |
} |
-void IdentityGetAuthTokenFunction::StartFlow(OAuth2MintTokenFlow::Mode mode) { |
- signin_flow_.reset(NULL); |
+void IdentityGetAuthTokenFunction::StartGaiaRequest( |
+ OAuth2MintTokenFlow::Mode mode) { |
mint_token_flow_.reset(CreateMintTokenFlow(mode)); |
mint_token_flow_->Start(); |
} |
@@ -339,6 +417,10 @@ void IdentityAPI::Initialize() { |
content::Source<TokenService>(token_service)); |
} |
+IdentityMintRequestQueue* IdentityAPI::mint_queue() { |
+ return &mint_queue_; |
+} |
+ |
void IdentityAPI::ReportAuthError(const GoogleServiceAuthError& error) { |
if (!signin_manager_) |
Initialize(); |