summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-03 17:53:37 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-03 17:53:37 +0000
commitf746b3f2db3603c6f0567b9f68ac9d0b2d393e7c (patch)
treef5f00bba897bd8dc3459ca58aaf551974393ebb9 /chrome/browser/extensions
parentbff93023230accd34f32443857b88ab17e1d9a0b (diff)
downloadchromium_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')
-rw-r--r--chrome/browser/extensions/api/identity/identity_api.cc104
-rw-r--r--chrome/browser/extensions/api/identity/identity_api.h16
-rw-r--r--chrome/browser/extensions/extension_install_prompt.cc20
-rw-r--r--chrome/browser/extensions/extension_install_prompt.h8
-rw-r--r--chrome/browser/extensions/permissions_updater.cc14
-rw-r--r--chrome/browser/extensions/permissions_updater.h3
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);