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
3 // found in the LICENSE file.
4
5 #include <set>
6 #include <string>
7 #include <vector>
8
9 #include "base/command_line.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/values.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/extensions/api/identity/identity_api.h"
16 #include "chrome/browser/extensions/component_loader.h"
17 #include "chrome/browser/extensions/extension_apitest.h"
18 #include "chrome/browser/extensions/extension_browsertest.h"
19 #include "chrome/browser/extensions/extension_function_test_utils.h"
20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/signin/account_reconcilor_factory.h"
23 #include "chrome/browser/signin/fake_account_reconcilor.h"
24 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
25 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
26 #include "chrome/browser/signin/fake_signin_manager.h"
27 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
28 #include "chrome/browser/signin/signin_manager_factory.h"
29 #include "chrome/browser/ui/browser.h"
30 #include "chrome/browser/ui/browser_window.h"
31 #include "chrome/common/chrome_switches.h"
32 #include "chrome/common/extensions/api/identity.h"
33 #include "chrome/common/extensions/api/identity/oauth2_manifest_handler.h"
34 #include "chrome/test/base/in_process_browser_test.h"
35 #include "chrome/test/base/test_switches.h"
36 #include "components/crx_file/id_util.h"
37 #include "components/signin/core/browser/signin_manager.h"
38 #include "components/signin/core/common/profile_management_switches.h"
39 #include "components/signin/core/common/signin_pref_names.h"
40 #include "content/public/browser/notification_service.h"
41 #include "content/public/browser/notification_source.h"
42 #include "content/public/test/test_utils.h"
43 #include "extensions/browser/guest_view/guest_view_base.h"
44 #include "extensions/common/test_util.h"
45 #include "google_apis/gaia/google_service_auth_error.h"
46 #include "google_apis/gaia/oauth2_mint_token_flow.h"
47 #include "net/test/spawned_test_server/spawned_test_server.h"
48 #include "testing/gmock/include/gmock/gmock.h"
49 #include "testing/gtest/include/gtest/gtest.h"
50 #include "url/gurl.h"
51
52 using testing::_;
53 using testing::Return;
54 using testing::ReturnRef;
55
56 namespace extensions {
57
58 namespace {
59
60 namespace errors = identity_constants;
61 namespace utils = extension_function_test_utils;
62
63 static const char kAccessToken[] = "auth_token";
64 static const char kExtensionId[] = "ext_id";
65
66 // This helps us be able to wait until an UIThreadExtensionFunction calls
67 // SendResponse.
68 class SendResponseDelegate
69 : public UIThreadExtensionFunction::DelegateForTests {
70 public:
SendResponseDelegate()71 SendResponseDelegate() : should_post_quit_(false) {}
72
~SendResponseDelegate()73 virtual ~SendResponseDelegate() {}
74
set_should_post_quit(bool should_quit)75 void set_should_post_quit(bool should_quit) {
76 should_post_quit_ = should_quit;
77 }
78
HasResponse()79 bool HasResponse() {
80 return response_.get() != NULL;
81 }
82
GetResponse()83 bool GetResponse() {
84 EXPECT_TRUE(HasResponse());
85 return *response_.get();
86 }
87
OnSendResponse(UIThreadExtensionFunction * function,bool success,bool bad_message)88 virtual void OnSendResponse(UIThreadExtensionFunction* function,
89 bool success,
90 bool bad_message) OVERRIDE {
91 ASSERT_FALSE(bad_message);
92 ASSERT_FALSE(HasResponse());
93 response_.reset(new bool);
94 *response_ = success;
95 if (should_post_quit_) {
96 base::MessageLoopForUI::current()->Quit();
97 }
98 }
99
100 private:
101 scoped_ptr<bool> response_;
102 bool should_post_quit_;
103 };
104
105 class AsyncExtensionBrowserTest : public ExtensionBrowserTest {
106 protected:
107 // Asynchronous function runner allows tests to manipulate the browser window
108 // after the call happens.
RunFunctionAsync(UIThreadExtensionFunction * function,const std::string & args)109 void RunFunctionAsync(
110 UIThreadExtensionFunction* function,
111 const std::string& args) {
112 response_delegate_.reset(new SendResponseDelegate);
113 function->set_test_delegate(response_delegate_.get());
114 scoped_ptr<base::ListValue> parsed_args(utils::ParseList(args));
115 EXPECT_TRUE(parsed_args.get()) <<
116 "Could not parse extension function arguments: " << args;
117 function->SetArgs(parsed_args.get());
118
119 if (!function->extension()) {
120 scoped_refptr<Extension> empty_extension(
121 test_util::CreateEmptyExtension());
122 function->set_extension(empty_extension.get());
123 }
124
125 function->set_browser_context(browser()->profile());
126 function->set_has_callback(true);
127 function->Run()->Execute();
128 }
129
WaitForError(UIThreadExtensionFunction * function)130 std::string WaitForError(UIThreadExtensionFunction* function) {
131 RunMessageLoopUntilResponse();
132 EXPECT_FALSE(function->GetResultList()) << "Did not expect a result";
133 return function->GetError();
134 }
135
WaitForSingleResult(UIThreadExtensionFunction * function)136 base::Value* WaitForSingleResult(UIThreadExtensionFunction* function) {
137 RunMessageLoopUntilResponse();
138 EXPECT_TRUE(function->GetError().empty()) << "Unexpected error: "
139 << function->GetError();
140 const base::Value* single_result = NULL;
141 if (function->GetResultList() != NULL &&
142 function->GetResultList()->Get(0, &single_result)) {
143 return single_result->DeepCopy();
144 }
145 return NULL;
146 }
147
148 private:
RunMessageLoopUntilResponse()149 void RunMessageLoopUntilResponse() {
150 // If the RunAsync of |function| didn't already call SendResponse, run the
151 // message loop until they do.
152 if (!response_delegate_->HasResponse()) {
153 response_delegate_->set_should_post_quit(true);
154 content::RunMessageLoop();
155 }
156 EXPECT_TRUE(response_delegate_->HasResponse());
157 }
158
159 scoped_ptr<SendResponseDelegate> response_delegate_;
160 };
161
162 class TestHangOAuth2MintTokenFlow : public OAuth2MintTokenFlow {
163 public:
TestHangOAuth2MintTokenFlow()164 TestHangOAuth2MintTokenFlow()
165 : OAuth2MintTokenFlow(NULL, NULL, OAuth2MintTokenFlow::Parameters()) {}
166
Start()167 virtual void Start() OVERRIDE {
168 // Do nothing, simulating a hanging network call.
169 }
170 };
171
172 class TestOAuth2MintTokenFlow : public OAuth2MintTokenFlow {
173 public:
174 enum ResultType {
175 ISSUE_ADVICE_SUCCESS,
176 MINT_TOKEN_SUCCESS,
177 MINT_TOKEN_FAILURE,
178 MINT_TOKEN_BAD_CREDENTIALS,
179 MINT_TOKEN_SERVICE_ERROR
180 };
181
TestOAuth2MintTokenFlow(ResultType result,OAuth2MintTokenFlow::Delegate * delegate)182 TestOAuth2MintTokenFlow(ResultType result,
183 OAuth2MintTokenFlow::Delegate* delegate)
184 : OAuth2MintTokenFlow(NULL, delegate, OAuth2MintTokenFlow::Parameters()),
185 result_(result),
186 delegate_(delegate) {
187 }
188
Start()189 virtual void Start() OVERRIDE {
190 switch (result_) {
191 case ISSUE_ADVICE_SUCCESS: {
192 IssueAdviceInfo info;
193 delegate_->OnIssueAdviceSuccess(info);
194 break;
195 }
196 case MINT_TOKEN_SUCCESS: {
197 delegate_->OnMintTokenSuccess(kAccessToken, 3600);
198 break;
199 }
200 case MINT_TOKEN_FAILURE: {
201 GoogleServiceAuthError error(GoogleServiceAuthError::CONNECTION_FAILED);
202 delegate_->OnMintTokenFailure(error);
203 break;
204 }
205 case MINT_TOKEN_BAD_CREDENTIALS: {
206 GoogleServiceAuthError error(
207 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
208 delegate_->OnMintTokenFailure(error);
209 break;
210 }
211 case MINT_TOKEN_SERVICE_ERROR: {
212 GoogleServiceAuthError error =
213 GoogleServiceAuthError::FromServiceError("invalid_scope");
214 delegate_->OnMintTokenFailure(error);
215 break;
216 }
217 }
218 }
219
220 private:
221 ResultType result_;
222 OAuth2MintTokenFlow::Delegate* delegate_;
223 };
224
225 // Waits for a specific GURL to generate a NOTIFICATION_LOAD_STOP event and
226 // saves a pointer to the window embedding the WebContents, which can be later
227 // closed.
228 class WaitForGURLAndCloseWindow : public content::WindowedNotificationObserver {
229 public:
WaitForGURLAndCloseWindow(GURL url)230 explicit WaitForGURLAndCloseWindow(GURL url)
231 : WindowedNotificationObserver(
232 content::NOTIFICATION_LOAD_STOP,
233 content::NotificationService::AllSources()),
234 url_(url) {}
235
236 // NotificationObserver:
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)237 virtual void Observe(int type,
238 const content::NotificationSource& source,
239 const content::NotificationDetails& details) OVERRIDE {
240 content::NavigationController* web_auth_flow_controller =
241 content::Source<content::NavigationController>(source).ptr();
242 content::WebContents* web_contents =
243 web_auth_flow_controller->GetWebContents();
244
245 if (web_contents->GetURL() == url_) {
246 // It is safe to keep the pointer here, because we know in a test, that
247 // the WebContents won't go away before CloseEmbedderWebContents is
248 // called. Don't copy this code to production.
249 GuestViewBase* guest = GuestViewBase::FromWebContents(web_contents);
250 embedder_web_contents_ = guest->embedder_web_contents();
251 // Condtionally invoke parent class so that Wait will not exit
252 // until the target URL arrives.
253 content::WindowedNotificationObserver::Observe(type, source, details);
254 }
255 }
256
257 // Closes the window embedding the WebContents. The action is separated from
258 // the Observe method to make sure the list of observers is not deleted,
259 // while some event is already being processed. (That causes ASAN failures.)
CloseEmbedderWebContents()260 void CloseEmbedderWebContents() {
261 if (embedder_web_contents_)
262 embedder_web_contents_->Close();
263 }
264
265 private:
266 GURL url_;
267 content::WebContents* embedder_web_contents_;
268 };
269
270 } // namespace
271
272 class FakeGetAuthTokenFunction : public IdentityGetAuthTokenFunction {
273 public:
FakeGetAuthTokenFunction()274 FakeGetAuthTokenFunction()
275 : login_access_token_result_(true),
276 auto_login_access_token_(true),
277 login_ui_result_(true),
278 scope_ui_result_(true),
279 login_ui_shown_(false),
280 scope_ui_shown_(false) {}
281
set_login_access_token_result(bool result)282 void set_login_access_token_result(bool result) {
283 login_access_token_result_ = result;
284 }
285
set_auto_login_access_token(bool automatic)286 void set_auto_login_access_token(bool automatic) {
287 auto_login_access_token_ = automatic;
288 }
289
set_login_ui_result(bool result)290 void set_login_ui_result(bool result) { login_ui_result_ = result; }
291
set_mint_token_flow(scoped_ptr<OAuth2MintTokenFlow> flow)292 void set_mint_token_flow(scoped_ptr<OAuth2MintTokenFlow> flow) {
293 flow_ = flow.Pass();
294 }
295
set_mint_token_result(TestOAuth2MintTokenFlow::ResultType result_type)296 void set_mint_token_result(TestOAuth2MintTokenFlow::ResultType result_type) {
297 set_mint_token_flow(scoped_ptr<TestOAuth2MintTokenFlow>(
298 new TestOAuth2MintTokenFlow(result_type, this))
299 .PassAs<OAuth2MintTokenFlow>());
300 }
301
set_scope_ui_failure(GaiaWebAuthFlow::Failure failure)302 void set_scope_ui_failure(GaiaWebAuthFlow::Failure failure) {
303 scope_ui_result_ = false;
304 scope_ui_failure_ = failure;
305 }
306
set_scope_ui_oauth_error(const std::string & oauth_error)307 void set_scope_ui_oauth_error(const std::string& oauth_error) {
308 scope_ui_result_ = false;
309 scope_ui_failure_ = GaiaWebAuthFlow::OAUTH_ERROR;
310 scope_ui_oauth_error_ = oauth_error;
311 }
312
login_ui_shown() const313 bool login_ui_shown() const { return login_ui_shown_; }
314
scope_ui_shown() const315 bool scope_ui_shown() const { return scope_ui_shown_; }
316
login_access_token() const317 std::string login_access_token() const { return login_access_token_; }
318
StartLoginAccessTokenRequest()319 virtual void StartLoginAccessTokenRequest() OVERRIDE {
320 if (auto_login_access_token_) {
321 if (login_access_token_result_) {
322 OnGetTokenSuccess(login_token_request_.get(),
323 "access_token",
324 base::Time::Now() + base::TimeDelta::FromHours(1LL));
325 } else {
326 GoogleServiceAuthError error(
327 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
328 OnGetTokenFailure(login_token_request_.get(), error);
329 }
330 } else {
331 // Make a request to the token service. The test now must tell
332 // the token service to issue an access token (or an error).
333 IdentityGetAuthTokenFunction::StartLoginAccessTokenRequest();
334 }
335 }
336
ShowLoginPopup()337 virtual void ShowLoginPopup() OVERRIDE {
338 EXPECT_FALSE(login_ui_shown_);
339 login_ui_shown_ = true;
340 if (login_ui_result_)
341 SigninSuccess();
342 else
343 SigninFailed();
344 }
345
ShowOAuthApprovalDialog(const IssueAdviceInfo & issue_advice)346 virtual void ShowOAuthApprovalDialog(
347 const IssueAdviceInfo& issue_advice) OVERRIDE {
348 scope_ui_shown_ = true;
349
350 if (scope_ui_result_) {
351 OnGaiaFlowCompleted(kAccessToken, "3600");
352 } else if (scope_ui_failure_ == GaiaWebAuthFlow::SERVICE_AUTH_ERROR) {
353 GoogleServiceAuthError error(GoogleServiceAuthError::CONNECTION_FAILED);
354 OnGaiaFlowFailure(scope_ui_failure_, error, "");
355 } else {
356 GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
357 OnGaiaFlowFailure(scope_ui_failure_, error, scope_ui_oauth_error_);
358 }
359 }
360
CreateMintTokenFlow(const std::string & login_access_token)361 virtual OAuth2MintTokenFlow* CreateMintTokenFlow(
362 const std::string& login_access_token) OVERRIDE {
363 EXPECT_TRUE(login_access_token_.empty());
364 // Save the login token used to create the flow so tests can see
365 // what account was used.
366 login_access_token_ = login_access_token;
367 return flow_.release();
368 }
369
370 private:
~FakeGetAuthTokenFunction()371 virtual ~FakeGetAuthTokenFunction() {}
372 bool login_access_token_result_;
373 bool auto_login_access_token_;
374 bool login_ui_result_;
375 bool scope_ui_result_;
376 GaiaWebAuthFlow::Failure scope_ui_failure_;
377 std::string scope_ui_oauth_error_;
378 bool login_ui_shown_;
379 bool scope_ui_shown_;
380
381 scoped_ptr<OAuth2MintTokenFlow> flow_;
382
383 std::string login_access_token_;
384 };
385
386 class MockQueuedMintRequest : public IdentityMintRequestQueue::Request {
387 public:
388 MOCK_METHOD1(StartMintToken, void(IdentityMintRequestQueue::MintType));
389 };
390
CreateIds(std::string email,std::string obfid)391 gaia::AccountIds CreateIds(std::string email, std::string obfid) {
392 gaia::AccountIds ids;
393 ids.account_key = email;
394 ids.email = email;
395 ids.gaia = obfid;
396 return ids;
397 }
398
399 class IdentityGetAccountsFunctionTest : public ExtensionBrowserTest {
SetUpCommandLine(CommandLine * command_line)400 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
401 ExtensionBrowserTest::SetUpCommandLine(command_line);
402 command_line->AppendSwitch(switches::kExtensionsMultiAccount);
403 }
404
405 protected:
SetAccountState(gaia::AccountIds ids,bool is_signed_in)406 void SetAccountState(gaia::AccountIds ids, bool is_signed_in) {
407 IdentityAPI::GetFactoryInstance()->Get(profile())->SetAccountStateForTest(
408 ids, is_signed_in);
409 }
410
ExpectGetAccounts(const std::vector<std::string> & accounts)411 testing::AssertionResult ExpectGetAccounts(
412 const std::vector<std::string>& accounts) {
413 scoped_refptr<IdentityGetAccountsFunction> func(
414 new IdentityGetAccountsFunction);
415 func->set_extension(test_util::CreateEmptyExtension(kExtensionId).get());
416 if (!utils::RunFunction(
417 func.get(), std::string("[]"), browser(), utils::NONE)) {
418 return GenerateFailureResult(accounts, NULL)
419 << "getAccounts did not return a result.";
420 }
421 const base::ListValue* callback_arguments = func->GetResultList();
422 if (!callback_arguments)
423 return GenerateFailureResult(accounts, NULL) << "NULL result";
424
425 if (callback_arguments->GetSize() != 1) {
426 return GenerateFailureResult(accounts, NULL)
427 << "Expected 1 argument but got " << callback_arguments->GetSize();
428 }
429
430 const base::ListValue* results;
431 if (!callback_arguments->GetList(0, &results))
432 GenerateFailureResult(accounts, NULL) << "Result was not an array";
433
434 std::set<std::string> result_ids;
435 for (base::ListValue::const_iterator it = results->begin();
436 it != results->end();
437 ++it) {
438 scoped_ptr<api::identity::AccountInfo> info =
439 api::identity::AccountInfo::FromValue(**it);
440 if (info.get())
441 result_ids.insert(info->id);
442 else
443 return GenerateFailureResult(accounts, results);
444 }
445
446 for (std::vector<std::string>::const_iterator it = accounts.begin();
447 it != accounts.end();
448 ++it) {
449 if (result_ids.find(*it) == result_ids.end())
450 return GenerateFailureResult(accounts, results);
451 }
452
453 return testing::AssertionResult(true);
454 }
455
GenerateFailureResult(const::std::vector<std::string> & accounts,const base::ListValue * results)456 testing::AssertionResult GenerateFailureResult(
457 const ::std::vector<std::string>& accounts,
458 const base::ListValue* results) {
459 testing::Message msg("Expected: ");
460 for (std::vector<std::string>::const_iterator it = accounts.begin();
461 it != accounts.end();
462 ++it) {
463 msg << *it << " ";
464 }
465 msg << "Actual: ";
466 if (!results) {
467 msg << "NULL";
468 } else {
469 for (base::ListValue::const_iterator it = results->begin();
470 it != results->end();
471 ++it) {
472 scoped_ptr<api::identity::AccountInfo> info =
473 api::identity::AccountInfo::FromValue(**it);
474 if (info.get())
475 msg << info->id << " ";
476 else
477 msg << *it << "<-" << (*it)->GetType() << " ";
478 }
479 }
480
481 return testing::AssertionFailure(msg);
482 }
483 };
484
IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest,MultiAccountOn)485 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, MultiAccountOn) {
486 EXPECT_TRUE(switches::IsExtensionsMultiAccount());
487 }
488
IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest,NoneSignedIn)489 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, NoneSignedIn) {
490 EXPECT_TRUE(ExpectGetAccounts(std::vector<std::string>()));
491 }
492
IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest,PrimaryAccountSignedIn)493 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest,
494 PrimaryAccountSignedIn) {
495 SetAccountState(CreateIds("primary@example.com", "1"), true);
496 std::vector<std::string> primary;
497 primary.push_back("1");
498 EXPECT_TRUE(ExpectGetAccounts(primary));
499 }
500
IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest,TwoAccountsSignedIn)501 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, TwoAccountsSignedIn) {
502 SetAccountState(CreateIds("primary@example.com", "1"), true);
503 SetAccountState(CreateIds("secondary@example.com", "2"), true);
504 std::vector<std::string> two_accounts;
505 two_accounts.push_back("1");
506 two_accounts.push_back("2");
507 EXPECT_TRUE(ExpectGetAccounts(two_accounts));
508 }
509
510 class IdentityOldProfilesGetAccountsFunctionTest
511 : public IdentityGetAccountsFunctionTest {
SetUpCommandLine(CommandLine * command_line)512 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
513 // Don't add the multi-account switch that parent class would have.
514 }
515 };
516
IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest,MultiAccountOff)517 IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest,
518 MultiAccountOff) {
519 EXPECT_FALSE(switches::IsExtensionsMultiAccount());
520 }
521
IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest,TwoAccountsSignedIn)522 IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest,
523 TwoAccountsSignedIn) {
524 SetAccountState(CreateIds("primary@example.com", "1"), true);
525 SetAccountState(CreateIds("secondary@example.com", "2"), true);
526 std::vector<std::string> only_primary;
527 only_primary.push_back("1");
528 EXPECT_TRUE(ExpectGetAccounts(only_primary));
529 }
530
531 class IdentityGetProfileUserInfoFunctionTest : public ExtensionBrowserTest {
532 protected:
RunGetProfileUserInfo()533 scoped_ptr<api::identity::ProfileUserInfo> RunGetProfileUserInfo() {
534 scoped_refptr<IdentityGetProfileUserInfoFunction> func(
535 new IdentityGetProfileUserInfoFunction);
536 func->set_extension(test_util::CreateEmptyExtension(kExtensionId).get());
537 scoped_ptr<base::Value> value(
538 utils::RunFunctionAndReturnSingleResult(func.get(), "[]", browser()));
539 return api::identity::ProfileUserInfo::FromValue(*value.get());
540 }
541
RunGetProfileUserInfoWithEmail()542 scoped_ptr<api::identity::ProfileUserInfo> RunGetProfileUserInfoWithEmail() {
543 scoped_refptr<IdentityGetProfileUserInfoFunction> func(
544 new IdentityGetProfileUserInfoFunction);
545 func->set_extension(CreateExtensionWithEmailPermission());
546 scoped_ptr<base::Value> value(
547 utils::RunFunctionAndReturnSingleResult(func.get(), "[]", browser()));
548 return api::identity::ProfileUserInfo::FromValue(*value.get());
549 }
550
551 private:
CreateExtensionWithEmailPermission()552 scoped_refptr<Extension> CreateExtensionWithEmailPermission() {
553 scoped_ptr<base::DictionaryValue> test_extension_value(
554 utils::ParseDictionary(
555 "{\"name\": \"Test\", \"version\": \"1.0\", "
556 "\"permissions\": [\"identity.email\"]}"));
557 return utils::CreateExtension(test_extension_value.get());
558 }
559 };
560
IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest,NotSignedIn)561 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest, NotSignedIn) {
562 scoped_ptr<api::identity::ProfileUserInfo> info =
563 RunGetProfileUserInfoWithEmail();
564 EXPECT_TRUE(info->email.empty());
565 EXPECT_TRUE(info->id.empty());
566 }
567
IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest,SignedIn)568 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest, SignedIn) {
569 profile()->GetPrefs()
570 ->SetString(prefs::kGoogleServicesUsername, "president@example.com");
571 profile()->GetPrefs()
572 ->SetString(prefs::kGoogleServicesUserAccountId, "12345");
573
574 scoped_ptr<api::identity::ProfileUserInfo> info =
575 RunGetProfileUserInfoWithEmail();
576 EXPECT_EQ("president@example.com", info->email);
577 EXPECT_EQ("12345", info->id);
578 }
579
IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest,NotSignedInNoEmail)580 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest,
581 NotSignedInNoEmail) {
582 scoped_ptr<api::identity::ProfileUserInfo> info = RunGetProfileUserInfo();
583 EXPECT_TRUE(info->email.empty());
584 EXPECT_TRUE(info->id.empty());
585 }
586
IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest,SignedInNoEmail)587 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest,
588 SignedInNoEmail) {
589 profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
590 "president@example.com");
591 profile()->GetPrefs()->SetString(prefs::kGoogleServicesUserAccountId,
592 "12345");
593
594 scoped_ptr<api::identity::ProfileUserInfo> info = RunGetProfileUserInfo();
595 EXPECT_TRUE(info->email.empty());
596 EXPECT_EQ("12345", info->id);
597 }
598
599 class GetAuthTokenFunctionTest : public AsyncExtensionBrowserTest {
600 public:
SetUpCommandLine(CommandLine * command_line)601 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
602 AsyncExtensionBrowserTest::SetUpCommandLine(command_line);
603 command_line->AppendSwitch(switches::kExtensionsMultiAccount);
604 }
605
SetUpInProcessBrowserTestFixture()606 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
607 AsyncExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
608
609 will_create_browser_context_services_subscription_ =
610 BrowserContextDependencyManager::GetInstance()
611 ->RegisterWillCreateBrowserContextServicesCallbackForTesting(
612 base::Bind(&GetAuthTokenFunctionTest::
613 OnWillCreateBrowserContextServices,
614 base::Unretained(this)))
615 .Pass();
616 }
617
OnWillCreateBrowserContextServices(content::BrowserContext * context)618 void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
619 // Replace the signin manager and token service with fakes. Do this ahead of
620 // creating the browser so that a bunch of classes don't register as
621 // observers and end up needing to unregister when the fake is substituted.
622 SigninManagerFactory::GetInstance()->SetTestingFactory(
623 context, &FakeSigninManagerBase::Build);
624 ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory(
625 context, &BuildFakeProfileOAuth2TokenService);
626 AccountReconcilorFactory::GetInstance()->SetTestingFactory(
627 context, &FakeAccountReconcilor::Build);
628 }
629
SetUpOnMainThread()630 virtual void SetUpOnMainThread() OVERRIDE {
631 AsyncExtensionBrowserTest::SetUpOnMainThread();
632
633 // Grab references to the fake signin manager and token service.
634 signin_manager_ = static_cast<FakeSigninManagerForTesting*>(
635 SigninManagerFactory::GetInstance()->GetForProfile(profile()));
636 ASSERT_TRUE(signin_manager_);
637 token_service_ = static_cast<FakeProfileOAuth2TokenService*>(
638 ProfileOAuth2TokenServiceFactory::GetInstance()->GetForProfile(
639 profile()));
640 ASSERT_TRUE(token_service_);
641 }
642
SignIn(const std::string account_key)643 void SignIn(const std::string account_key) {
644 #if defined(OS_CHROMEOS)
645 signin_manager_->SetAuthenticatedUsername(account_key);
646 #else
647 signin_manager_->SignIn(account_key, "password");
648 #endif
649 token_service_->IssueRefreshTokenForUser(account_key, "refresh_token");
650 }
651
IssueLoginRefreshTokenForAccount(const std::string account_key)652 void IssueLoginRefreshTokenForAccount(const std::string account_key) {
653 token_service_->IssueRefreshTokenForUser(account_key, "refresh_token");
654 }
655
IssueLoginAccessTokenForAccount(const std::string account_key)656 void IssueLoginAccessTokenForAccount(const std::string account_key) {
657 token_service_->IssueAllTokensForAccount(
658 account_key,
659 "access_token-" + account_key,
660 base::Time::Now() + base::TimeDelta::FromSeconds(3600));
661 }
662
SetAccountState(gaia::AccountIds ids,bool is_signed_in)663 void SetAccountState(gaia::AccountIds ids, bool is_signed_in) {
664 IdentityAPI::GetFactoryInstance()->Get(profile())->SetAccountStateForTest(
665 ids, is_signed_in);
666 }
667
668 protected:
669 enum OAuth2Fields {
670 NONE = 0,
671 CLIENT_ID = 1,
672 SCOPES = 2,
673 AS_COMPONENT = 4
674 };
675
676 FakeSigninManagerForTesting* signin_manager_;
677 FakeProfileOAuth2TokenService* token_service_;
678
~GetAuthTokenFunctionTest()679 virtual ~GetAuthTokenFunctionTest() {}
680
681 // Helper to create an extension with specific OAuth2Info fields set.
682 // |fields_to_set| should be computed by using fields of Oauth2Fields enum.
CreateExtension(int fields_to_set)683 const Extension* CreateExtension(int fields_to_set) {
684 const Extension* ext;
685 base::FilePath manifest_path =
686 test_data_dir_.AppendASCII("platform_apps/oauth2");
687 base::FilePath component_manifest_path =
688 test_data_dir_.AppendASCII("packaged_app/component_oauth2");
689 if ((fields_to_set & AS_COMPONENT) == 0)
690 ext = LoadExtension(manifest_path);
691 else
692 ext = LoadExtensionAsComponent(component_manifest_path);
693 OAuth2Info& oauth2_info =
694 const_cast<OAuth2Info&>(OAuth2Info::GetOAuth2Info(ext));
695 if ((fields_to_set & CLIENT_ID) != 0)
696 oauth2_info.client_id = "client1";
697 if ((fields_to_set & SCOPES) != 0) {
698 oauth2_info.scopes.push_back("scope1");
699 oauth2_info.scopes.push_back("scope2");
700 }
701
702 extension_id_ = ext->id();
703 oauth_scopes_ = std::set<std::string>(oauth2_info.scopes.begin(),
704 oauth2_info.scopes.end());
705 return ext;
706 }
707
id_api()708 IdentityAPI* id_api() {
709 return IdentityAPI::GetFactoryInstance()->Get(browser()->profile());
710 }
711
GetPrimaryAccountId()712 const std::string GetPrimaryAccountId() {
713 SigninManagerBase* signin_manager =
714 SigninManagerFactory::GetForProfile(browser()->profile());
715 return signin_manager->GetAuthenticatedAccountId();
716 }
717
SetCachedToken(const IdentityTokenCacheValue & token_data)718 void SetCachedToken(const IdentityTokenCacheValue& token_data) {
719 ExtensionTokenKey key(extension_id_, GetPrimaryAccountId(), oauth_scopes_);
720 id_api()->SetCachedToken(key, token_data);
721 }
722
GetCachedToken(std::string account_id)723 const IdentityTokenCacheValue& GetCachedToken(std::string account_id) {
724 if (account_id.empty())
725 account_id = GetPrimaryAccountId();
726 ExtensionTokenKey key(extension_id_, account_id, oauth_scopes_);
727 return id_api()->GetCachedToken(key);
728 }
729
QueueRequestStart(IdentityMintRequestQueue::MintType type,IdentityMintRequestQueue::Request * request)730 void QueueRequestStart(IdentityMintRequestQueue::MintType type,
731 IdentityMintRequestQueue::Request* request) {
732 ExtensionTokenKey key(extension_id_, GetPrimaryAccountId(), oauth_scopes_);
733 id_api()->mint_queue()->RequestStart(type, key, request);
734 }
735
QueueRequestComplete(IdentityMintRequestQueue::MintType type,IdentityMintRequestQueue::Request * request)736 void QueueRequestComplete(IdentityMintRequestQueue::MintType type,
737 IdentityMintRequestQueue::Request* request) {
738 ExtensionTokenKey key(extension_id_, GetPrimaryAccountId(), oauth_scopes_);
739 id_api()->mint_queue()->RequestComplete(type, key, request);
740 }
741
742 private:
743 std::string extension_id_;
744 std::set<std::string> oauth_scopes_;
745
746 scoped_ptr<base::CallbackList<void(content::BrowserContext*)>::Subscription>
747 will_create_browser_context_services_subscription_;
748 };
749
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NoClientId)750 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
751 NoClientId) {
752 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
753 func->set_extension(CreateExtension(SCOPES));
754 std::string error = utils::RunFunctionAndReturnError(
755 func.get(), "[{}]", browser());
756 EXPECT_EQ(std::string(errors::kInvalidClientId), error);
757 EXPECT_FALSE(func->login_ui_shown());
758 EXPECT_FALSE(func->scope_ui_shown());
759 }
760
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NoScopes)761 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
762 NoScopes) {
763 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
764 func->set_extension(CreateExtension(CLIENT_ID));
765 std::string error = utils::RunFunctionAndReturnError(
766 func.get(), "[{}]", browser());
767 EXPECT_EQ(std::string(errors::kInvalidScopes), error);
768 EXPECT_FALSE(func->login_ui_shown());
769 EXPECT_FALSE(func->scope_ui_shown());
770 }
771
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveNotSignedIn)772 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
773 NonInteractiveNotSignedIn) {
774 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
775 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
776 std::string error = utils::RunFunctionAndReturnError(
777 func.get(), "[{}]", browser());
778 EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
779 EXPECT_FALSE(func->login_ui_shown());
780 EXPECT_FALSE(func->scope_ui_shown());
781 }
782
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveMintFailure)783 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
784 NonInteractiveMintFailure) {
785 SignIn("primary@example.com");
786 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
787 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
788 func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE);
789 std::string error =
790 utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
791 EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
792 EXPECT_FALSE(func->login_ui_shown());
793 EXPECT_FALSE(func->scope_ui_shown());
794 }
795
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveLoginAccessTokenFailure)796 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
797 NonInteractiveLoginAccessTokenFailure) {
798 SignIn("primary@example.com");
799 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
800 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
801 func->set_login_access_token_result(false);
802 std::string error = utils::RunFunctionAndReturnError(
803 func.get(), "[{}]", browser());
804 EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
805 }
806
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveMintAdviceSuccess)807 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
808 NonInteractiveMintAdviceSuccess) {
809 SignIn("primary@example.com");
810 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
811 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
812 func->set_extension(extension.get());
813 func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
814 std::string error =
815 utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
816 EXPECT_EQ(std::string(errors::kNoGrant), error);
817 EXPECT_FALSE(func->login_ui_shown());
818 EXPECT_FALSE(func->scope_ui_shown());
819
820 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_ADVICE,
821 GetCachedToken(std::string()).status());
822 }
823
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveMintBadCredentials)824 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
825 NonInteractiveMintBadCredentials) {
826 SignIn("primary@example.com");
827 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
828 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
829 func->set_mint_token_result(
830 TestOAuth2MintTokenFlow::MINT_TOKEN_BAD_CREDENTIALS);
831 std::string error =
832 utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
833 EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
834 EXPECT_FALSE(func->login_ui_shown());
835 EXPECT_FALSE(func->scope_ui_shown());
836 }
837
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveMintServiceError)838 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
839 NonInteractiveMintServiceError) {
840 SignIn("primary@example.com");
841 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
842 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
843 func->set_mint_token_result(
844 TestOAuth2MintTokenFlow::MINT_TOKEN_SERVICE_ERROR);
845 std::string error =
846 utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
847 EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
848 EXPECT_FALSE(func->login_ui_shown());
849 EXPECT_FALSE(func->scope_ui_shown());
850 }
851
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NoOptionsSuccess)852 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
853 NoOptionsSuccess) {
854 SignIn("primary@example.com");
855 #if defined(OS_WIN) && defined(USE_ASH)
856 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
857 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
858 return;
859 #endif
860
861 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
862 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
863 func->set_extension(extension.get());
864 func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
865 scoped_ptr<base::Value> value(
866 utils::RunFunctionAndReturnSingleResult(func.get(), "[]", browser()));
867 std::string access_token;
868 EXPECT_TRUE(value->GetAsString(&access_token));
869 EXPECT_EQ(std::string(kAccessToken), access_token);
870 EXPECT_FALSE(func->login_ui_shown());
871 EXPECT_FALSE(func->scope_ui_shown());
872 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
873 GetCachedToken(std::string()).status());
874 }
875
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveSuccess)876 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
877 NonInteractiveSuccess) {
878 SignIn("primary@example.com");
879 #if defined(OS_WIN) && defined(USE_ASH)
880 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
881 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
882 return;
883 #endif
884
885 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
886 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
887 func->set_extension(extension.get());
888 func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
889 scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
890 func.get(), "[{}]", browser()));
891 std::string access_token;
892 EXPECT_TRUE(value->GetAsString(&access_token));
893 EXPECT_EQ(std::string(kAccessToken), access_token);
894 EXPECT_FALSE(func->login_ui_shown());
895 EXPECT_FALSE(func->scope_ui_shown());
896 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
897 GetCachedToken(std::string()).status());
898 }
899
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveLoginCanceled)900 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
901 InteractiveLoginCanceled) {
902 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
903 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
904 func->set_login_ui_result(false);
905 std::string error = utils::RunFunctionAndReturnError(
906 func.get(), "[{\"interactive\": true}]", browser());
907 EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
908 EXPECT_TRUE(func->login_ui_shown());
909 EXPECT_FALSE(func->scope_ui_shown());
910 }
911
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveMintBadCredentialsLoginCanceled)912 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
913 InteractiveMintBadCredentialsLoginCanceled) {
914 SignIn("primary@example.com");
915 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
916 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
917 func->set_mint_token_result(
918 TestOAuth2MintTokenFlow::MINT_TOKEN_BAD_CREDENTIALS);
919 func->set_login_ui_result(false);
920 std::string error = utils::RunFunctionAndReturnError(
921 func.get(), "[{\"interactive\": true}]", browser());
922 EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
923 EXPECT_TRUE(func->login_ui_shown());
924 EXPECT_FALSE(func->scope_ui_shown());
925 }
926
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveLoginSuccessNoToken)927 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
928 InteractiveLoginSuccessNoToken) {
929 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
930 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
931 func->set_login_ui_result(false);
932 std::string error = utils::RunFunctionAndReturnError(
933 func.get(), "[{\"interactive\": true}]", browser());
934 EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
935 EXPECT_TRUE(func->login_ui_shown());
936 EXPECT_FALSE(func->scope_ui_shown());
937 }
938
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveLoginSuccessMintFailure)939 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
940 InteractiveLoginSuccessMintFailure) {
941 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
942 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
943 func->set_login_ui_result(true);
944 func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE);
945 std::string error = utils::RunFunctionAndReturnError(
946 func.get(), "[{\"interactive\": true}]", browser());
947 EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
948 EXPECT_TRUE(func->login_ui_shown());
949 EXPECT_FALSE(func->scope_ui_shown());
950 }
951
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveLoginSuccessLoginAccessTokenFailure)952 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
953 InteractiveLoginSuccessLoginAccessTokenFailure) {
954 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
955 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
956 func->set_login_ui_result(true);
957 func->set_login_access_token_result(false);
958 std::string error = utils::RunFunctionAndReturnError(
959 func.get(), "[{\"interactive\": true}]", browser());
960 EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
961 EXPECT_TRUE(func->login_ui_shown());
962 EXPECT_FALSE(func->scope_ui_shown());
963 }
964
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveLoginSuccessMintSuccess)965 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
966 InteractiveLoginSuccessMintSuccess) {
967 // TODO(courage): verify that account_id in token service requests
968 // is correct once manual token minting for tests is implemented.
969 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
970 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
971 func->set_login_ui_result(true);
972 func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
973 scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
974 func.get(), "[{\"interactive\": true}]", browser()));
975 std::string access_token;
976 EXPECT_TRUE(value->GetAsString(&access_token));
977 EXPECT_EQ(std::string(kAccessToken), access_token);
978 EXPECT_TRUE(func->login_ui_shown());
979 EXPECT_FALSE(func->scope_ui_shown());
980 }
981
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveLoginSuccessApprovalAborted)982 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
983 InteractiveLoginSuccessApprovalAborted) {
984 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
985 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
986 func->set_login_ui_result(true);
987 func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
988 func->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED);
989 std::string error = utils::RunFunctionAndReturnError(
990 func.get(), "[{\"interactive\": true}]", browser());
991 EXPECT_EQ(std::string(errors::kUserRejected), error);
992 EXPECT_TRUE(func->login_ui_shown());
993 EXPECT_TRUE(func->scope_ui_shown());
994 }
995
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveLoginSuccessApprovalSuccess)996 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
997 InteractiveLoginSuccessApprovalSuccess) {
998 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
999 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1000 func->set_extension(extension.get());
1001 func->set_login_ui_result(true);
1002 func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1003
1004 scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1005 func.get(), "[{\"interactive\": true}]", browser()));
1006 std::string access_token;
1007 EXPECT_TRUE(value->GetAsString(&access_token));
1008 EXPECT_EQ(std::string(kAccessToken), access_token);
1009 EXPECT_TRUE(func->login_ui_shown());
1010 EXPECT_TRUE(func->scope_ui_shown());
1011 }
1012
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveApprovalAborted)1013 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1014 InteractiveApprovalAborted) {
1015 SignIn("primary@example.com");
1016 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1017 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
1018 func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1019 func->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED);
1020 std::string error = utils::RunFunctionAndReturnError(
1021 func.get(), "[{\"interactive\": true}]", browser());
1022 EXPECT_EQ(std::string(errors::kUserRejected), error);
1023 EXPECT_FALSE(func->login_ui_shown());
1024 EXPECT_TRUE(func->scope_ui_shown());
1025 }
1026
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveApprovalLoadFailed)1027 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1028 InteractiveApprovalLoadFailed) {
1029 SignIn("primary@example.com");
1030 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1031 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
1032 func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1033 func->set_scope_ui_failure(GaiaWebAuthFlow::LOAD_FAILED);
1034 std::string error = utils::RunFunctionAndReturnError(
1035 func.get(), "[{\"interactive\": true}]", browser());
1036 EXPECT_EQ(std::string(errors::kPageLoadFailure), error);
1037 EXPECT_FALSE(func->login_ui_shown());
1038 EXPECT_TRUE(func->scope_ui_shown());
1039 }
1040
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveApprovalInvalidRedirect)1041 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1042 InteractiveApprovalInvalidRedirect) {
1043 SignIn("primary@example.com");
1044 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1045 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
1046 func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1047 func->set_scope_ui_failure(GaiaWebAuthFlow::INVALID_REDIRECT);
1048 std::string error = utils::RunFunctionAndReturnError(
1049 func.get(), "[{\"interactive\": true}]", browser());
1050 EXPECT_EQ(std::string(errors::kInvalidRedirect), error);
1051 EXPECT_FALSE(func->login_ui_shown());
1052 EXPECT_TRUE(func->scope_ui_shown());
1053 }
1054
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveApprovalConnectionFailure)1055 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1056 InteractiveApprovalConnectionFailure) {
1057 SignIn("primary@example.com");
1058 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1059 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
1060 func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1061 func->set_scope_ui_failure(GaiaWebAuthFlow::SERVICE_AUTH_ERROR);
1062 std::string error = utils::RunFunctionAndReturnError(
1063 func.get(), "[{\"interactive\": true}]", browser());
1064 EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
1065 EXPECT_FALSE(func->login_ui_shown());
1066 EXPECT_TRUE(func->scope_ui_shown());
1067 }
1068
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveApprovalOAuthErrors)1069 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1070 InteractiveApprovalOAuthErrors) {
1071 SignIn("primary@example.com");
1072 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1073
1074 std::map<std::string, std::string> error_map;
1075 error_map.insert(std::make_pair("access_denied", errors::kUserRejected));
1076 error_map.insert(std::make_pair("invalid_scope", errors::kInvalidScopes));
1077 error_map.insert(std::make_pair(
1078 "unmapped_error", std::string(errors::kAuthFailure) + "unmapped_error"));
1079
1080 for (std::map<std::string, std::string>::const_iterator
1081 it = error_map.begin();
1082 it != error_map.end();
1083 ++it) {
1084 scoped_refptr<FakeGetAuthTokenFunction> func(
1085 new FakeGetAuthTokenFunction());
1086 func->set_extension(extension.get());
1087 // Make sure we don't get a cached issue_advice result, which would cause
1088 // flow to be leaked.
1089 id_api()->EraseAllCachedTokens();
1090 func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1091 func->set_scope_ui_oauth_error(it->first);
1092 std::string error = utils::RunFunctionAndReturnError(
1093 func.get(), "[{\"interactive\": true}]", browser());
1094 EXPECT_EQ(it->second, error);
1095 EXPECT_FALSE(func->login_ui_shown());
1096 EXPECT_TRUE(func->scope_ui_shown());
1097 }
1098 }
1099
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveApprovalSuccess)1100 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1101 InteractiveApprovalSuccess) {
1102 SignIn("primary@example.com");
1103 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1104 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1105 func->set_extension(extension.get());
1106 func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1107
1108 scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1109 func.get(), "[{\"interactive\": true}]", browser()));
1110 std::string access_token;
1111 EXPECT_TRUE(value->GetAsString(&access_token));
1112 EXPECT_EQ(std::string(kAccessToken), access_token);
1113 EXPECT_FALSE(func->login_ui_shown());
1114 EXPECT_TRUE(func->scope_ui_shown());
1115
1116 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
1117 GetCachedToken(std::string()).status());
1118 }
1119
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NoninteractiveQueue)1120 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoninteractiveQueue) {
1121 SignIn("primary@example.com");
1122 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1123 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1124 func->set_extension(extension.get());
1125
1126 // Create a fake request to block the queue.
1127 MockQueuedMintRequest queued_request;
1128 IdentityMintRequestQueue::MintType type =
1129 IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE;
1130
1131 EXPECT_CALL(queued_request, StartMintToken(type)).Times(1);
1132 QueueRequestStart(type, &queued_request);
1133
1134 // The real request will start processing, but wait in the queue behind
1135 // the blocker.
1136 RunFunctionAsync(func.get(), "[{}]");
1137 // Verify that we have fetched the login token at this point.
1138 testing::Mock::VerifyAndClearExpectations(func.get());
1139
1140 // The flow will be created after the first queued request clears.
1141 func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
1142
1143 QueueRequestComplete(type, &queued_request);
1144
1145 scoped_ptr<base::Value> value(WaitForSingleResult(func.get()));
1146 std::string access_token;
1147 EXPECT_TRUE(value->GetAsString(&access_token));
1148 EXPECT_EQ(std::string(kAccessToken), access_token);
1149 EXPECT_FALSE(func->login_ui_shown());
1150 EXPECT_FALSE(func->scope_ui_shown());
1151 }
1152
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveQueue)1153 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveQueue) {
1154 SignIn("primary@example.com");
1155 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1156 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1157 func->set_extension(extension.get());
1158
1159 // Create a fake request to block the queue.
1160 MockQueuedMintRequest queued_request;
1161 IdentityMintRequestQueue::MintType type =
1162 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE;
1163
1164 EXPECT_CALL(queued_request, StartMintToken(type)).Times(1);
1165 QueueRequestStart(type, &queued_request);
1166
1167 // The real request will start processing, but wait in the queue behind
1168 // the blocker.
1169 func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1170 RunFunctionAsync(func.get(), "[{\"interactive\": true}]");
1171 // Verify that we have fetched the login token and run the first flow.
1172 testing::Mock::VerifyAndClearExpectations(func.get());
1173 EXPECT_FALSE(func->scope_ui_shown());
1174
1175 // The UI will be displayed and a token retrieved after the first
1176 // queued request clears.
1177 QueueRequestComplete(type, &queued_request);
1178
1179 scoped_ptr<base::Value> value(WaitForSingleResult(func.get()));
1180 std::string access_token;
1181 EXPECT_TRUE(value->GetAsString(&access_token));
1182 EXPECT_EQ(std::string(kAccessToken), access_token);
1183 EXPECT_FALSE(func->login_ui_shown());
1184 EXPECT_TRUE(func->scope_ui_shown());
1185 }
1186
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveQueueShutdown)1187 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveQueueShutdown) {
1188 SignIn("primary@example.com");
1189 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1190 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1191 func->set_extension(extension.get());
1192
1193 // Create a fake request to block the queue.
1194 MockQueuedMintRequest queued_request;
1195 IdentityMintRequestQueue::MintType type =
1196 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE;
1197
1198 EXPECT_CALL(queued_request, StartMintToken(type)).Times(1);
1199 QueueRequestStart(type, &queued_request);
1200
1201 // The real request will start processing, but wait in the queue behind
1202 // the blocker.
1203 func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1204 RunFunctionAsync(func.get(), "[{\"interactive\": true}]");
1205 // Verify that we have fetched the login token and run the first flow.
1206 testing::Mock::VerifyAndClearExpectations(func.get());
1207 EXPECT_FALSE(func->scope_ui_shown());
1208
1209 // After the request is canceled, the function will complete.
1210 func->OnShutdown();
1211 EXPECT_EQ(std::string(errors::kCanceled), WaitForError(func.get()));
1212 EXPECT_FALSE(func->login_ui_shown());
1213 EXPECT_FALSE(func->scope_ui_shown());
1214
1215 QueueRequestComplete(type, &queued_request);
1216 }
1217
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NoninteractiveShutdown)1218 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoninteractiveShutdown) {
1219 SignIn("primary@example.com");
1220 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1221 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1222 func->set_extension(extension.get());
1223
1224 scoped_ptr<TestHangOAuth2MintTokenFlow> flow(
1225 new TestHangOAuth2MintTokenFlow());
1226 func->set_mint_token_flow(flow.PassAs<OAuth2MintTokenFlow>());
1227 RunFunctionAsync(func.get(), "[{\"interactive\": false}]");
1228
1229 // After the request is canceled, the function will complete.
1230 func->OnShutdown();
1231 EXPECT_EQ(std::string(errors::kCanceled), WaitForError(func.get()));
1232 }
1233
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveQueuedNoninteractiveFails)1234 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1235 InteractiveQueuedNoninteractiveFails) {
1236 SignIn("primary@example.com");
1237 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1238 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1239 func->set_extension(extension.get());
1240
1241 // Create a fake request to block the interactive queue.
1242 MockQueuedMintRequest queued_request;
1243 IdentityMintRequestQueue::MintType type =
1244 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE;
1245
1246 EXPECT_CALL(queued_request, StartMintToken(type)).Times(1);
1247 QueueRequestStart(type, &queued_request);
1248
1249 // Non-interactive requests fail without hitting GAIA, because a
1250 // consent UI is known to be up.
1251 std::string error = utils::RunFunctionAndReturnError(
1252 func.get(), "[{}]", browser());
1253 EXPECT_EQ(std::string(errors::kNoGrant), error);
1254 EXPECT_FALSE(func->login_ui_shown());
1255 EXPECT_FALSE(func->scope_ui_shown());
1256
1257 QueueRequestComplete(type, &queued_request);
1258 }
1259
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveCacheHit)1260 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1261 NonInteractiveCacheHit) {
1262 SignIn("primary@example.com");
1263 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1264 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1265 func->set_extension(extension.get());
1266
1267 // pre-populate the cache with a token
1268 IdentityTokenCacheValue token(kAccessToken,
1269 base::TimeDelta::FromSeconds(3600));
1270 SetCachedToken(token);
1271
1272 // Get a token. Should not require a GAIA request.
1273 scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1274 func.get(), "[{}]", browser()));
1275 std::string access_token;
1276 EXPECT_TRUE(value->GetAsString(&access_token));
1277 EXPECT_EQ(std::string(kAccessToken), access_token);
1278 EXPECT_FALSE(func->login_ui_shown());
1279 EXPECT_FALSE(func->scope_ui_shown());
1280 }
1281
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveIssueAdviceCacheHit)1282 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1283 NonInteractiveIssueAdviceCacheHit) {
1284 SignIn("primary@example.com");
1285 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1286 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1287 func->set_extension(extension.get());
1288
1289 // pre-populate the cache with advice
1290 IssueAdviceInfo info;
1291 IdentityTokenCacheValue token(info);
1292 SetCachedToken(token);
1293
1294 // Should return an error without a GAIA request.
1295 std::string error = utils::RunFunctionAndReturnError(
1296 func.get(), "[{}]", browser());
1297 EXPECT_EQ(std::string(errors::kNoGrant), error);
1298 EXPECT_FALSE(func->login_ui_shown());
1299 EXPECT_FALSE(func->scope_ui_shown());
1300 }
1301
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveCacheHit)1302 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1303 InteractiveCacheHit) {
1304 SignIn("primary@example.com");
1305 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1306 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1307 func->set_extension(extension.get());
1308
1309 // Create a fake request to block the queue.
1310 MockQueuedMintRequest queued_request;
1311 IdentityMintRequestQueue::MintType type =
1312 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE;
1313
1314 EXPECT_CALL(queued_request, StartMintToken(type)).Times(1);
1315 QueueRequestStart(type, &queued_request);
1316
1317 // The real request will start processing, but wait in the queue behind
1318 // the blocker.
1319 func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1320 RunFunctionAsync(func.get(), "[{\"interactive\": true}]");
1321
1322 // Populate the cache with a token while the request is blocked.
1323 IdentityTokenCacheValue token(kAccessToken,
1324 base::TimeDelta::FromSeconds(3600));
1325 SetCachedToken(token);
1326
1327 // When we wake up the request, it returns the cached token without
1328 // displaying a UI, or hitting GAIA.
1329
1330 QueueRequestComplete(type, &queued_request);
1331
1332 scoped_ptr<base::Value> value(WaitForSingleResult(func.get()));
1333 std::string access_token;
1334 EXPECT_TRUE(value->GetAsString(&access_token));
1335 EXPECT_EQ(std::string(kAccessToken), access_token);
1336 EXPECT_FALSE(func->login_ui_shown());
1337 EXPECT_FALSE(func->scope_ui_shown());
1338 }
1339
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,LoginInvalidatesTokenCache)1340 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1341 LoginInvalidatesTokenCache) {
1342 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1343 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1344 func->set_extension(extension.get());
1345
1346 // pre-populate the cache with a token
1347 IdentityTokenCacheValue token(kAccessToken,
1348 base::TimeDelta::FromSeconds(3600));
1349 SetCachedToken(token);
1350
1351 // Because the user is not signed in, the token will be removed,
1352 // and we'll hit GAIA for new tokens.
1353 func->set_login_ui_result(true);
1354 func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1355
1356 scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1357 func.get(), "[{\"interactive\": true}]", browser()));
1358 std::string access_token;
1359 EXPECT_TRUE(value->GetAsString(&access_token));
1360 EXPECT_EQ(std::string(kAccessToken), access_token);
1361 EXPECT_TRUE(func->login_ui_shown());
1362 EXPECT_TRUE(func->scope_ui_shown());
1363 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
1364 GetCachedToken(std::string()).status());
1365 }
1366
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,ComponentWithChromeClientId)1367 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ComponentWithChromeClientId) {
1368 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1369 scoped_refptr<const Extension> extension(
1370 CreateExtension(SCOPES | AS_COMPONENT));
1371 func->set_extension(extension.get());
1372 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension.get());
1373 EXPECT_TRUE(oauth2_info.client_id.empty());
1374 EXPECT_FALSE(func->GetOAuth2ClientId().empty());
1375 EXPECT_NE("client1", func->GetOAuth2ClientId());
1376 }
1377
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,ComponentWithNormalClientId)1378 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ComponentWithNormalClientId) {
1379 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1380 scoped_refptr<const Extension> extension(
1381 CreateExtension(CLIENT_ID | SCOPES | AS_COMPONENT));
1382 func->set_extension(extension.get());
1383 EXPECT_EQ("client1", func->GetOAuth2ClientId());
1384 }
1385
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,MultiDefaultUser)1386 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiDefaultUser) {
1387 SignIn("primary@example.com");
1388 SetAccountState(CreateIds("primary@example.com", "1"), true);
1389 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1390
1391 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1392 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1393 func->set_extension(extension.get());
1394 func->set_auto_login_access_token(false);
1395 func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
1396
1397 RunFunctionAsync(func.get(), "[{}]");
1398
1399 IssueLoginAccessTokenForAccount("primary@example.com");
1400
1401 scoped_ptr<base::Value> value(WaitForSingleResult(func.get()));
1402 std::string access_token;
1403 EXPECT_TRUE(value->GetAsString(&access_token));
1404 EXPECT_EQ(std::string(kAccessToken), access_token);
1405 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
1406 GetCachedToken(std::string()).status());
1407 EXPECT_EQ("access_token-primary@example.com", func->login_access_token());
1408 }
1409
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,MultiPrimaryUser)1410 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiPrimaryUser) {
1411 SignIn("primary@example.com");
1412 IssueLoginRefreshTokenForAccount("secondary@example.com");
1413 SetAccountState(CreateIds("primary@example.com", "1"), true);
1414 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1415
1416 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1417 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1418 func->set_extension(extension.get());
1419 func->set_auto_login_access_token(false);
1420 func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
1421
1422 RunFunctionAsync(func.get(), "[{\"account\": { \"id\": \"1\" } }]");
1423
1424 IssueLoginAccessTokenForAccount("primary@example.com");
1425
1426 scoped_ptr<base::Value> value(WaitForSingleResult(func.get()));
1427 std::string access_token;
1428 EXPECT_TRUE(value->GetAsString(&access_token));
1429 EXPECT_EQ(std::string(kAccessToken), access_token);
1430 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
1431 GetCachedToken(std::string()).status());
1432 EXPECT_EQ("access_token-primary@example.com", func->login_access_token());
1433 }
1434
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,MultiSecondaryUser)1435 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiSecondaryUser) {
1436 SignIn("primary@example.com");
1437 IssueLoginRefreshTokenForAccount("secondary@example.com");
1438 SetAccountState(CreateIds("primary@example.com", "1"), true);
1439 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1440
1441 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1442 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1443 func->set_extension(extension.get());
1444 func->set_auto_login_access_token(false);
1445 func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
1446
1447 RunFunctionAsync(func.get(), "[{\"account\": { \"id\": \"2\" } }]");
1448
1449 IssueLoginAccessTokenForAccount("secondary@example.com");
1450
1451 scoped_ptr<base::Value> value(WaitForSingleResult(func.get()));
1452 std::string access_token;
1453 EXPECT_TRUE(value->GetAsString(&access_token));
1454 EXPECT_EQ(std::string(kAccessToken), access_token);
1455 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
1456 GetCachedToken("secondary@example.com").status());
1457 EXPECT_EQ("access_token-secondary@example.com", func->login_access_token());
1458 }
1459
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,MultiUnknownUser)1460 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiUnknownUser) {
1461 SignIn("primary@example.com");
1462 IssueLoginRefreshTokenForAccount("secondary@example.com");
1463 SetAccountState(CreateIds("primary@example.com", "1"), true);
1464 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1465
1466 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1467 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1468 func->set_extension(extension.get());
1469 func->set_auto_login_access_token(false);
1470
1471 std::string error = utils::RunFunctionAndReturnError(
1472 func.get(), "[{\"account\": { \"id\": \"3\" } }]", browser());
1473 EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
1474 }
1475
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,MultiSecondaryNonInteractiveMintFailure)1476 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1477 MultiSecondaryNonInteractiveMintFailure) {
1478 SignIn("primary@example.com");
1479 IssueLoginRefreshTokenForAccount("secondary@example.com");
1480 SetAccountState(CreateIds("primary@example.com", "1"), true);
1481 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1482
1483 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1484 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
1485 func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE);
1486 std::string error = utils::RunFunctionAndReturnError(
1487 func.get(), "[{\"account\": { \"id\": \"2\" } }]", browser());
1488 EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
1489 EXPECT_FALSE(func->login_ui_shown());
1490 EXPECT_FALSE(func->scope_ui_shown());
1491 }
1492
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,MultiSecondaryNonInteractiveLoginAccessTokenFailure)1493 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1494 MultiSecondaryNonInteractiveLoginAccessTokenFailure) {
1495 SignIn("primary@example.com");
1496 IssueLoginRefreshTokenForAccount("secondary@example.com");
1497 SetAccountState(CreateIds("primary@example.com", "1"), true);
1498 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1499
1500 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1501 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
1502 func->set_login_access_token_result(false);
1503 std::string error = utils::RunFunctionAndReturnError(
1504 func.get(), "[{\"account\": { \"id\": \"2\" } }]", browser());
1505 EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
1506 }
1507
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,MultiSecondaryInteractiveApprovalAborted)1508 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1509 MultiSecondaryInteractiveApprovalAborted) {
1510 SignIn("primary@example.com");
1511 IssueLoginRefreshTokenForAccount("secondary@example.com");
1512 SetAccountState(CreateIds("primary@example.com", "1"), true);
1513 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1514
1515 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1516 func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
1517 func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1518 func->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED);
1519 std::string error = utils::RunFunctionAndReturnError(
1520 func.get(),
1521 "[{\"account\": { \"id\": \"2\" }, \"interactive\": true}]",
1522 browser());
1523 EXPECT_EQ(std::string(errors::kUserRejected), error);
1524 EXPECT_FALSE(func->login_ui_shown());
1525 EXPECT_TRUE(func->scope_ui_shown());
1526 }
1527
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,ScopesDefault)1528 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesDefault) {
1529 SignIn("primary@example.com");
1530 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1531 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1532 func->set_extension(extension.get());
1533 func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
1534 scoped_ptr<base::Value> value(
1535 utils::RunFunctionAndReturnSingleResult(func.get(), "[{}]", browser()));
1536 std::string access_token;
1537 EXPECT_TRUE(value->GetAsString(&access_token));
1538 EXPECT_EQ(std::string(kAccessToken), access_token);
1539
1540 const ExtensionTokenKey* token_key = func->GetExtensionTokenKeyForTest();
1541 EXPECT_EQ(2ul, token_key->scopes.size());
1542 EXPECT_TRUE(ContainsKey(token_key->scopes, "scope1"));
1543 EXPECT_TRUE(ContainsKey(token_key->scopes, "scope2"));
1544 }
1545
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,ScopesEmpty)1546 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmpty) {
1547 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1548 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1549 func->set_extension(extension.get());
1550
1551 std::string error(utils::RunFunctionAndReturnError(
1552 func.get(), "[{\"scopes\": []}]", browser()));
1553
1554 EXPECT_EQ(errors::kInvalidScopes, error);
1555 }
1556
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,ScopesEmail)1557 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmail) {
1558 SignIn("primary@example.com");
1559 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1560 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1561 func->set_extension(extension.get());
1562 func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
1563 scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1564 func.get(), "[{\"scopes\": [\"email\"]}]", browser()));
1565 std::string access_token;
1566 EXPECT_TRUE(value->GetAsString(&access_token));
1567 EXPECT_EQ(std::string(kAccessToken), access_token);
1568
1569 const ExtensionTokenKey* token_key = func->GetExtensionTokenKeyForTest();
1570 EXPECT_EQ(1ul, token_key->scopes.size());
1571 EXPECT_TRUE(ContainsKey(token_key->scopes, "email"));
1572 }
1573
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,ScopesEmailFooBar)1574 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmailFooBar) {
1575 SignIn("primary@example.com");
1576 scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1577 scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1578 func->set_extension(extension.get());
1579 func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
1580 scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1581 func.get(), "[{\"scopes\": [\"email\", \"foo\", \"bar\"]}]", browser()));
1582 std::string access_token;
1583 EXPECT_TRUE(value->GetAsString(&access_token));
1584 EXPECT_EQ(std::string(kAccessToken), access_token);
1585
1586 const ExtensionTokenKey* token_key = func->GetExtensionTokenKeyForTest();
1587 EXPECT_EQ(3ul, token_key->scopes.size());
1588 EXPECT_TRUE(ContainsKey(token_key->scopes, "email"));
1589 EXPECT_TRUE(ContainsKey(token_key->scopes, "foo"));
1590 EXPECT_TRUE(ContainsKey(token_key->scopes, "bar"));
1591 }
1592
1593 class RemoveCachedAuthTokenFunctionTest : public ExtensionBrowserTest {
1594 protected:
InvalidateDefaultToken()1595 bool InvalidateDefaultToken() {
1596 scoped_refptr<IdentityRemoveCachedAuthTokenFunction> func(
1597 new IdentityRemoveCachedAuthTokenFunction);
1598 func->set_extension(test_util::CreateEmptyExtension(kExtensionId).get());
1599 return utils::RunFunction(
1600 func.get(),
1601 std::string("[{\"token\": \"") + kAccessToken + "\"}]",
1602 browser(),
1603 extension_function_test_utils::NONE);
1604 }
1605
id_api()1606 IdentityAPI* id_api() {
1607 return IdentityAPI::GetFactoryInstance()->Get(browser()->profile());
1608 }
1609
SetCachedToken(IdentityTokenCacheValue & token_data)1610 void SetCachedToken(IdentityTokenCacheValue& token_data) {
1611 ExtensionTokenKey key(
1612 kExtensionId, "test@example.com", std::set<std::string>());
1613 id_api()->SetCachedToken(key, token_data);
1614 }
1615
GetCachedToken()1616 const IdentityTokenCacheValue& GetCachedToken() {
1617 return id_api()->GetCachedToken(ExtensionTokenKey(
1618 kExtensionId, "test@example.com", std::set<std::string>()));
1619 }
1620 };
1621
IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest,NotFound)1622 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, NotFound) {
1623 EXPECT_TRUE(InvalidateDefaultToken());
1624 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND,
1625 GetCachedToken().status());
1626 }
1627
IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest,Advice)1628 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, Advice) {
1629 IssueAdviceInfo info;
1630 IdentityTokenCacheValue advice(info);
1631 SetCachedToken(advice);
1632 EXPECT_TRUE(InvalidateDefaultToken());
1633 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_ADVICE,
1634 GetCachedToken().status());
1635 }
1636
IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest,NonMatchingToken)1637 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, NonMatchingToken) {
1638 IdentityTokenCacheValue token("non_matching_token",
1639 base::TimeDelta::FromSeconds(3600));
1640 SetCachedToken(token);
1641 EXPECT_TRUE(InvalidateDefaultToken());
1642 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
1643 GetCachedToken().status());
1644 EXPECT_EQ("non_matching_token", GetCachedToken().token());
1645 }
1646
IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest,MatchingToken)1647 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, MatchingToken) {
1648 IdentityTokenCacheValue token(kAccessToken,
1649 base::TimeDelta::FromSeconds(3600));
1650 SetCachedToken(token);
1651 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
1652 GetCachedToken().status());
1653 EXPECT_TRUE(InvalidateDefaultToken());
1654 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND,
1655 GetCachedToken().status());
1656 }
1657
1658 class LaunchWebAuthFlowFunctionTest : public AsyncExtensionBrowserTest {
1659 public:
SetUpCommandLine(CommandLine * command_line)1660 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
1661 AsyncExtensionBrowserTest::SetUpCommandLine(command_line);
1662 // Reduce performance test variance by disabling background networking.
1663 command_line->AppendSwitch(switches::kDisableBackgroundNetworking);
1664 }
1665 };
1666
IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest,UserCloseWindow)1667 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, UserCloseWindow) {
1668 net::SpawnedTestServer https_server(
1669 net::SpawnedTestServer::TYPE_HTTPS,
1670 net::SpawnedTestServer::kLocalhost,
1671 base::FilePath(FILE_PATH_LITERAL(
1672 "chrome/test/data/extensions/api_test/identity")));
1673 ASSERT_TRUE(https_server.Start());
1674 GURL auth_url(https_server.GetURL("files/interaction_required.html"));
1675
1676 scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1677 new IdentityLaunchWebAuthFlowFunction());
1678 scoped_refptr<Extension> empty_extension(test_util::CreateEmptyExtension());
1679 function->set_extension(empty_extension.get());
1680
1681 WaitForGURLAndCloseWindow popup_observer(auth_url);
1682
1683 std::string args = "[{\"interactive\": true, \"url\": \"" +
1684 auth_url.spec() + "\"}]";
1685 RunFunctionAsync(function.get(), args);
1686
1687 popup_observer.Wait();
1688 popup_observer.CloseEmbedderWebContents();
1689
1690 EXPECT_EQ(std::string(errors::kUserRejected), WaitForError(function.get()));
1691 }
1692
IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest,InteractionRequired)1693 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, InteractionRequired) {
1694 net::SpawnedTestServer https_server(
1695 net::SpawnedTestServer::TYPE_HTTPS,
1696 net::SpawnedTestServer::kLocalhost,
1697 base::FilePath(FILE_PATH_LITERAL(
1698 "chrome/test/data/extensions/api_test/identity")));
1699 ASSERT_TRUE(https_server.Start());
1700 GURL auth_url(https_server.GetURL("files/interaction_required.html"));
1701
1702 scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1703 new IdentityLaunchWebAuthFlowFunction());
1704 scoped_refptr<Extension> empty_extension(test_util::CreateEmptyExtension());
1705 function->set_extension(empty_extension.get());
1706
1707 std::string args = "[{\"interactive\": false, \"url\": \"" +
1708 auth_url.spec() + "\"}]";
1709 std::string error =
1710 utils::RunFunctionAndReturnError(function.get(), args, browser());
1711
1712 EXPECT_EQ(std::string(errors::kInteractionRequired), error);
1713 }
1714
IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest,LoadFailed)1715 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, LoadFailed) {
1716 net::SpawnedTestServer https_server(
1717 net::SpawnedTestServer::TYPE_HTTPS,
1718 net::SpawnedTestServer::kLocalhost,
1719 base::FilePath(FILE_PATH_LITERAL(
1720 "chrome/test/data/extensions/api_test/identity")));
1721 ASSERT_TRUE(https_server.Start());
1722 GURL auth_url(https_server.GetURL("files/five_hundred.html"));
1723
1724 scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1725 new IdentityLaunchWebAuthFlowFunction());
1726 scoped_refptr<Extension> empty_extension(test_util::CreateEmptyExtension());
1727 function->set_extension(empty_extension.get());
1728
1729 std::string args = "[{\"interactive\": true, \"url\": \"" +
1730 auth_url.spec() + "\"}]";
1731 std::string error =
1732 utils::RunFunctionAndReturnError(function.get(), args, browser());
1733
1734 EXPECT_EQ(std::string(errors::kPageLoadFailure), error);
1735 }
1736
IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest,NonInteractiveSuccess)1737 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, NonInteractiveSuccess) {
1738 #if defined(OS_WIN) && defined(USE_ASH)
1739 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
1740 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
1741 return;
1742 #endif
1743
1744 scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1745 new IdentityLaunchWebAuthFlowFunction());
1746 scoped_refptr<Extension> empty_extension(test_util::CreateEmptyExtension());
1747 function->set_extension(empty_extension.get());
1748
1749 function->InitFinalRedirectURLPrefixForTest("abcdefghij");
1750 scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1751 function.get(),
1752 "[{\"interactive\": false,"
1753 "\"url\": \"https://abcdefghij.chromiumapp.org/callback#test\"}]",
1754 browser()));
1755
1756 std::string url;
1757 EXPECT_TRUE(value->GetAsString(&url));
1758 EXPECT_EQ(std::string("https://abcdefghij.chromiumapp.org/callback#test"),
1759 url);
1760 }
1761
IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest,InteractiveFirstNavigationSuccess)1762 IN_PROC_BROWSER_TEST_F(
1763 LaunchWebAuthFlowFunctionTest, InteractiveFirstNavigationSuccess) {
1764 #if defined(OS_WIN) && defined(USE_ASH)
1765 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
1766 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
1767 return;
1768 #endif
1769
1770 scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1771 new IdentityLaunchWebAuthFlowFunction());
1772 scoped_refptr<Extension> empty_extension(test_util::CreateEmptyExtension());
1773 function->set_extension(empty_extension.get());
1774
1775 function->InitFinalRedirectURLPrefixForTest("abcdefghij");
1776 scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1777 function.get(),
1778 "[{\"interactive\": true,"
1779 "\"url\": \"https://abcdefghij.chromiumapp.org/callback#test\"}]",
1780 browser()));
1781
1782 std::string url;
1783 EXPECT_TRUE(value->GetAsString(&url));
1784 EXPECT_EQ(std::string("https://abcdefghij.chromiumapp.org/callback#test"),
1785 url);
1786 }
1787
IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest,DISABLED_InteractiveSecondNavigationSuccess)1788 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest,
1789 DISABLED_InteractiveSecondNavigationSuccess) {
1790 net::SpawnedTestServer https_server(
1791 net::SpawnedTestServer::TYPE_HTTPS,
1792 net::SpawnedTestServer::kLocalhost,
1793 base::FilePath(FILE_PATH_LITERAL(
1794 "chrome/test/data/extensions/api_test/identity")));
1795 ASSERT_TRUE(https_server.Start());
1796 GURL auth_url(https_server.GetURL("files/redirect_to_chromiumapp.html"));
1797
1798 scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1799 new IdentityLaunchWebAuthFlowFunction());
1800 scoped_refptr<Extension> empty_extension(test_util::CreateEmptyExtension());
1801 function->set_extension(empty_extension.get());
1802
1803 function->InitFinalRedirectURLPrefixForTest("abcdefghij");
1804 std::string args = "[{\"interactive\": true, \"url\": \"" +
1805 auth_url.spec() + "\"}]";
1806 scoped_ptr<base::Value> value(
1807 utils::RunFunctionAndReturnSingleResult(function.get(), args, browser()));
1808
1809 std::string url;
1810 EXPECT_TRUE(value->GetAsString(&url));
1811 EXPECT_EQ(std::string("https://abcdefghij.chromiumapp.org/callback#test"),
1812 url);
1813 }
1814
1815 } // namespace extensions
1816
1817 // Tests the chrome.identity API implemented by custom JS bindings .
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,ChromeIdentityJsBindings)1818 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ChromeIdentityJsBindings) {
1819 ASSERT_TRUE(RunExtensionTest("identity/js_bindings")) << message_;
1820 }
1821