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

Unified Diff: chrome/browser/extensions/api/identity/identity_apitest.cc

Issue 14329014: Identity API: Add token cache and identity.invalidateAuthToken. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rounding third rebase Created 7 years, 8 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/api/identity/identity_apitest.cc
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc
index 9bf130d64a4e7858b8a6ea2d68f6b25545fc91c3..0b04145ad3335ebf92d59ab6815254eac72ebccf 100644
--- a/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -19,6 +19,7 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/test/test_utils.h"
+#include "extensions/common/id_util.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_mint_token_flow.h"
#include "googleurl/src/gurl.h"
@@ -37,6 +38,7 @@ namespace errors = identity_constants;
namespace utils = extension_function_test_utils;
static const char kAccessToken[] = "auth_token";
+static const char kExtensionId[] = "ext_id";
// This helps us be able to wait until an AsyncExtensionFunction calls
// SendResponse.
@@ -158,7 +160,7 @@ class TestOAuth2MintTokenFlow : public OAuth2MintTokenFlow {
break;
}
case MINT_TOKEN_SUCCESS: {
- delegate_->OnMintTokenSuccess(kAccessToken);
+ delegate_->OnMintTokenSuccess(kAccessToken, 3600);
break;
}
case MINT_TOKEN_FAILURE: {
@@ -273,9 +275,9 @@ class GetAuthTokenFunctionTest : public AsyncExtensionBrowserTest {
return ext;
}
- void InitializeTestAPIFactory() {
- IdentityAPI::GetFactoryInstance()->SetTestingFactory(
- browser()->profile(), &IdentityAPITestFactory);
+ IdentityAPI* id_api() {
+ return IdentityAPI::GetFactoryInstance()->GetForProfile(
+ browser()->profile());
}
};
@@ -330,6 +332,28 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
+ NonInteractiveMintAdviceSuccess) {
+ scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
+ func->set_extension(extension);
+ EXPECT_CALL(*func.get(), HasLoginToken())
+ .WillOnce(Return(true));
+ TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
+ TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
+ EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
+ std::string error = utils::RunFunctionAndReturnError(
+ func.get(), "[{}]", browser());
+ EXPECT_TRUE(StartsWithASCII(error, errors::kNoGrant, false));
+ EXPECT_FALSE(func->login_ui_shown());
+ EXPECT_FALSE(func->install_ui_shown());
+
+ const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension);
+ EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_ADVICE,
+ id_api()->GetCachedToken(extension->id(),
+ oauth2_info.scopes).status());
+}
+
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
NonInteractiveMintBadCredentials) {
scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
@@ -348,7 +372,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
NonInteractiveSuccess) {
scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
- func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
+ scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
+ func->set_extension(extension);
+ const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension);
EXPECT_CALL(*func.get(), HasLoginToken())
.WillOnce(Return(true));
TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
@@ -361,6 +387,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(kAccessToken), access_token);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->install_ui_shown());
+ EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
+ id_api()->GetCachedToken(extension->id(),
+ oauth2_info.scopes).status());
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -486,7 +515,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
InteractiveLoginSuccessApprovalDoneMintSuccess) {
scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
- func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
+ scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
+ func->set_extension(extension);
+ const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension);
EXPECT_CALL(*func.get(), HasLoginToken())
.WillOnce(Return(false));
func->set_login_ui_result(true);
@@ -506,6 +537,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(kAccessToken), access_token);
EXPECT_TRUE(func->login_ui_shown());
EXPECT_TRUE(func->install_ui_shown());
+ EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
+ id_api()->GetCachedToken(extension->id(),
+ oauth2_info.scopes).status());
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -572,7 +606,6 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoninteractiveQueue) {
- InitializeTestAPIFactory();
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
func->set_extension(extension);
@@ -615,7 +648,6 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoninteractiveQueue) {
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveQueue) {
- InitializeTestAPIFactory();
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
func->set_extension(extension);
@@ -665,7 +697,6 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveQueue) {
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
InteractiveQueuedNoninteractiveFails) {
- InitializeTestAPIFactory();
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
func->set_extension(extension);
@@ -697,6 +728,196 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
queue->RequestComplete(type, extension->id(), scopes, &queued_request);
}
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
+ NonInteractiveCacheHit) {
+ scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
+ func->set_extension(extension);
+
+ // pre-populate the cache with a token
+ const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension);
+ IdentityTokenCacheValue token(kAccessToken,
+ base::TimeDelta::FromSeconds(3600));
+ id_api()->SetCachedToken(extension->id(), oauth2_info.scopes, token);
+
+ // Get a token. Should not require a GAIA request.
+ EXPECT_CALL(*func.get(), HasLoginToken())
+ .WillOnce(Return(true));
+ scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
+ func.get(), "[{}]", browser()));
+ std::string access_token;
+ EXPECT_TRUE(value->GetAsString(&access_token));
+ EXPECT_EQ(std::string(kAccessToken), access_token);
+ EXPECT_FALSE(func->login_ui_shown());
+ EXPECT_FALSE(func->install_ui_shown());
+}
+
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
+ NonInteractiveIssueAdviceCacheHit) {
+ scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
+ func->set_extension(extension);
+
+ // pre-populate the cache with advice
+ const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension);
+ IssueAdviceInfo info;
+ IdentityTokenCacheValue token(info);
+ id_api()->SetCachedToken(extension->id(), oauth2_info.scopes, token);
+
+ // Should return an error without a GAIA request.
+ EXPECT_CALL(*func.get(), HasLoginToken())
+ .WillOnce(Return(true));
+ std::string error = utils::RunFunctionAndReturnError(
+ func.get(), "[{}]", browser());
+ EXPECT_EQ(std::string(errors::kNoGrant), error);
+ EXPECT_FALSE(func->login_ui_shown());
+ EXPECT_FALSE(func->install_ui_shown());
+}
+
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
+ InteractiveCacheHit) {
+ scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
+ func->set_extension(extension);
+
+ // Create a fake request to block the queue.
+ const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension);
+ std::set<std::string> scopes(oauth2_info.scopes.begin(),
+ oauth2_info.scopes.end());
+ IdentityMintRequestQueue* queue = id_api()->mint_queue();
+ MockQueuedMintRequest queued_request;
+ IdentityMintRequestQueue::MintType type =
+ IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE;
+
+ EXPECT_CALL(queued_request, StartMintToken(type)).Times(1);
+ queue->RequestStart(type, extension->id(), scopes, &queued_request);
+
+ // The real request will start processing, but wait in the queue behind
+ // the blocker.
+ EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(true));
+ TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
+ TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
+ EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
+ RunFunctionAsync(func, "[{\"interactive\": true}]");
+
+ // Populate the cache with a token while the request is blocked.
+ IdentityTokenCacheValue token(kAccessToken,
+ base::TimeDelta::FromSeconds(3600));
+ id_api()->SetCachedToken(extension->id(), oauth2_info.scopes, token);
+
+ // When we wake up the request, it returns the cached token without
+ // displaying a UI, or hitting GAIA.
+
+ queue->RequestComplete(type, extension->id(), scopes, &queued_request);
+
+ scoped_ptr<base::Value> value(WaitForSingleResult(func));
+ std::string access_token;
+ EXPECT_TRUE(value->GetAsString(&access_token));
+ EXPECT_EQ(std::string(kAccessToken), access_token);
+ EXPECT_FALSE(func->login_ui_shown());
+ EXPECT_FALSE(func->install_ui_shown());
+}
+
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
+ LoginInvalidatesTokenCache) {
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
+ scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
+ func->set_extension(extension);
+
+ // pre-populate the cache with a token
+ const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension);
+ IdentityTokenCacheValue token(kAccessToken,
+ base::TimeDelta::FromSeconds(3600));
+ id_api()->SetCachedToken(extension->id(), oauth2_info.scopes, token);
+
+ // Because the user is not signed in, the token will be removed,
+ // and we'll hit GAIA for new tokens.
+ EXPECT_CALL(*func.get(), HasLoginToken())
+ .WillOnce(Return(false));
+ func->set_login_ui_result(true);
+ TestOAuth2MintTokenFlow* flow1 = new TestOAuth2MintTokenFlow(
+ TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
+ TestOAuth2MintTokenFlow* flow2 = new TestOAuth2MintTokenFlow(
+ TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS, func.get());
+ EXPECT_CALL(*func.get(), CreateMintTokenFlow(_))
+ .WillOnce(Return(flow1))
+ .WillOnce(Return(flow2));
+
+ func->set_install_ui_result(true);
+ scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
+ func.get(), "[{\"interactive\": true}]", browser()));
+ std::string access_token;
+ EXPECT_TRUE(value->GetAsString(&access_token));
+ EXPECT_EQ(std::string(kAccessToken), access_token);
+ EXPECT_TRUE(func->login_ui_shown());
+ EXPECT_TRUE(func->install_ui_shown());
+ EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
+ id_api()->GetCachedToken(extension->id(),
+ oauth2_info.scopes).status());
+}
+
+class RemoveCachedAuthTokenFunctionTest : public ExtensionBrowserTest {
+ protected:
+ bool InvalidateDefaultToken() {
+ scoped_refptr<IdentityRemoveCachedAuthTokenFunction> func(
+ new IdentityRemoveCachedAuthTokenFunction);
+ func->set_extension(utils::CreateEmptyExtension(kExtensionId));
+ return utils::RunFunction(
+ func, std::string("[{\"token\": \"") + kAccessToken + "\"}]", browser(),
+ extension_function_test_utils::NONE);
+ }
+
+ IdentityAPI* id_api() {
+ return IdentityAPI::GetFactoryInstance()->GetForProfile(
+ browser()->profile());
+ }
+
+ void SetCachedToken(IdentityTokenCacheValue& token_data) {
+ id_api()->SetCachedToken(extensions::id_util::GenerateId(kExtensionId),
+ std::vector<std::string>(), token_data);
+ }
+
+ const IdentityTokenCacheValue& GetCachedToken() {
+ return id_api()->GetCachedToken(
+ extensions::id_util::GenerateId(kExtensionId),
+ std::vector<std::string>());
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, NotFound) {
+ EXPECT_TRUE(InvalidateDefaultToken());
+ EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND,
+ GetCachedToken().status());
+}
+
+IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, Advice) {
+ IssueAdviceInfo info;
+ IdentityTokenCacheValue advice(info);
+ SetCachedToken(advice);
+ EXPECT_TRUE(InvalidateDefaultToken());
+ EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_ADVICE,
+ GetCachedToken().status());
+}
+
+IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, NonMatchingToken) {
+ IdentityTokenCacheValue token("non_matching_token",
+ base::TimeDelta::FromSeconds(3600));
+ SetCachedToken(token);
+ EXPECT_TRUE(InvalidateDefaultToken());
+ EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
+ GetCachedToken().status());
+ EXPECT_EQ("non_matching_token", GetCachedToken().token());
+}
+
+IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, MatchingToken) {
+ IdentityTokenCacheValue token(kAccessToken,
+ base::TimeDelta::FromSeconds(3600));
+ SetCachedToken(token);
+ EXPECT_TRUE(InvalidateDefaultToken());
+ EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND,
+ GetCachedToken().status());
+}
+
class LaunchWebAuthFlowFunctionTest : public AsyncExtensionBrowserTest {
protected:
void RunAndCheckBounds(
« no previous file with comments | « chrome/browser/extensions/api/identity/identity_api.cc ('k') | chrome/browser/extensions/extension_function_histogram_value.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698