1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/identity/gaia_web_auth_flow.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "content/public/test/test_browser_thread.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 namespace extensions
{
17 class FakeWebAuthFlow
: public WebAuthFlow
{
19 explicit FakeWebAuthFlow(WebAuthFlow::Delegate
* delegate
)
20 : WebAuthFlow(delegate
,
23 WebAuthFlow::INTERACTIVE
) {}
25 virtual void Start() OVERRIDE
{}
28 class TestGaiaWebAuthFlow
: public GaiaWebAuthFlow
{
30 TestGaiaWebAuthFlow(GaiaWebAuthFlow::Delegate
* delegate
,
31 const ExtensionTokenKey
* token_key
,
32 const std::string oauth2_client_id
,
33 GoogleServiceAuthError::State ubertoken_error_state
)
34 : GaiaWebAuthFlow(delegate
, NULL
, token_key
, oauth2_client_id
, "en-us"),
35 ubertoken_error_(ubertoken_error_state
) {}
37 virtual void Start() OVERRIDE
{
38 if (ubertoken_error_
.state() == GoogleServiceAuthError::NONE
)
39 OnUbertokenSuccess("fake_ubertoken");
41 OnUbertokenFailure(ubertoken_error_
);
45 virtual scoped_ptr
<WebAuthFlow
> CreateWebAuthFlow(GURL url
) OVERRIDE
{
46 return scoped_ptr
<WebAuthFlow
>(new FakeWebAuthFlow(this));
49 GoogleServiceAuthError ubertoken_error_
;
52 class MockGaiaWebAuthFlowDelegate
: public GaiaWebAuthFlow::Delegate
{
54 MOCK_METHOD3(OnGaiaFlowFailure
,
55 void(GaiaWebAuthFlow::Failure failure
,
56 GoogleServiceAuthError service_error
,
57 const std::string
& oauth_error
));
58 MOCK_METHOD2(OnGaiaFlowCompleted
,
59 void(const std::string
& access_token
,
60 const std::string
& expiration
));
63 class IdentityGaiaWebAuthFlowTest
: public testing::Test
{
65 IdentityGaiaWebAuthFlowTest()
66 : ubertoken_error_state_(GoogleServiceAuthError::NONE
),
67 fake_ui_thread_(content::BrowserThread::UI
, &message_loop_
) {}
69 virtual void TearDown() {
70 testing::Test::TearDown();
72 loop
.RunUntilIdle(); // Run tasks so FakeWebAuthFlows get deleted.
75 scoped_ptr
<TestGaiaWebAuthFlow
> CreateTestFlow() {
76 ExtensionTokenKey
token_key(
77 "extension_id", "account_id", std::set
<std::string
>());
78 return scoped_ptr
<TestGaiaWebAuthFlow
>(new TestGaiaWebAuthFlow(
79 &delegate_
, &token_key
, "fake.client.id", ubertoken_error_state_
));
82 std::string
GetFinalTitle(const std::string
& fragment
) {
83 return std::string("Loading id.client.fake:/extension_id#") + fragment
;
86 GoogleServiceAuthError
GetNoneServiceError() {
87 return GoogleServiceAuthError(GoogleServiceAuthError::NONE
);
90 void set_ubertoken_error(
91 GoogleServiceAuthError::State ubertoken_error_state
) {
92 ubertoken_error_state_
= ubertoken_error_state
;
96 testing::StrictMock
<MockGaiaWebAuthFlowDelegate
> delegate_
;
97 GoogleServiceAuthError::State ubertoken_error_state_
;
98 base::MessageLoop message_loop_
;
99 content::TestBrowserThread fake_ui_thread_
;
102 TEST_F(IdentityGaiaWebAuthFlowTest
, OAuthError
) {
103 scoped_ptr
<TestGaiaWebAuthFlow
> flow
= CreateTestFlow();
105 EXPECT_CALL(delegate_
, OnGaiaFlowFailure(
106 GaiaWebAuthFlow::OAUTH_ERROR
,
107 GoogleServiceAuthError(GoogleServiceAuthError::NONE
),
109 flow
->OnAuthFlowTitleChange(GetFinalTitle("error=access_denied"));
112 TEST_F(IdentityGaiaWebAuthFlowTest
, Token
) {
113 scoped_ptr
<TestGaiaWebAuthFlow
> flow
= CreateTestFlow();
115 EXPECT_CALL(delegate_
, OnGaiaFlowCompleted("fake_access_token", ""));
116 flow
->OnAuthFlowTitleChange(GetFinalTitle("access_token=fake_access_token"));
119 TEST_F(IdentityGaiaWebAuthFlowTest
, TokenAndExpiration
) {
120 scoped_ptr
<TestGaiaWebAuthFlow
> flow
= CreateTestFlow();
122 EXPECT_CALL(delegate_
, OnGaiaFlowCompleted("fake_access_token", "3600"));
123 flow
->OnAuthFlowTitleChange(
124 GetFinalTitle("access_token=fake_access_token&expires_in=3600"));
127 TEST_F(IdentityGaiaWebAuthFlowTest
, ExtraFragmentParametersSuccess
) {
128 scoped_ptr
<TestGaiaWebAuthFlow
> flow
= CreateTestFlow();
130 EXPECT_CALL(delegate_
,
131 OnGaiaFlowCompleted("fake_access_token", "3600"));
132 flow
->OnAuthFlowTitleChange(GetFinalTitle("chaff1=stuff&"
135 "nonerror=fake_error&"
137 "access_token=fake_access_token&"
141 TEST_F(IdentityGaiaWebAuthFlowTest
, ExtraFragmentParametersError
) {
142 scoped_ptr
<TestGaiaWebAuthFlow
> flow
= CreateTestFlow();
144 EXPECT_CALL(delegate_
, OnGaiaFlowFailure(
145 GaiaWebAuthFlow::OAUTH_ERROR
,
146 GoogleServiceAuthError(GoogleServiceAuthError::NONE
),
148 flow
->OnAuthFlowTitleChange(GetFinalTitle("chaff1=stuff&"
153 "access_token=fake_access_token&"
157 TEST_F(IdentityGaiaWebAuthFlowTest
, TitleSpam
) {
158 scoped_ptr
<TestGaiaWebAuthFlow
> flow
= CreateTestFlow();
160 flow
->OnAuthFlowTitleChange(
161 "Loading https://extension_id.chromiumapp.org/#error=non_final_title");
162 flow
->OnAuthFlowTitleChange("I'm feeling entitled.");
163 flow
->OnAuthFlowTitleChange("");
164 flow
->OnAuthFlowTitleChange(
165 "Loading id.client.fake:/bad_extension_id#error=non_final_title");
166 flow
->OnAuthFlowTitleChange(
167 "Loading bad.id.client.fake:/extension_id#error=non_final_title");
168 EXPECT_CALL(delegate_
, OnGaiaFlowCompleted("fake_access_token", ""));
169 flow
->OnAuthFlowTitleChange(GetFinalTitle("access_token=fake_access_token"));
172 TEST_F(IdentityGaiaWebAuthFlowTest
, EmptyFragment
) {
173 scoped_ptr
<TestGaiaWebAuthFlow
> flow
= CreateTestFlow();
178 GaiaWebAuthFlow::INVALID_REDIRECT
,
179 GoogleServiceAuthError(GoogleServiceAuthError::NONE
),
181 flow
->OnAuthFlowTitleChange(GetFinalTitle(""));
184 TEST_F(IdentityGaiaWebAuthFlowTest
, JunkFragment
) {
185 scoped_ptr
<TestGaiaWebAuthFlow
> flow
= CreateTestFlow();
190 GaiaWebAuthFlow::INVALID_REDIRECT
,
191 GoogleServiceAuthError(GoogleServiceAuthError::NONE
),
193 flow
->OnAuthFlowTitleChange(GetFinalTitle("thisisjustabunchofjunk"));
196 TEST_F(IdentityGaiaWebAuthFlowTest
, NoFragment
) {
197 scoped_ptr
<TestGaiaWebAuthFlow
> flow
= CreateTestFlow();
199 // This won't be recognized as an interesting title.
200 flow
->OnAuthFlowTitleChange("Loading id.client.fake:/extension_id");
203 TEST_F(IdentityGaiaWebAuthFlowTest
, Host
) {
204 scoped_ptr
<TestGaiaWebAuthFlow
> flow
= CreateTestFlow();
206 // These won't be recognized as interesting titles.
207 flow
->OnAuthFlowTitleChange(
208 "Loading id.client.fake://extension_id#access_token=fake_access_token");
209 flow
->OnAuthFlowTitleChange(
210 "Loading id.client.fake://extension_id/#access_token=fake_access_token");
211 flow
->OnAuthFlowTitleChange(
213 "id.client.fake://host/extension_id/#access_token=fake_access_token");
216 TEST_F(IdentityGaiaWebAuthFlowTest
, UbertokenFailure
) {
217 set_ubertoken_error(GoogleServiceAuthError::CONNECTION_FAILED
);
218 scoped_ptr
<TestGaiaWebAuthFlow
> flow
= CreateTestFlow();
222 GaiaWebAuthFlow::SERVICE_AUTH_ERROR
,
223 GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED
),
228 TEST_F(IdentityGaiaWebAuthFlowTest
, AuthFlowFailure
) {
229 scoped_ptr
<TestGaiaWebAuthFlow
> flow
= CreateTestFlow();
234 GaiaWebAuthFlow::WINDOW_CLOSED
,
235 GoogleServiceAuthError(GoogleServiceAuthError::NONE
),
237 flow
->OnAuthFlowFailure(WebAuthFlow::WINDOW_CLOSED
);
240 } // namespace extensions