OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/string_util.h" | |
6 #include "base/values.h" | |
5 #include "chrome/browser/extensions/api/identity/identity_api.h" | 7 #include "chrome/browser/extensions/api/identity/identity_api.h" |
6 #include "chrome/browser/extensions/api/identity/web_auth_flow.h" | 8 #include "chrome/browser/extensions/api/identity/web_auth_flow.h" |
7 #include "chrome/browser/extensions/extension_apitest.h" | 9 #include "chrome/browser/extensions/extension_apitest.h" |
10 #include "chrome/browser/extensions/extension_browsertest.h" | |
11 #include "chrome/browser/extensions/extension_function_test_utils.h" | |
12 #include "chrome/browser/ui/webui/signin/login_ui_service.h" | |
8 #include "chrome/common/net/gaia/google_service_auth_error.h" | 13 #include "chrome/common/net/gaia/google_service_auth_error.h" |
9 #include "chrome/common/net/gaia/oauth2_mint_token_flow.h" | 14 #include "chrome/common/net/gaia/oauth2_mint_token_flow.h" |
10 #include "chrome/common/chrome_switches.h" | 15 #include "chrome/common/chrome_switches.h" |
16 #include "chrome/test/base/in_process_browser_test.h" | |
11 #include "googleurl/src/gurl.h" | 17 #include "googleurl/src/gurl.h" |
18 #include "testing/gmock/include/gmock/gmock.h" | |
19 #include "testing/gtest/include/gtest/gtest.h" | |
20 | |
21 using extensions::Extension; | |
22 using extensions::IdentityGetAuthTokenFunction; | |
23 using testing::_; | |
24 using testing::Return; | |
25 using testing::ReturnRef; | |
26 | |
27 namespace utils = extension_function_test_utils; | |
12 | 28 |
13 namespace { | 29 namespace { |
14 | 30 |
15 class IdentityInterceptor : public OAuth2MintTokenFlow::InterceptorForTests { | 31 static const char kAccessToken[] = "auth_token"; |
32 | |
33 class TestLoginUI : public LoginUIService::LoginUI { | |
16 public: | 34 public: |
17 IdentityInterceptor() : called_(false) { } | 35 virtual void FocusUI() OVERRIDE {} |
18 | 36 virtual void CloseUI() OVERRIDE {} |
19 virtual bool DoIntercept(const OAuth2MintTokenFlow* flow, | 37 }; |
20 std::string* access_token, | 38 |
21 GoogleServiceAuthError* error) OVERRIDE { | 39 class TestOAuth2MintTokenFlow : public OAuth2MintTokenFlow { |
22 *access_token = "auth_token"; | 40 public: |
23 called_ = true; | 41 enum ResultType { |
24 return true; | 42 ISSUE_ADVICE_SUCCESS, |
25 } | 43 MINT_TOKEN_SUCCESS, |
26 | 44 MINT_TOKEN_FAILURE |
27 bool called() const { return called_; } | 45 }; |
46 | |
47 TestOAuth2MintTokenFlow(ResultType result, | |
48 OAuth2MintTokenFlow::Delegate* delegate) | |
49 : OAuth2MintTokenFlow(NULL, delegate, OAuth2MintTokenFlow::Parameters()), | |
50 result_(result), | |
51 delegate_(delegate) { | |
52 } | |
53 | |
54 virtual void Start() OVERRIDE { | |
55 switch (result_) { | |
56 case ISSUE_ADVICE_SUCCESS: { | |
57 IssueAdviceInfo info; | |
58 delegate_->OnIssueAdviceSuccess(info); | |
59 break; | |
60 } | |
61 case MINT_TOKEN_SUCCESS: { | |
62 delegate_->OnMintTokenSuccess(kAccessToken); | |
63 break; | |
64 } | |
65 case MINT_TOKEN_FAILURE: { | |
66 GoogleServiceAuthError error( | |
67 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); | |
68 delegate_->OnMintTokenFailure(error); | |
69 break; | |
70 } | |
71 } | |
72 } | |
28 | 73 |
29 private: | 74 private: |
30 bool called_; | 75 ResultType result_; |
76 OAuth2MintTokenFlow::Delegate* delegate_; | |
31 }; | 77 }; |
32 | 78 |
33 class WebAuthFlowInterceptor | 79 } // namespace |
34 : public extensions::WebAuthFlow::InterceptorForTests { | 80 |
81 class MockGetAuthTokenFunction : public IdentityGetAuthTokenFunction { | |
35 public: | 82 public: |
36 WebAuthFlowInterceptor() : called_(false) { } | 83 MockGetAuthTokenFunction() : install_ui_result_(false), |
37 | 84 login_ui_shown_(false), |
38 virtual GURL DoIntercept(const GURL& provider_url) OVERRIDE { | 85 install_ui_shown_(false) { |
39 called_ = true; | 86 } |
40 return GURL("https://abcd.chromiumapp.org/cb#access_token=tok"); | 87 |
41 } | 88 void set_install_ui_result(bool result) { |
42 | 89 install_ui_result_ = result; |
43 bool called() const { return called_; } | 90 } |
44 | 91 |
45 private: | 92 bool login_ui_shown() const { |
46 bool called_; | 93 return login_ui_shown_; |
94 } | |
95 | |
96 bool install_ui_shown() const { | |
97 return install_ui_shown_; | |
98 } | |
99 | |
100 virtual void StartObservingLoginService() OVERRIDE { | |
101 // Do nothing in tests. | |
102 } | |
103 virtual void StopObservingLoginService() OVERRIDE { | |
104 // Do nothing in tests. | |
105 } | |
106 | |
107 virtual void ShowLoginPopup() OVERRIDE { | |
108 login_ui_shown_ = true; | |
109 // Explicitly call OnLoginUIClosed. | |
110 TestLoginUI login_ui;; | |
111 OnLoginUIClosed(&login_ui); | |
112 } | |
113 | |
114 virtual void ShowOAuthApprovalDialog( | |
115 const IssueAdviceInfo& issue_advice) OVERRIDE { | |
116 install_ui_shown_ = true; | |
117 // Call InstallUIProceed or InstallUIAbort based on the flag. | |
118 if (install_ui_result_) | |
119 InstallUIProceed(); | |
120 else | |
121 InstallUIAbort(true); | |
122 } | |
123 | |
124 MOCK_CONST_METHOD0(HasLoginToken, bool ()); | |
125 MOCK_METHOD1(CreateMintTokenFlow, | |
126 OAuth2MintTokenFlow* (OAuth2MintTokenFlow::Mode mode)); | |
127 private: | |
128 bool install_ui_result_; | |
129 bool login_ui_shown_; | |
130 bool install_ui_shown_; | |
47 }; | 131 }; |
48 | 132 |
49 } // namespace | 133 class GetAuthTokenFunctionTest : public ExtensionBrowserTest { |
50 | 134 protected: |
51 IN_PROC_BROWSER_TEST_F(PlatformAppApiTest, Identity) { | 135 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.
| |
52 IdentityInterceptor id_interceptor; | 136 const Extension* const_ext = LoadExtension( |
53 OAuth2MintTokenFlow::SetInterceptorForTests(&id_interceptor); | 137 test_data_dir_.AppendASCII("platform_apps/minimal")); |
54 WebAuthFlowInterceptor waf_interceptor; | 138 Extension::OAuth2Info oauth2_info; |
55 extensions::WebAuthFlow::SetInterceptorForTests(&waf_interceptor); | 139 if (with_client_id) |
56 ASSERT_TRUE(RunExtensionTest("identity")) << message_; | 140 oauth2_info.client_id = "client1"; |
57 ASSERT_TRUE(id_interceptor.called()); | 141 if (with_scopes) { |
58 ASSERT_TRUE(waf_interceptor.called()); | 142 oauth2_info.scopes.push_back("scope1"); |
143 oauth2_info.scopes.push_back("scope2"); | |
144 } | |
145 Extension* ext = const_cast<Extension*>(const_ext); | |
146 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
| |
147 return ext; | |
148 } | |
59 }; | 149 }; |
150 | |
151 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, | |
152 NoClientId) { | |
153 scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); | |
154 func->set_extension(CreateExtension(false, true)); | |
155 std::string error = utils::RunFunctionAndReturnError( | |
156 func.get(), "[{}]", browser()); | |
157 EXPECT_EQ(std::string(IdentityGetAuthTokenFunction::kInvalidClientId), | |
158 error); | |
159 EXPECT_FALSE(func->login_ui_shown()); | |
160 EXPECT_FALSE(func->install_ui_shown()); | |
161 } | |
162 | |
163 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, | |
164 NoScopes) { | |
165 scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); | |
166 func->set_extension(CreateExtension(true, false)); | |
167 std::string error = utils::RunFunctionAndReturnError( | |
168 func.get(), "[{}]", browser()); | |
169 EXPECT_EQ(std::string(IdentityGetAuthTokenFunction::kInvalidScopes), | |
170 error); | |
171 EXPECT_FALSE(func->login_ui_shown()); | |
172 EXPECT_FALSE(func->install_ui_shown()); | |
173 } | |
174 | |
175 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, | |
176 NonInteractiveNotSignedIn) { | |
177 scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); | |
178 func->set_extension(CreateExtension(true, true)); | |
179 EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(false)); | |
180 std::string error = utils::RunFunctionAndReturnError( | |
181 func.get(), "[{}]", browser()); | |
182 EXPECT_EQ(std::string(IdentityGetAuthTokenFunction::kUserNotSignedIn), | |
183 error); | |
184 EXPECT_FALSE(func->login_ui_shown()); | |
185 EXPECT_FALSE(func->install_ui_shown()); | |
186 } | |
187 | |
188 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, | |
189 NonInteractiveMintFailure) { | |
190 scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); | |
191 func->set_extension(CreateExtension(true, true)); | |
192 EXPECT_CALL(*func.get(), HasLoginToken()) | |
193 .WillOnce(Return(true)) | |
194 .WillOnce(Return(true)); | |
195 TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow( | |
196 TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE, func.get()); | |
197 EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow)); | |
198 std::string error = utils::RunFunctionAndReturnError( | |
199 func.get(), "[{}]", browser()); | |
200 EXPECT_TRUE(StartsWithASCII( | |
201 error, IdentityGetAuthTokenFunction::kAuthFailure, false)); | |
202 EXPECT_FALSE(func->login_ui_shown()); | |
203 EXPECT_FALSE(func->install_ui_shown()); | |
204 } | |
205 | |
206 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, | |
207 NonInteractiveSuccess) { | |
208 scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); | |
209 func->set_extension(CreateExtension(true, true)); | |
210 EXPECT_CALL(*func.get(), HasLoginToken()) | |
211 .WillOnce(Return(true)) | |
212 .WillOnce(Return(true)); | |
213 TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow( | |
214 TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS, func.get()); | |
215 EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow)); | |
216 scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult( | |
217 func.get(), "[{}]", browser())); | |
218 std::string access_token; | |
219 EXPECT_TRUE(value->GetAsString(&access_token)); | |
220 EXPECT_EQ(std::string(kAccessToken), access_token); | |
221 EXPECT_FALSE(func->login_ui_shown()); | |
222 EXPECT_FALSE(func->install_ui_shown()); | |
223 } | |
224 | |
225 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, | |
226 InteractiveLoginCanceled) { | |
227 scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); | |
228 func->set_extension(CreateExtension(true, true)); | |
229 EXPECT_CALL(*func.get(), HasLoginToken()).WillRepeatedly(Return(false)); | |
230 std::string error = utils::RunFunctionAndReturnError( | |
231 func.get(), "[{\"interactive\": true}]", browser()); | |
232 EXPECT_EQ(std::string(IdentityGetAuthTokenFunction::kUserNotSignedIn), | |
233 error); | |
234 EXPECT_TRUE(func->login_ui_shown()); | |
235 EXPECT_FALSE(func->install_ui_shown()); | |
236 } | |
237 | |
238 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, | |
239 InteractiveLoginSuccessMintFailure) { | |
240 scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); | |
241 func->set_extension(CreateExtension(true, true)); | |
242 EXPECT_CALL(*func.get(), HasLoginToken()) | |
243 .WillOnce(Return(false)) | |
244 .WillOnce(Return(true)); | |
245 TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow( | |
246 TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE, func.get()); | |
247 EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow)); | |
248 std::string error = utils::RunFunctionAndReturnError( | |
249 func.get(), "[{\"interactive\": true}]", browser()); | |
250 EXPECT_TRUE(StartsWithASCII( | |
251 error, IdentityGetAuthTokenFunction::kAuthFailure, false)); | |
252 EXPECT_TRUE(func->login_ui_shown()); | |
253 EXPECT_FALSE(func->install_ui_shown()); | |
254 } | |
255 | |
256 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, | |
257 InteractiveLoginSuccessMintSuccess) { | |
258 scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); | |
259 func->set_extension(CreateExtension(true, true)); | |
260 EXPECT_CALL(*func.get(), HasLoginToken()) | |
261 .WillOnce(Return(false)) | |
262 .WillOnce(Return(true)); | |
263 TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow( | |
264 TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS, func.get()); | |
265 EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow)); | |
266 scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult( | |
267 func.get(), "[{\"interactive\": true}]", browser())); | |
268 std::string access_token; | |
269 EXPECT_TRUE(value->GetAsString(&access_token)); | |
270 EXPECT_EQ(std::string(kAccessToken), access_token); | |
271 EXPECT_TRUE(func->login_ui_shown()); | |
272 EXPECT_FALSE(func->install_ui_shown()); | |
273 } | |
274 | |
275 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, | |
276 InteractiveLoginSuccessApprovalAborted) { | |
277 scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); | |
278 func->set_extension(CreateExtension(true, true)); | |
279 EXPECT_CALL(*func.get(), HasLoginToken()) | |
280 .WillOnce(Return(false)) | |
281 .WillOnce(Return(true)); | |
282 TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow( | |
283 TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get()); | |
284 EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow)); | |
285 func->set_install_ui_result(false); | |
286 std::string error = utils::RunFunctionAndReturnError( | |
287 func.get(), "[{\"interactive\": true}]", browser()); | |
288 EXPECT_EQ(std::string(IdentityGetAuthTokenFunction::kUserRejected), error); | |
289 EXPECT_TRUE(func->login_ui_shown()); | |
290 EXPECT_TRUE(func->install_ui_shown()); | |
291 } | |
292 | |
293 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, | |
294 InteractiveLoginSuccessApprovalDoneMintFailure) { | |
295 scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); | |
296 func->set_extension(CreateExtension(true, true)); | |
297 EXPECT_CALL(*func.get(), HasLoginToken()) | |
298 .WillOnce(Return(false)) | |
299 .WillOnce(Return(true)) | |
300 .WillOnce(Return(true)); | |
301 TestOAuth2MintTokenFlow* flow1 = new TestOAuth2MintTokenFlow( | |
302 TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get()); | |
303 TestOAuth2MintTokenFlow* flow2 = new TestOAuth2MintTokenFlow( | |
304 TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE, func.get()); | |
305 EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)) | |
306 .WillOnce(Return(flow1)) | |
307 .WillOnce(Return(flow2)); | |
308 | |
309 func->set_install_ui_result(true); | |
310 std::string error = utils::RunFunctionAndReturnError( | |
311 func.get(), "[{\"interactive\": true}]", browser()); | |
312 EXPECT_TRUE(StartsWithASCII( | |
313 error, IdentityGetAuthTokenFunction::kAuthFailure, false)); | |
314 EXPECT_TRUE(func->login_ui_shown()); | |
315 EXPECT_TRUE(func->install_ui_shown()); | |
316 } | |
317 | |
318 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, | |
319 InteractiveLoginSuccessApprovalDoneMintSuccess) { | |
320 scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); | |
321 func->set_extension(CreateExtension(true, true)); | |
322 EXPECT_CALL(*func.get(), HasLoginToken()) | |
323 .WillOnce(Return(false)) | |
324 .WillOnce(Return(true)) | |
325 .WillOnce(Return(true)); | |
326 TestOAuth2MintTokenFlow* flow1 = new TestOAuth2MintTokenFlow( | |
327 TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get()); | |
328 TestOAuth2MintTokenFlow* flow2 = new TestOAuth2MintTokenFlow( | |
329 TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS, func.get()); | |
330 EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)) | |
331 .WillOnce(Return(flow1)) | |
332 .WillOnce(Return(flow2)); | |
333 | |
334 func->set_install_ui_result(true); | |
335 scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult( | |
336 func.get(), "[{\"interactive\": true}]", browser())); | |
337 std::string access_token; | |
338 EXPECT_TRUE(value->GetAsString(&access_token)); | |
339 EXPECT_EQ(std::string(kAccessToken), access_token); | |
340 EXPECT_TRUE(func->login_ui_shown()); | |
341 EXPECT_TRUE(func->install_ui_shown()); | |
342 } | |
343 | |
344 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, | |
345 InteractiveApprovalAborted) { | |
346 scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); | |
347 func->set_extension(CreateExtension(true, true)); | |
348 EXPECT_CALL(*func.get(), HasLoginToken()) | |
349 .WillOnce(Return(true)) | |
350 .WillOnce(Return(true)); | |
351 TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow( | |
352 TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get()); | |
353 EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow)); | |
354 func->set_install_ui_result(false); | |
355 std::string error = utils::RunFunctionAndReturnError( | |
356 func.get(), "[{\"interactive\": true}]", browser()); | |
357 EXPECT_EQ(std::string(IdentityGetAuthTokenFunction::kUserRejected), error); | |
358 EXPECT_FALSE(func->login_ui_shown()); | |
359 EXPECT_TRUE(func->install_ui_shown()); | |
360 } | |
361 | |
362 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, | |
363 InteractiveApprovalDoneMintSuccess) { | |
364 scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction()); | |
365 func->set_extension(CreateExtension(true, true)); | |
366 EXPECT_CALL(*func.get(), HasLoginToken()) | |
367 .WillOnce(Return(true)) | |
368 .WillOnce(Return(true)) | |
369 .WillOnce(Return(true)); | |
370 TestOAuth2MintTokenFlow* flow1 = new TestOAuth2MintTokenFlow( | |
371 TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get()); | |
372 TestOAuth2MintTokenFlow* flow2 = new TestOAuth2MintTokenFlow( | |
373 TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS, func.get()); | |
374 EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)) | |
375 .WillOnce(Return(flow1)) | |
376 .WillOnce(Return(flow2)); | |
377 | |
378 func->set_install_ui_result(true); | |
379 scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult( | |
380 func.get(), "[{\"interactive\": true}]", browser())); | |
381 std::string access_token; | |
382 EXPECT_TRUE(value->GetAsString(&access_token)); | |
383 EXPECT_EQ(std::string(kAccessToken), access_token); | |
384 EXPECT_FALSE(func->login_ui_shown()); | |
385 EXPECT_TRUE(func->install_ui_shown()); | |
386 } | |
OLD | NEW |