Index: chrome/browser/extensions/api/identity/identity_apitest.cc |
=================================================================== |
--- chrome/browser/extensions/api/identity/identity_apitest.cc (revision 147566) |
+++ chrome/browser/extensions/api/identity/identity_apitest.cc (working copy) |
@@ -2,58 +2,385 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include "base/string_util.h" |
+#include "base/values.h" |
#include "chrome/browser/extensions/api/identity/identity_api.h" |
#include "chrome/browser/extensions/api/identity/web_auth_flow.h" |
#include "chrome/browser/extensions/extension_apitest.h" |
+#include "chrome/browser/extensions/extension_browsertest.h" |
+#include "chrome/browser/extensions/extension_function_test_utils.h" |
+#include "chrome/browser/ui/webui/signin/login_ui_service.h" |
#include "chrome/common/net/gaia/google_service_auth_error.h" |
#include "chrome/common/net/gaia/oauth2_mint_token_flow.h" |
#include "chrome/common/chrome_switches.h" |
+#include "chrome/test/base/in_process_browser_test.h" |
#include "googleurl/src/gurl.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+using extensions::Extension; |
+using extensions::IdentityGetAuthTokenFunction; |
+using testing::_; |
+using testing::Return; |
+using testing::ReturnRef; |
+ |
+namespace utils = extension_function_test_utils; |
+ |
namespace { |
-class IdentityInterceptor : public OAuth2MintTokenFlow::InterceptorForTests { |
+static const char kAccessToken[] = "auth_token"; |
+ |
+class TestLoginUI : public LoginUIService::LoginUI { |
public: |
- IdentityInterceptor() : called_(false) { } |
+ virtual void FocusUI() OVERRIDE {} |
+ virtual void CloseUI() OVERRIDE {} |
+}; |
- virtual bool DoIntercept(const OAuth2MintTokenFlow* flow, |
- std::string* access_token, |
- GoogleServiceAuthError* error) OVERRIDE { |
- *access_token = "auth_token"; |
- called_ = true; |
- return true; |
+class TestOAuth2MintTokenFlow : public OAuth2MintTokenFlow { |
+ public: |
+ enum ResultType { |
+ ISSUE_ADVICE_SUCCESS, |
+ MINT_TOKEN_SUCCESS, |
+ MINT_TOKEN_FAILURE |
+ }; |
+ |
+ TestOAuth2MintTokenFlow(ResultType result, |
+ OAuth2MintTokenFlow::Delegate* delegate) |
+ : OAuth2MintTokenFlow(NULL, delegate, OAuth2MintTokenFlow::Parameters()), |
+ result_(result), |
+ delegate_(delegate) { |
} |
- bool called() const { return called_; } |
+ virtual void Start() OVERRIDE { |
+ switch (result_) { |
+ case ISSUE_ADVICE_SUCCESS: { |
+ IssueAdviceInfo info; |
+ delegate_->OnIssueAdviceSuccess(info); |
+ break; |
+ } |
+ case MINT_TOKEN_SUCCESS: { |
+ delegate_->OnMintTokenSuccess(kAccessToken); |
+ break; |
+ } |
+ case MINT_TOKEN_FAILURE: { |
+ GoogleServiceAuthError error( |
+ GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); |
+ delegate_->OnMintTokenFailure(error); |
+ break; |
+ } |
+ } |
+ } |
private: |
- bool called_; |
+ ResultType result_; |
+ OAuth2MintTokenFlow::Delegate* delegate_; |
}; |
-class WebAuthFlowInterceptor |
- : public extensions::WebAuthFlow::InterceptorForTests { |
+} // namespace |
+ |
+class MockGetAuthTokenFunction : public IdentityGetAuthTokenFunction { |
public: |
- WebAuthFlowInterceptor() : called_(false) { } |
+ MockGetAuthTokenFunction() : install_ui_result_(false), |
+ login_ui_shown_(false), |
+ install_ui_shown_(false) { |
+ } |
- virtual GURL DoIntercept(const GURL& provider_url) OVERRIDE { |
- called_ = true; |
- return GURL("https://abcd.chromiumapp.org/cb#access_token=tok"); |
+ void set_install_ui_result(bool result) { |
+ install_ui_result_ = result; |
} |
- bool called() const { return called_; } |
+ bool login_ui_shown() const { |
+ return login_ui_shown_; |
+ } |
- private: |
- bool called_; |
+ bool install_ui_shown() const { |
+ return install_ui_shown_; |
+ } |
+ |
+ virtual void StartObservingLoginService() OVERRIDE { |
+ // Do nothing in tests. |
+ } |
+ virtual void StopObservingLoginService() OVERRIDE { |
+ // Do nothing in tests. |
+ } |
+ |
+ virtual void ShowLoginPopup() OVERRIDE { |
+ login_ui_shown_ = true; |
+ // Explicitly call OnLoginUIClosed. |
+ TestLoginUI login_ui;; |
+ OnLoginUIClosed(&login_ui); |
+ } |
+ |
+ virtual void ShowOAuthApprovalDialog( |
+ const IssueAdviceInfo& issue_advice) OVERRIDE { |
+ install_ui_shown_ = true; |
+ // Call InstallUIProceed or InstallUIAbort based on the flag. |
+ if (install_ui_result_) |
+ InstallUIProceed(); |
+ else |
+ InstallUIAbort(true); |
+ } |
+ |
+ MOCK_CONST_METHOD0(HasLoginToken, bool ()); |
+ MOCK_METHOD1(CreateMintTokenFlow, |
+ OAuth2MintTokenFlow* (OAuth2MintTokenFlow::Mode mode)); |
+private: |
+ bool install_ui_result_; |
+ bool login_ui_shown_; |
+ bool install_ui_shown_; |
}; |
-} // namespace |
+class GetAuthTokenFunctionTest : public ExtensionBrowserTest { |
+protected: |
+ const Extension* CreateExtension(bool with_client_id, bool with_scopes) { |
Mihai Parparita -not on Chrome
2012/07/20 18:02:32
Two boolean parameters side-by-side like this make
Munjal (Google)
2012/07/20 18:54:15
Done.
|
+ const Extension* const_ext = LoadExtension( |
+ test_data_dir_.AppendASCII("platform_apps/minimal")); |
+ Extension::OAuth2Info oauth2_info; |
+ if (with_client_id) |
+ oauth2_info.client_id = "client1"; |
+ if (with_scopes) { |
+ oauth2_info.scopes.push_back("scope1"); |
+ oauth2_info.scopes.push_back("scope2"); |
+ } |
+ Extension* ext = const_cast<Extension*>(const_ext); |
+ ext->set_oauth2_info(oauth2_info); |
Mihai Parparita -not on Chrome
2012/07/20 18:02:32
It looks like you're adding this setter, but I'm n
Munjal (Google)
2012/07/20 18:54:15
Good catch. I realized it when the try bots failed
|
+ return ext; |
+ } |
+}; |
-IN_PROC_BROWSER_TEST_F(PlatformAppApiTest, Identity) { |
- IdentityInterceptor id_interceptor; |
- OAuth2MintTokenFlow::SetInterceptorForTests(&id_interceptor); |
- WebAuthFlowInterceptor waf_interceptor; |
- extensions::WebAuthFlow::SetInterceptorForTests(&waf_interceptor); |
- ASSERT_TRUE(RunExtensionTest("identity")) << message_; |
- ASSERT_TRUE(id_interceptor.called()); |
- ASSERT_TRUE(waf_interceptor.called()); |
-}; |
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, |
+ NoClientId) { |
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); |
+ func->set_extension(CreateExtension(false, true)); |
+ std::string error = utils::RunFunctionAndReturnError( |
+ func.get(), "[{}]", browser()); |
+ EXPECT_EQ(std::string(IdentityGetAuthTokenFunction::kInvalidClientId), |
+ error); |
+ EXPECT_FALSE(func->login_ui_shown()); |
+ EXPECT_FALSE(func->install_ui_shown()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, |
+ NoScopes) { |
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); |
+ func->set_extension(CreateExtension(true, false)); |
+ std::string error = utils::RunFunctionAndReturnError( |
+ func.get(), "[{}]", browser()); |
+ EXPECT_EQ(std::string(IdentityGetAuthTokenFunction::kInvalidScopes), |
+ error); |
+ EXPECT_FALSE(func->login_ui_shown()); |
+ EXPECT_FALSE(func->install_ui_shown()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, |
+ NonInteractiveNotSignedIn) { |
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); |
+ func->set_extension(CreateExtension(true, true)); |
+ EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(false)); |
+ std::string error = utils::RunFunctionAndReturnError( |
+ func.get(), "[{}]", browser()); |
+ EXPECT_EQ(std::string(IdentityGetAuthTokenFunction::kUserNotSignedIn), |
+ error); |
+ EXPECT_FALSE(func->login_ui_shown()); |
+ EXPECT_FALSE(func->install_ui_shown()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, |
+ NonInteractiveMintFailure) { |
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); |
+ func->set_extension(CreateExtension(true, true)); |
+ EXPECT_CALL(*func.get(), HasLoginToken()) |
+ .WillOnce(Return(true)) |
+ .WillOnce(Return(true)); |
+ TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow( |
+ TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE, func.get()); |
+ EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow)); |
+ std::string error = utils::RunFunctionAndReturnError( |
+ func.get(), "[{}]", browser()); |
+ EXPECT_TRUE(StartsWithASCII( |
+ error, IdentityGetAuthTokenFunction::kAuthFailure, false)); |
+ EXPECT_FALSE(func->login_ui_shown()); |
+ EXPECT_FALSE(func->install_ui_shown()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, |
+ NonInteractiveSuccess) { |
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); |
+ func->set_extension(CreateExtension(true, true)); |
+ EXPECT_CALL(*func.get(), HasLoginToken()) |
+ .WillOnce(Return(true)) |
+ .WillOnce(Return(true)); |
+ TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow( |
+ TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS, func.get()); |
+ EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow)); |
+ 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, |
+ InteractiveLoginCanceled) { |
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); |
+ func->set_extension(CreateExtension(true, true)); |
+ EXPECT_CALL(*func.get(), HasLoginToken()).WillRepeatedly(Return(false)); |
+ std::string error = utils::RunFunctionAndReturnError( |
+ func.get(), "[{\"interactive\": true}]", browser()); |
+ EXPECT_EQ(std::string(IdentityGetAuthTokenFunction::kUserNotSignedIn), |
+ error); |
+ EXPECT_TRUE(func->login_ui_shown()); |
+ EXPECT_FALSE(func->install_ui_shown()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, |
+ InteractiveLoginSuccessMintFailure) { |
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); |
+ func->set_extension(CreateExtension(true, true)); |
+ EXPECT_CALL(*func.get(), HasLoginToken()) |
+ .WillOnce(Return(false)) |
+ .WillOnce(Return(true)); |
+ TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow( |
+ TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE, func.get()); |
+ EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow)); |
+ std::string error = utils::RunFunctionAndReturnError( |
+ func.get(), "[{\"interactive\": true}]", browser()); |
+ EXPECT_TRUE(StartsWithASCII( |
+ error, IdentityGetAuthTokenFunction::kAuthFailure, false)); |
+ EXPECT_TRUE(func->login_ui_shown()); |
+ EXPECT_FALSE(func->install_ui_shown()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, |
+ InteractiveLoginSuccessMintSuccess) { |
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); |
+ func->set_extension(CreateExtension(true, true)); |
+ EXPECT_CALL(*func.get(), HasLoginToken()) |
+ .WillOnce(Return(false)) |
+ .WillOnce(Return(true)); |
+ TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow( |
+ TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS, func.get()); |
+ EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow)); |
+ 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_FALSE(func->install_ui_shown()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, |
+ InteractiveLoginSuccessApprovalAborted) { |
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); |
+ func->set_extension(CreateExtension(true, true)); |
+ EXPECT_CALL(*func.get(), HasLoginToken()) |
+ .WillOnce(Return(false)) |
+ .WillOnce(Return(true)); |
+ TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow( |
+ TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get()); |
+ EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow)); |
+ func->set_install_ui_result(false); |
+ std::string error = utils::RunFunctionAndReturnError( |
+ func.get(), "[{\"interactive\": true}]", browser()); |
+ EXPECT_EQ(std::string(IdentityGetAuthTokenFunction::kUserRejected), error); |
+ EXPECT_TRUE(func->login_ui_shown()); |
+ EXPECT_TRUE(func->install_ui_shown()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, |
+ InteractiveLoginSuccessApprovalDoneMintFailure) { |
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); |
+ func->set_extension(CreateExtension(true, true)); |
+ EXPECT_CALL(*func.get(), HasLoginToken()) |
+ .WillOnce(Return(false)) |
+ .WillOnce(Return(true)) |
+ .WillOnce(Return(true)); |
+ TestOAuth2MintTokenFlow* flow1 = new TestOAuth2MintTokenFlow( |
+ TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get()); |
+ TestOAuth2MintTokenFlow* flow2 = new TestOAuth2MintTokenFlow( |
+ TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE, func.get()); |
+ EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)) |
+ .WillOnce(Return(flow1)) |
+ .WillOnce(Return(flow2)); |
+ |
+ func->set_install_ui_result(true); |
+ std::string error = utils::RunFunctionAndReturnError( |
+ func.get(), "[{\"interactive\": true}]", browser()); |
+ EXPECT_TRUE(StartsWithASCII( |
+ error, IdentityGetAuthTokenFunction::kAuthFailure, false)); |
+ EXPECT_TRUE(func->login_ui_shown()); |
+ EXPECT_TRUE(func->install_ui_shown()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, |
+ InteractiveLoginSuccessApprovalDoneMintSuccess) { |
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); |
+ func->set_extension(CreateExtension(true, true)); |
+ EXPECT_CALL(*func.get(), HasLoginToken()) |
+ .WillOnce(Return(false)) |
+ .WillOnce(Return(true)) |
+ .WillOnce(Return(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()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, |
+ InteractiveApprovalAborted) { |
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); |
+ func->set_extension(CreateExtension(true, true)); |
+ EXPECT_CALL(*func.get(), HasLoginToken()) |
+ .WillOnce(Return(true)) |
+ .WillOnce(Return(true)); |
+ TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow( |
+ TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get()); |
+ EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow)); |
+ func->set_install_ui_result(false); |
+ std::string error = utils::RunFunctionAndReturnError( |
+ func.get(), "[{\"interactive\": true}]", browser()); |
+ EXPECT_EQ(std::string(IdentityGetAuthTokenFunction::kUserRejected), error); |
+ EXPECT_FALSE(func->login_ui_shown()); |
+ EXPECT_TRUE(func->install_ui_shown()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, |
+ InteractiveApprovalDoneMintSuccess) { |
+ scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); |
+ func->set_extension(CreateExtension(true, true)); |
+ EXPECT_CALL(*func.get(), HasLoginToken()) |
+ .WillOnce(Return(true)) |
+ .WillOnce(Return(true)) |
+ .WillOnce(Return(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_FALSE(func->login_ui_shown()); |
+ EXPECT_TRUE(func->install_ui_shown()); |
+} |