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 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 void Start() override {
38 if (ubertoken_error_.state() == GoogleServiceAuthError::NONE)
39 OnUbertokenSuccess("fake_ubertoken");
41 OnUbertokenFailure(ubertoken_error_);
45 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