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 std::string& extension_id,
32 const OAuth2Info& oauth2_info,
33 GoogleServiceAuthError::State ubertoken_error_state)
34 : GaiaWebAuthFlow(delegate,
39 ubertoken_error_(ubertoken_error_state) {}
41 virtual void Start() OVERRIDE {
42 if (ubertoken_error_.state() == GoogleServiceAuthError::NONE)
43 OnUbertokenSuccess("fake_ubertoken");
45 OnUbertokenFailure(ubertoken_error_);
49 virtual scoped_ptr<WebAuthFlow> CreateWebAuthFlow(GURL url) OVERRIDE {
50 return scoped_ptr<WebAuthFlow>(new FakeWebAuthFlow(this));
53 GoogleServiceAuthError ubertoken_error_;
56 class MockGaiaWebAuthFlowDelegate : public GaiaWebAuthFlow::Delegate {
58 MOCK_METHOD3(OnGaiaFlowFailure,
59 void(GaiaWebAuthFlow::Failure failure,
60 GoogleServiceAuthError service_error,
61 const std::string& oauth_error));
62 MOCK_METHOD2(OnGaiaFlowCompleted,
63 void(const std::string& access_token,
64 const std::string& expiration));
67 class IdentityGaiaWebAuthFlowTest : public testing::Test {
69 IdentityGaiaWebAuthFlowTest()
70 : ubertoken_error_state_(GoogleServiceAuthError::NONE),
71 fake_ui_thread_(content::BrowserThread::UI, &message_loop_) {}
73 virtual void TearDown() {
74 testing::Test::TearDown();
76 loop.RunUntilIdle(); // Run tasks so FakeWebAuthFlows get deleted.
79 scoped_ptr<TestGaiaWebAuthFlow> CreateTestFlow() {
80 OAuth2Info oauth2_info;
81 oauth2_info.client_id = "fake.client.id";
82 return scoped_ptr<TestGaiaWebAuthFlow>(new TestGaiaWebAuthFlow(
83 &delegate_, "extension_id", oauth2_info, ubertoken_error_state_));
86 std::string GetFinalTitle(const std::string& fragment) {
87 return std::string("Loading id.client.fake:/extension_id#") + fragment;
90 GoogleServiceAuthError GetNoneServiceError() {
91 return GoogleServiceAuthError(GoogleServiceAuthError::NONE);
94 void set_ubertoken_error(
95 GoogleServiceAuthError::State ubertoken_error_state) {
96 ubertoken_error_state_ = ubertoken_error_state;
100 testing::StrictMock<MockGaiaWebAuthFlowDelegate> delegate_;
101 GoogleServiceAuthError::State ubertoken_error_state_;
102 base::MessageLoop message_loop_;
103 content::TestBrowserThread fake_ui_thread_;
106 TEST_F(IdentityGaiaWebAuthFlowTest, OAuthError) {
107 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow();
109 EXPECT_CALL(delegate_, OnGaiaFlowFailure(
110 GaiaWebAuthFlow::OAUTH_ERROR,
111 GoogleServiceAuthError(GoogleServiceAuthError::NONE),
113 flow->OnAuthFlowTitleChange(GetFinalTitle("error=access_denied"));
116 TEST_F(IdentityGaiaWebAuthFlowTest, Token) {
117 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow();
119 EXPECT_CALL(delegate_, OnGaiaFlowCompleted("fake_access_token", ""));
120 flow->OnAuthFlowTitleChange(GetFinalTitle("access_token=fake_access_token"));
123 TEST_F(IdentityGaiaWebAuthFlowTest, TokenAndExpiration) {
124 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow();
126 EXPECT_CALL(delegate_, OnGaiaFlowCompleted("fake_access_token", "3600"));
127 flow->OnAuthFlowTitleChange(
128 GetFinalTitle("access_token=fake_access_token&expires_in=3600"));
131 TEST_F(IdentityGaiaWebAuthFlowTest, ExtraFragmentParametersSuccess) {
132 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow();
134 EXPECT_CALL(delegate_,
135 OnGaiaFlowCompleted("fake_access_token", "3600"));
136 flow->OnAuthFlowTitleChange(GetFinalTitle("chaff1=stuff&"
139 "nonerror=fake_error&"
141 "access_token=fake_access_token&"
145 TEST_F(IdentityGaiaWebAuthFlowTest, ExtraFragmentParametersError) {
146 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow();
148 EXPECT_CALL(delegate_, OnGaiaFlowFailure(
149 GaiaWebAuthFlow::OAUTH_ERROR,
150 GoogleServiceAuthError(GoogleServiceAuthError::NONE),
152 flow->OnAuthFlowTitleChange(GetFinalTitle("chaff1=stuff&"
157 "access_token=fake_access_token&"
161 TEST_F(IdentityGaiaWebAuthFlowTest, TitleSpam) {
162 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow();
164 flow->OnAuthFlowTitleChange(
165 "Loading https://extension_id.chromiumapp.org/#error=non_final_title");
166 flow->OnAuthFlowTitleChange("I'm feeling entitled.");
167 flow->OnAuthFlowTitleChange("");
168 flow->OnAuthFlowTitleChange(
169 "Loading id.client.fake:/bad_extension_id#error=non_final_title");
170 flow->OnAuthFlowTitleChange(
171 "Loading bad.id.client.fake:/extension_id#error=non_final_title");
172 EXPECT_CALL(delegate_, OnGaiaFlowCompleted("fake_access_token", ""));
173 flow->OnAuthFlowTitleChange(GetFinalTitle("access_token=fake_access_token"));
176 TEST_F(IdentityGaiaWebAuthFlowTest, EmptyFragment) {
177 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow();
182 GaiaWebAuthFlow::INVALID_REDIRECT,
183 GoogleServiceAuthError(GoogleServiceAuthError::NONE),
185 flow->OnAuthFlowTitleChange(GetFinalTitle(""));
188 TEST_F(IdentityGaiaWebAuthFlowTest, JunkFragment) {
189 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow();
194 GaiaWebAuthFlow::INVALID_REDIRECT,
195 GoogleServiceAuthError(GoogleServiceAuthError::NONE),
197 flow->OnAuthFlowTitleChange(GetFinalTitle("thisisjustabunchofjunk"));
200 TEST_F(IdentityGaiaWebAuthFlowTest, NoFragment) {
201 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow();
203 // This won't be recognized as an interesting title.
204 flow->OnAuthFlowTitleChange("Loading id.client.fake:/extension_id");
207 TEST_F(IdentityGaiaWebAuthFlowTest, Host) {
208 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow();
210 // These won't be recognized as interesting titles.
211 flow->OnAuthFlowTitleChange(
212 "Loading id.client.fake://extension_id#access_token=fake_access_token");
213 flow->OnAuthFlowTitleChange(
214 "Loading id.client.fake://extension_id/#access_token=fake_access_token");
215 flow->OnAuthFlowTitleChange(
217 "id.client.fake://host/extension_id/#access_token=fake_access_token");
220 TEST_F(IdentityGaiaWebAuthFlowTest, UbertokenFailure) {
221 set_ubertoken_error(GoogleServiceAuthError::CONNECTION_FAILED);
222 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow();
226 GaiaWebAuthFlow::SERVICE_AUTH_ERROR,
227 GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED),
232 TEST_F(IdentityGaiaWebAuthFlowTest, AuthFlowFailure) {
233 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow();
238 GaiaWebAuthFlow::WINDOW_CLOSED,
239 GoogleServiceAuthError(GoogleServiceAuthError::NONE),
241 flow->OnAuthFlowFailure(WebAuthFlow::WINDOW_CLOSED);
244 } // namespace extensions