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