diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-03 17:53:37 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-03 17:53:37 +0000 |
commit | f746b3f2db3603c6f0567b9f68ac9d0b2d393e7c (patch) | |
tree | f5f00bba897bd8dc3459ca58aaf551974393ebb9 /chrome/browser/extensions | |
parent | bff93023230accd34f32443857b88ab17e1d9a0b (diff) | |
download | chromium_src-f746b3f2db3603c6f0567b9f68ac9d0b2d393e7c.zip chromium_src-f746b3f2db3603c6f0567b9f68ac9d0b2d393e7c.tar.gz chromium_src-f746b3f2db3603c6f0567b9f68ac9d0b2d393e7c.tar.bz2 |
make getAuthToken interactive
when interactive is true, and the grant is missing, getAuthToken will pop up a permission confirmation dialog.
BUG=130206
TEST=manual
Review URL: https://chromiumcodereview.appspot.com/10694046
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@145331 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions')
6 files changed, 123 insertions, 42 deletions
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc index 73164ae..7c6cfe9 100644 --- a/chrome/browser/extensions/api/identity/identity_api.cc +++ b/chrome/browser/extensions/api/identity/identity_api.cc @@ -8,6 +8,7 @@ #include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_function_dispatcher.h" #include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/permissions_updater.h" #include "chrome/browser/signin/token_service.h" #include "chrome/browser/signin/token_service_factory.h" #include "chrome/browser/ui/browser.h" @@ -23,45 +24,31 @@ const char kInvalidClientId[] = "Invalid OAuth2 Client ID."; const char kInvalidScopes[] = "Invalid OAuth2 scopes."; const char kInvalidRedirect[] = "Did not redirect to the right URL."; const char kAuthFailure[] = "OAuth2 request failed: "; -const char kGrantRevoked[] = "OAuth2 not granted or revoked."; +const char kNoGrant[] = "OAuth2 not granted or revoked."; +const char kUserRejected[] = "The user did not approve access."; } // namespace -GetAuthTokenFunction::GetAuthTokenFunction() {} +GetAuthTokenFunction::GetAuthTokenFunction() : interactive_(false) {} GetAuthTokenFunction::~GetAuthTokenFunction() {} bool GetAuthTokenFunction::RunImpl() { - const Extension* extension = GetExtension(); - Extension::OAuth2Info oauth2_info = extension->oauth2_info(); - - if (oauth2_info.client_id.empty()) { - error_ = kInvalidClientId; - return false; - } - - if (oauth2_info.scopes.size() == 0) { - error_ = kInvalidScopes; + DictionaryValue* arg = NULL; + EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &arg)); + arg->GetBoolean("interactive", &interactive_); + + // Balanced in OnIssueAdviceSuccess|OnMintTokenSuccess|OnMintTokenFailure| + // InstallUIAbort. + AddRef(); + + if (StartFlow(ExtensionInstallPrompt::ShouldAutomaticallyApproveScopes() ? + OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE : + OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE)) { + return true; + } else { + Release(); return false; } - - AddRef(); // Balanced in OnMintTokenSuccess|Failure. - - TokenService* token_service = TokenServiceFactory::GetForProfile(profile()); - - flow_.reset(new OAuth2MintTokenFlow( - profile()->GetRequestContext(), - this, - OAuth2MintTokenFlow::Parameters( - token_service->GetOAuth2LoginRefreshToken(), - extension->id(), - oauth2_info.client_id, - oauth2_info.scopes, - ExtensionInstallPrompt::ShouldAutomaticallyApproveScopes() ? - OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE : - OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE))); - flow_->Start(); - - return true; } void GetAuthTokenFunction::OnMintTokenSuccess(const std::string& access_token) { @@ -81,21 +68,58 @@ void GetAuthTokenFunction::OnIssueAdviceSuccess( const IssueAdviceInfo& issue_advice) { // Existing grant was revoked and we used NO_FORCE, so we got info back // instead. - error_ = kGrantRevoked; - - // Remove the oauth2 scopes from the extension's granted permissions, if - // revoked server-side. - scoped_refptr<PermissionSet> scopes = - new PermissionSet(GetExtension()->GetActivePermissions()->scopes()); - profile()->GetExtensionService()->extension_prefs()->RemoveGrantedPermissions( - GetExtension()->id(), scopes); + if (interactive_) { + install_ui_.reset(new ExtensionInstallPrompt(GetCurrentBrowser())); + install_ui_->ConfirmIssueAdvice(this, GetExtension(), issue_advice); + } else { + error_ = kNoGrant; + SendResponse(false); + Release(); // Balanced in RunImpl. + } +} - // TODO(estade): need to prompt the user for scope permissions. +void GetAuthTokenFunction::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). + bool success = StartFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE); + DCHECK(success); +} +void GetAuthTokenFunction::InstallUIAbort(bool user_initiated) { + error_ = kUserRejected; SendResponse(false); Release(); // Balanced in RunImpl. } +bool GetAuthTokenFunction::StartFlow(OAuth2MintTokenFlow::Mode mode) { + const Extension* extension = GetExtension(); + Extension::OAuth2Info oauth2_info = extension->oauth2_info(); + + if (oauth2_info.client_id.empty()) { + error_ = kInvalidClientId; + return false; + } + + if (oauth2_info.scopes.size() == 0) { + error_ = kInvalidScopes; + return false; + } + + TokenService* token_service = TokenServiceFactory::GetForProfile(profile()); + flow_.reset(new OAuth2MintTokenFlow( + profile()->GetRequestContext(), + this, + OAuth2MintTokenFlow::Parameters( + token_service->GetOAuth2LoginRefreshToken(), + extension->id(), + oauth2_info.client_id, + oauth2_info.scopes, + mode))); + flow_->Start(); + return true; +} + LaunchWebAuthFlowFunction::LaunchWebAuthFlowFunction() {} LaunchWebAuthFlowFunction::~LaunchWebAuthFlowFunction() {} diff --git a/chrome/browser/extensions/api/identity/identity_api.h b/chrome/browser/extensions/api/identity/identity_api.h index 6a7f65685..74dbeb6 100644 --- a/chrome/browser/extensions/api/identity/identity_api.h +++ b/chrome/browser/extensions/api/identity/identity_api.h @@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/extensions/api/identity/web_auth_flow.h" #include "chrome/browser/extensions/app_notify_channel_setup.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_function.h" #include "chrome/common/net/gaia/oauth2_mint_token_flow.h" @@ -20,7 +21,8 @@ class GoogleServiceAuthError; namespace extensions { class GetAuthTokenFunction : public AsyncExtensionFunction, - public OAuth2MintTokenFlow::Delegate { + public OAuth2MintTokenFlow::Delegate, + public ExtensionInstallPrompt::Delegate { public: DECLARE_EXTENSION_FUNCTION_NAME("experimental.identity.getAuthToken"); @@ -38,7 +40,19 @@ class GetAuthTokenFunction : public AsyncExtensionFunction, virtual void OnIssueAdviceSuccess( const IssueAdviceInfo& issue_advice) OVERRIDE; + // ExtensionInstallPrompt::Delegate implementation: + virtual void InstallUIProceed() OVERRIDE; + virtual void InstallUIAbort(bool user_initiated) OVERRIDE; + + // Starts a MintTokenFlow with the given mode; Returns success. + bool StartFlow(OAuth2MintTokenFlow::Mode mode); + + bool interactive_; scoped_ptr<OAuth2MintTokenFlow> flow_; + + // When launched in interactive mode, and if there is no existing grant, + // a permissions prompt will be popped up to the user. + scoped_ptr<ExtensionInstallPrompt> install_ui_; }; class LaunchWebAuthFlowFunction : public AsyncExtensionFunction, diff --git a/chrome/browser/extensions/extension_install_prompt.cc b/chrome/browser/extensions/extension_install_prompt.cc index 9e6f36e..aade1ec 100644 --- a/chrome/browser/extensions/extension_install_prompt.cc +++ b/chrome/browser/extensions/extension_install_prompt.cc @@ -364,6 +364,21 @@ void ExtensionInstallPrompt::ConfirmPermissions( LoadImageIfNeeded(); } +void ExtensionInstallPrompt::ConfirmIssueAdvice( + Delegate* delegate, + const Extension* extension, + const IssueAdviceInfo& issue_advice) { + DCHECK(ui_loop_ == MessageLoop::current()); + extension_ = extension; + delegate_ = delegate; + prompt_type_ = PERMISSIONS_PROMPT; + + record_oauth2_grant_ = true; + prompt_.SetOAuthIssueAdvice(issue_advice); + + LoadImageIfNeeded(); +} + void ExtensionInstallPrompt::OnInstallSuccess(const Extension* extension, SkBitmap* icon) { extension_ = extension; @@ -411,6 +426,7 @@ void ExtensionInstallPrompt::LoadImageIfNeeded() { void ExtensionInstallPrompt::FetchOAuthIssueAdviceIfNeeded() { const Extension::OAuth2Info& oauth2_info = extension_->oauth2_info(); if (ShouldAutomaticallyApproveScopes() || + prompt_.GetOAuthIssueCount() != 0U || oauth2_info.client_id.empty() || permissions_->scopes().empty() || prompt_type_ == BUNDLE_INSTALL_PROMPT || @@ -450,7 +466,9 @@ void ExtensionInstallPrompt::OnMintTokenFailure( void ExtensionInstallPrompt::ShowConfirmation() { prompt_.set_type(prompt_type_); - prompt_.SetPermissions(permissions_->GetWarningMessages()); + + if (permissions_) + prompt_.SetPermissions(permissions_->GetWarningMessages()); switch (prompt_type_) { case PERMISSIONS_PROMPT: diff --git a/chrome/browser/extensions/extension_install_prompt.h b/chrome/browser/extensions/extension_install_prompt.h index 6437573..4a4d04e 100644 --- a/chrome/browser/extensions/extension_install_prompt.h +++ b/chrome/browser/extensions/extension_install_prompt.h @@ -214,6 +214,14 @@ class ExtensionInstallPrompt : public ImageLoadingTracker::Observer, const extensions::Extension* extension, const extensions::PermissionSet* permissions); + // This is called by the extension identity API to verify whether an + // extension can be granted an OAuth2 token. + // + // We *MUST* eventually call either Proceed() or Abort() on |delegate|. + virtual void ConfirmIssueAdvice(Delegate* delegate, + const extensions::Extension* extension, + const IssueAdviceInfo& issue_advice); + // Installation was successful. This is declared virtual for testing. virtual void OnInstallSuccess(const extensions::Extension* extension, SkBitmap* icon); diff --git a/chrome/browser/extensions/permissions_updater.cc b/chrome/browser/extensions/permissions_updater.cc index c36c641..d2940dd 100644 --- a/chrome/browser/extensions/permissions_updater.cc +++ b/chrome/browser/extensions/permissions_updater.cc @@ -97,6 +97,20 @@ void PermissionsUpdater::GrantActivePermissions(const Extension* extension, GetExtensionPrefs()->AddGrantedPermissions(extension->id(), permissions); } +void PermissionsUpdater::GrantOAuth2Permissions(const Extension* extension) { + CHECK(extension); + + // We only maintain the granted permissions prefs for INTERNAL and LOAD + // extensions. + if (extension->location() != Extension::LOAD && + extension->location() != Extension::INTERNAL) + return; + + scoped_refptr<const PermissionSet> permissions = + new PermissionSet(extension->GetActivePermissions()->scopes()); + GetExtensionPrefs()->AddGrantedPermissions(extension->id(), permissions); +} + void PermissionsUpdater::UpdateActivePermissions( const Extension* extension, const PermissionSet* permissions) { GetExtensionPrefs()->SetActivePermissions(extension->id(), permissions); diff --git a/chrome/browser/extensions/permissions_updater.h b/chrome/browser/extensions/permissions_updater.h index ce601eb..c29b014 100644 --- a/chrome/browser/extensions/permissions_updater.h +++ b/chrome/browser/extensions/permissions_updater.h @@ -45,6 +45,9 @@ class PermissionsUpdater { void GrantActivePermissions(const Extension* extension, bool record_oauth2_grant); + // Grants just the OAuth2 scopes in the extension's active permissions. + void GrantOAuth2Permissions(const Extension* extension); + // Sets the |extension|'s active permissions to |permissions|. void UpdateActivePermissions(const Extension* extension, const PermissionSet* permissions); |