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.
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_tracker_service_factory.h"
23 #include "chrome/browser/signin/fake_gaia_cookie_manager_service.h"
24 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
25 #include "chrome/browser/signin/fake_signin_manager_builder.h"
26 #include "chrome/browser/signin/gaia_cookie_manager_service_factory.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/test/base/in_process_browser_test.h"
34 #include "chrome/test/base/test_switches.h"
35 #include "components/crx_file/id_util.h"
36 #include "components/guest_view/browser/guest_view_base.h"
37 #include "components/signin/core/browser/account_tracker_service.h"
38 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
39 #include "components/signin/core/browser/signin_manager.h"
40 #include "components/signin/core/common/profile_management_switches.h"
41 #include "components/signin/core/common/signin_pref_names.h"
42 #include "content/public/browser/notification_service.h"
43 #include "content/public/browser/notification_source.h"
44 #include "content/public/test/test_utils.h"
45 #include "extensions/browser/api_test_utils.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"
55 using guest_view::GuestViewBase
;
57 using testing::Return
;
58 using testing::ReturnRef
;
60 namespace extensions
{
64 namespace errors
= identity_constants
;
65 namespace utils
= extension_function_test_utils
;
67 static const char kAccessToken
[] = "auth_token";
68 static const char kExtensionId
[] = "ext_id";
70 // This helps us be able to wait until an UIThreadExtensionFunction calls
72 class SendResponseDelegate
73 : public UIThreadExtensionFunction::DelegateForTests
{
75 SendResponseDelegate() : should_post_quit_(false) {}
77 virtual ~SendResponseDelegate() {}
79 void set_should_post_quit(bool should_quit
) {
80 should_post_quit_
= should_quit
;
84 return response_
.get() != NULL
;
88 EXPECT_TRUE(HasResponse());
89 return *response_
.get();
92 void OnSendResponse(UIThreadExtensionFunction
* function
,
94 bool bad_message
) override
{
95 ASSERT_FALSE(bad_message
);
96 ASSERT_FALSE(HasResponse());
97 response_
.reset(new bool);
99 if (should_post_quit_
) {
100 base::MessageLoopForUI::current()->Quit();
105 scoped_ptr
<bool> response_
;
106 bool should_post_quit_
;
109 class AsyncExtensionBrowserTest
: public ExtensionBrowserTest
{
111 // Asynchronous function runner allows tests to manipulate the browser window
112 // after the call happens.
113 void RunFunctionAsync(
114 UIThreadExtensionFunction
* function
,
115 const std::string
& args
) {
116 response_delegate_
.reset(new SendResponseDelegate
);
117 function
->set_test_delegate(response_delegate_
.get());
118 scoped_ptr
<base::ListValue
> parsed_args(utils::ParseList(args
));
119 EXPECT_TRUE(parsed_args
.get()) <<
120 "Could not parse extension function arguments: " << args
;
121 function
->SetArgs(parsed_args
.get());
123 if (!function
->extension()) {
124 scoped_refptr
<Extension
> empty_extension(
125 test_util::CreateEmptyExtension());
126 function
->set_extension(empty_extension
.get());
129 function
->set_browser_context(browser()->profile());
130 function
->set_has_callback(true);
131 function
->Run()->Execute();
134 std::string
WaitForError(UIThreadExtensionFunction
* function
) {
135 RunMessageLoopUntilResponse();
136 EXPECT_FALSE(function
->GetResultList()) << "Did not expect a result";
137 return function
->GetError();
140 base::Value
* WaitForSingleResult(UIThreadExtensionFunction
* function
) {
141 RunMessageLoopUntilResponse();
142 EXPECT_TRUE(function
->GetError().empty()) << "Unexpected error: "
143 << function
->GetError();
144 const base::Value
* single_result
= NULL
;
145 if (function
->GetResultList() != NULL
&&
146 function
->GetResultList()->Get(0, &single_result
)) {
147 return single_result
->DeepCopy();
153 void RunMessageLoopUntilResponse() {
154 // If the RunAsync of |function| didn't already call SendResponse, run the
155 // message loop until they do.
156 if (!response_delegate_
->HasResponse()) {
157 response_delegate_
->set_should_post_quit(true);
158 content::RunMessageLoop();
160 EXPECT_TRUE(response_delegate_
->HasResponse());
163 scoped_ptr
<SendResponseDelegate
> response_delegate_
;
166 class TestHangOAuth2MintTokenFlow
: public OAuth2MintTokenFlow
{
168 TestHangOAuth2MintTokenFlow()
169 : OAuth2MintTokenFlow(NULL
, OAuth2MintTokenFlow::Parameters()) {}
171 void Start(net::URLRequestContextGetter
* context
,
172 const std::string
& access_token
) override
{
173 // Do nothing, simulating a hanging network call.
177 class TestOAuth2MintTokenFlow
: public OAuth2MintTokenFlow
{
180 ISSUE_ADVICE_SUCCESS
,
183 MINT_TOKEN_BAD_CREDENTIALS
,
184 MINT_TOKEN_SERVICE_ERROR
187 TestOAuth2MintTokenFlow(ResultType result
,
188 OAuth2MintTokenFlow::Delegate
* delegate
)
189 : OAuth2MintTokenFlow(delegate
, OAuth2MintTokenFlow::Parameters()),
191 delegate_(delegate
) {}
193 void Start(net::URLRequestContextGetter
* context
,
194 const std::string
& access_token
) override
{
196 case ISSUE_ADVICE_SUCCESS
: {
197 IssueAdviceInfo info
;
198 delegate_
->OnIssueAdviceSuccess(info
);
201 case MINT_TOKEN_SUCCESS
: {
202 delegate_
->OnMintTokenSuccess(kAccessToken
, 3600);
205 case MINT_TOKEN_FAILURE
: {
206 GoogleServiceAuthError
error(GoogleServiceAuthError::CONNECTION_FAILED
);
207 delegate_
->OnMintTokenFailure(error
);
210 case MINT_TOKEN_BAD_CREDENTIALS
: {
211 GoogleServiceAuthError
error(
212 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
);
213 delegate_
->OnMintTokenFailure(error
);
216 case MINT_TOKEN_SERVICE_ERROR
: {
217 GoogleServiceAuthError error
=
218 GoogleServiceAuthError::FromServiceError("invalid_scope");
219 delegate_
->OnMintTokenFailure(error
);
227 OAuth2MintTokenFlow::Delegate
* delegate_
;
230 // Waits for a specific GURL to generate a NOTIFICATION_LOAD_STOP event and
231 // saves a pointer to the window embedding the WebContents, which can be later
233 class WaitForGURLAndCloseWindow
: public content::WindowedNotificationObserver
{
235 explicit WaitForGURLAndCloseWindow(GURL url
)
236 : WindowedNotificationObserver(
237 content::NOTIFICATION_LOAD_STOP
,
238 content::NotificationService::AllSources()),
241 // NotificationObserver:
242 void Observe(int type
,
243 const content::NotificationSource
& source
,
244 const content::NotificationDetails
& details
) override
{
245 content::NavigationController
* web_auth_flow_controller
=
246 content::Source
<content::NavigationController
>(source
).ptr();
247 content::WebContents
* web_contents
=
248 web_auth_flow_controller
->GetWebContents();
250 if (web_contents
->GetURL() == url_
) {
251 // It is safe to keep the pointer here, because we know in a test, that
252 // the WebContents won't go away before CloseEmbedderWebContents is
253 // called. Don't copy this code to production.
254 GuestViewBase
* guest
= GuestViewBase::FromWebContents(web_contents
);
255 embedder_web_contents_
= guest
->embedder_web_contents();
256 // Condtionally invoke parent class so that Wait will not exit
257 // until the target URL arrives.
258 content::WindowedNotificationObserver::Observe(type
, source
, details
);
262 // Closes the window embedding the WebContents. The action is separated from
263 // the Observe method to make sure the list of observers is not deleted,
264 // while some event is already being processed. (That causes ASAN failures.)
265 void CloseEmbedderWebContents() {
266 if (embedder_web_contents_
)
267 embedder_web_contents_
->Close();
272 content::WebContents
* embedder_web_contents_
;
277 class FakeGetAuthTokenFunction
: public IdentityGetAuthTokenFunction
{
279 FakeGetAuthTokenFunction()
280 : login_access_token_result_(true),
281 auto_login_access_token_(true),
282 login_ui_result_(true),
283 scope_ui_result_(true),
284 login_ui_shown_(false),
285 scope_ui_shown_(false) {}
287 void set_login_access_token_result(bool result
) {
288 login_access_token_result_
= result
;
291 void set_auto_login_access_token(bool automatic
) {
292 auto_login_access_token_
= automatic
;
295 void set_login_ui_result(bool result
) { login_ui_result_
= result
; }
297 void set_mint_token_flow(scoped_ptr
<OAuth2MintTokenFlow
> flow
) {
301 void set_mint_token_result(TestOAuth2MintTokenFlow::ResultType result_type
) {
303 make_scoped_ptr(new TestOAuth2MintTokenFlow(result_type
, this)));
306 void set_scope_ui_failure(GaiaWebAuthFlow::Failure failure
) {
307 scope_ui_result_
= false;
308 scope_ui_failure_
= failure
;
311 void set_scope_ui_oauth_error(const std::string
& oauth_error
) {
312 scope_ui_result_
= false;
313 scope_ui_failure_
= GaiaWebAuthFlow::OAUTH_ERROR
;
314 scope_ui_oauth_error_
= oauth_error
;
317 bool login_ui_shown() const { return login_ui_shown_
; }
319 bool scope_ui_shown() const { return scope_ui_shown_
; }
321 std::string
login_access_token() const { return login_access_token_
; }
323 void StartLoginAccessTokenRequest() override
{
324 if (auto_login_access_token_
) {
325 if (login_access_token_result_
) {
326 OnGetTokenSuccess(login_token_request_
.get(),
328 base::Time::Now() + base::TimeDelta::FromHours(1LL));
330 GoogleServiceAuthError
error(
331 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
);
332 OnGetTokenFailure(login_token_request_
.get(), error
);
335 // Make a request to the token service. The test now must tell
336 // the token service to issue an access token (or an error).
337 IdentityGetAuthTokenFunction::StartLoginAccessTokenRequest();
341 void ShowLoginPopup() override
{
342 EXPECT_FALSE(login_ui_shown_
);
343 login_ui_shown_
= true;
344 if (login_ui_result_
)
350 void ShowOAuthApprovalDialog(const IssueAdviceInfo
& issue_advice
) override
{
351 scope_ui_shown_
= true;
353 if (scope_ui_result_
) {
354 OnGaiaFlowCompleted(kAccessToken
, "3600");
355 } else if (scope_ui_failure_
== GaiaWebAuthFlow::SERVICE_AUTH_ERROR
) {
356 GoogleServiceAuthError
error(GoogleServiceAuthError::CONNECTION_FAILED
);
357 OnGaiaFlowFailure(scope_ui_failure_
, error
, "");
359 GoogleServiceAuthError
error(GoogleServiceAuthError::NONE
);
360 OnGaiaFlowFailure(scope_ui_failure_
, error
, scope_ui_oauth_error_
);
364 void StartGaiaRequest(const std::string
& login_access_token
) override
{
365 EXPECT_TRUE(login_access_token_
.empty());
366 // Save the login token used in the mint token flow so tests can see
367 // what account was used.
368 login_access_token_
= login_access_token
;
369 IdentityGetAuthTokenFunction::StartGaiaRequest(login_access_token
);
372 OAuth2MintTokenFlow
* CreateMintTokenFlow() override
{
373 return flow_
.release();
377 ~FakeGetAuthTokenFunction() override
{}
378 bool login_access_token_result_
;
379 bool auto_login_access_token_
;
380 bool login_ui_result_
;
381 bool scope_ui_result_
;
382 GaiaWebAuthFlow::Failure scope_ui_failure_
;
383 std::string scope_ui_oauth_error_
;
384 bool login_ui_shown_
;
385 bool scope_ui_shown_
;
387 scoped_ptr
<OAuth2MintTokenFlow
> flow_
;
389 std::string login_access_token_
;
392 class MockQueuedMintRequest
: public IdentityMintRequestQueue::Request
{
394 MOCK_METHOD1(StartMintToken
, void(IdentityMintRequestQueue::MintType
));
397 gaia::AccountIds
CreateIds(std::string email
, std::string obfid
) {
398 gaia::AccountIds ids
;
399 ids
.account_key
= email
;
405 class IdentityGetAccountsFunctionTest
: public ExtensionBrowserTest
{
406 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
407 ExtensionBrowserTest::SetUpCommandLine(command_line
);
408 command_line
->AppendSwitch(switches::kExtensionsMultiAccount
);
412 void SetAccountState(gaia::AccountIds ids
, bool is_signed_in
) {
413 IdentityAPI::GetFactoryInstance()->Get(profile())->SetAccountStateForTest(
417 testing::AssertionResult
ExpectGetAccounts(
418 const std::vector
<std::string
>& accounts
) {
419 scoped_refptr
<IdentityGetAccountsFunction
> func(
420 new IdentityGetAccountsFunction
);
421 func
->set_extension(test_util::CreateEmptyExtension(kExtensionId
).get());
422 if (!utils::RunFunction(
423 func
.get(), std::string("[]"), browser(), utils::NONE
)) {
424 return GenerateFailureResult(accounts
, NULL
)
425 << "getAccounts did not return a result.";
427 const base::ListValue
* callback_arguments
= func
->GetResultList();
428 if (!callback_arguments
)
429 return GenerateFailureResult(accounts
, NULL
) << "NULL result";
431 if (callback_arguments
->GetSize() != 1) {
432 return GenerateFailureResult(accounts
, NULL
)
433 << "Expected 1 argument but got " << callback_arguments
->GetSize();
436 const base::ListValue
* results
;
437 if (!callback_arguments
->GetList(0, &results
))
438 GenerateFailureResult(accounts
, NULL
) << "Result was not an array";
440 std::set
<std::string
> result_ids
;
441 for (base::ListValue::const_iterator it
= results
->begin();
442 it
!= results
->end();
444 scoped_ptr
<api::identity::AccountInfo
> info
=
445 api::identity::AccountInfo::FromValue(**it
);
447 result_ids
.insert(info
->id
);
449 return GenerateFailureResult(accounts
, results
);
452 for (std::vector
<std::string
>::const_iterator it
= accounts
.begin();
453 it
!= accounts
.end();
455 if (result_ids
.find(*it
) == result_ids
.end())
456 return GenerateFailureResult(accounts
, results
);
459 return testing::AssertionResult(true);
462 testing::AssertionResult
GenerateFailureResult(
463 const ::std::vector
<std::string
>& accounts
,
464 const base::ListValue
* results
) {
465 testing::Message
msg("Expected: ");
466 for (std::vector
<std::string
>::const_iterator it
= accounts
.begin();
467 it
!= accounts
.end();
475 for (base::ListValue::const_iterator it
= results
->begin();
476 it
!= results
->end();
478 scoped_ptr
<api::identity::AccountInfo
> info
=
479 api::identity::AccountInfo::FromValue(**it
);
481 msg
<< info
->id
<< " ";
483 msg
<< *it
<< "<-" << (*it
)->GetType() << " ";
487 return testing::AssertionFailure(msg
);
491 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest
, MultiAccountOn
) {
492 EXPECT_TRUE(switches::IsExtensionsMultiAccount());
495 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest
, NoneSignedIn
) {
496 EXPECT_TRUE(ExpectGetAccounts(std::vector
<std::string
>()));
499 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest
,
500 PrimaryAccountSignedIn
) {
501 SetAccountState(CreateIds("primary@example.com", "1"), true);
502 std::vector
<std::string
> primary
;
503 primary
.push_back("1");
504 EXPECT_TRUE(ExpectGetAccounts(primary
));
507 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest
, TwoAccountsSignedIn
) {
508 SetAccountState(CreateIds("primary@example.com", "1"), true);
509 SetAccountState(CreateIds("secondary@example.com", "2"), true);
510 std::vector
<std::string
> two_accounts
;
511 two_accounts
.push_back("1");
512 two_accounts
.push_back("2");
513 EXPECT_TRUE(ExpectGetAccounts(two_accounts
));
516 class IdentityOldProfilesGetAccountsFunctionTest
517 : public IdentityGetAccountsFunctionTest
{
518 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
519 // Don't add the multi-account switch that parent class would have.
523 IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest
,
525 EXPECT_FALSE(switches::IsExtensionsMultiAccount());
528 IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest
,
529 TwoAccountsSignedIn
) {
530 SetAccountState(CreateIds("primary@example.com", "1"), true);
531 SetAccountState(CreateIds("secondary@example.com", "2"), true);
532 std::vector
<std::string
> only_primary
;
533 only_primary
.push_back("1");
534 EXPECT_TRUE(ExpectGetAccounts(only_primary
));
537 class IdentityTestWithSignin
: public AsyncExtensionBrowserTest
{
539 void SetUpInProcessBrowserTestFixture() override
{
540 AsyncExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
542 will_create_browser_context_services_subscription_
=
543 BrowserContextDependencyManager::GetInstance()
544 ->RegisterWillCreateBrowserContextServicesCallbackForTesting(
545 base::Bind(&IdentityTestWithSignin::
546 OnWillCreateBrowserContextServices
,
547 base::Unretained(this)))
551 void OnWillCreateBrowserContextServices(content::BrowserContext
* context
) {
552 // Replace the signin manager and token service with fakes. Do this ahead of
553 // creating the browser so that a bunch of classes don't register as
554 // observers and end up needing to unregister when the fake is substituted.
555 SigninManagerFactory::GetInstance()->SetTestingFactory(
556 context
, &BuildFakeSigninManagerBase
);
557 ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory(
558 context
, &BuildFakeProfileOAuth2TokenService
);
559 GaiaCookieManagerServiceFactory::GetInstance()->SetTestingFactory(
560 context
, &FakeGaiaCookieManagerService::Build
);
563 void SetUpOnMainThread() override
{
564 AsyncExtensionBrowserTest::SetUpOnMainThread();
566 // Grab references to the fake signin manager and token service.
567 signin_manager_
= static_cast<FakeSigninManagerForTesting
*>(
568 SigninManagerFactory::GetInstance()->GetForProfile(profile()));
569 ASSERT_TRUE(signin_manager_
);
570 token_service_
= static_cast<FakeProfileOAuth2TokenService
*>(
571 ProfileOAuth2TokenServiceFactory::GetInstance()->GetForProfile(
573 ASSERT_TRUE(token_service_
);
574 GaiaCookieManagerServiceFactory::GetInstance()->GetForProfile(profile())
579 void SignIn(const std::string
& account_key
) {
580 SignIn(account_key
, account_key
);
583 void SignIn(const std::string
& email
, const std::string
& gaia
) {
584 AccountTrackerService
* account_tracker
=
585 AccountTrackerServiceFactory::GetForProfile(profile());
586 std::string account_id
=
587 account_tracker
->SeedAccountInfo(gaia
, email
);
589 #if defined(OS_CHROMEOS)
590 signin_manager_
->SetAuthenticatedAccountInfo(gaia
, email
);
592 signin_manager_
->SignIn(gaia
, email
, "password");
594 token_service_
->UpdateCredentials(account_id
, "refresh_token");
597 FakeSigninManagerForTesting
* signin_manager_
;
598 FakeProfileOAuth2TokenService
* token_service_
;
600 scoped_ptr
<base::CallbackList
<void(content::BrowserContext
*)>::Subscription
>
601 will_create_browser_context_services_subscription_
;
604 class IdentityGetProfileUserInfoFunctionTest
: public IdentityTestWithSignin
{
606 scoped_ptr
<api::identity::ProfileUserInfo
> RunGetProfileUserInfo() {
607 scoped_refptr
<IdentityGetProfileUserInfoFunction
> func(
608 new IdentityGetProfileUserInfoFunction
);
609 func
->set_extension(test_util::CreateEmptyExtension(kExtensionId
).get());
610 scoped_ptr
<base::Value
> value(
611 utils::RunFunctionAndReturnSingleResult(func
.get(), "[]", browser()));
612 return api::identity::ProfileUserInfo::FromValue(*value
.get());
615 scoped_ptr
<api::identity::ProfileUserInfo
> RunGetProfileUserInfoWithEmail() {
616 scoped_refptr
<IdentityGetProfileUserInfoFunction
> func(
617 new IdentityGetProfileUserInfoFunction
);
618 func
->set_extension(CreateExtensionWithEmailPermission());
619 scoped_ptr
<base::Value
> value(
620 utils::RunFunctionAndReturnSingleResult(func
.get(), "[]", browser()));
621 return api::identity::ProfileUserInfo::FromValue(*value
.get());
625 scoped_refptr
<Extension
> CreateExtensionWithEmailPermission() {
626 scoped_ptr
<base::DictionaryValue
> test_extension_value(
627 api_test_utils::ParseDictionary(
628 "{\"name\": \"Test\", \"version\": \"1.0\", "
629 "\"permissions\": [\"identity.email\"]}"));
630 return api_test_utils::CreateExtension(test_extension_value
.get());
634 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest
, NotSignedIn
) {
635 scoped_ptr
<api::identity::ProfileUserInfo
> info
=
636 RunGetProfileUserInfoWithEmail();
637 EXPECT_TRUE(info
->email
.empty());
638 EXPECT_TRUE(info
->id
.empty());
641 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest
, SignedIn
) {
642 SignIn("president@example.com", "12345");
643 scoped_ptr
<api::identity::ProfileUserInfo
> info
=
644 RunGetProfileUserInfoWithEmail();
645 EXPECT_EQ("president@example.com", info
->email
);
646 EXPECT_EQ("12345", info
->id
);
649 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest
,
650 NotSignedInNoEmail
) {
651 scoped_ptr
<api::identity::ProfileUserInfo
> info
= RunGetProfileUserInfo();
652 EXPECT_TRUE(info
->email
.empty());
653 EXPECT_TRUE(info
->id
.empty());
656 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest
,
658 SignIn("president@example.com", "12345");
659 scoped_ptr
<api::identity::ProfileUserInfo
> info
= RunGetProfileUserInfo();
660 EXPECT_TRUE(info
->email
.empty());
661 EXPECT_TRUE(info
->id
.empty());
664 class GetAuthTokenFunctionTest
: public IdentityTestWithSignin
{
666 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
667 IdentityTestWithSignin::SetUpCommandLine(command_line
);
668 command_line
->AppendSwitch(switches::kExtensionsMultiAccount
);
671 void IssueLoginRefreshTokenForAccount(const std::string account_key
) {
672 token_service_
->UpdateCredentials(account_key
, "refresh_token");
675 void IssueLoginAccessTokenForAccount(const std::string account_key
) {
676 token_service_
->IssueAllTokensForAccount(
678 "access_token-" + account_key
,
679 base::Time::Now() + base::TimeDelta::FromSeconds(3600));
682 void SetAccountState(gaia::AccountIds ids
, bool is_signed_in
) {
683 IdentityAPI::GetFactoryInstance()->Get(profile())->SetAccountStateForTest(
695 ~GetAuthTokenFunctionTest() override
{}
697 // Helper to create an extension with specific OAuth2Info fields set.
698 // |fields_to_set| should be computed by using fields of Oauth2Fields enum.
699 const Extension
* CreateExtension(int fields_to_set
) {
700 const Extension
* ext
;
701 base::FilePath manifest_path
=
702 test_data_dir_
.AppendASCII("platform_apps/oauth2");
703 base::FilePath component_manifest_path
=
704 test_data_dir_
.AppendASCII("packaged_app/component_oauth2");
705 if ((fields_to_set
& AS_COMPONENT
) == 0)
706 ext
= LoadExtension(manifest_path
);
708 ext
= LoadExtensionAsComponent(component_manifest_path
);
709 OAuth2Info
& oauth2_info
=
710 const_cast<OAuth2Info
&>(OAuth2Info::GetOAuth2Info(ext
));
711 if ((fields_to_set
& CLIENT_ID
) != 0)
712 oauth2_info
.client_id
= "client1";
713 if ((fields_to_set
& SCOPES
) != 0) {
714 oauth2_info
.scopes
.push_back("scope1");
715 oauth2_info
.scopes
.push_back("scope2");
718 extension_id_
= ext
->id();
719 oauth_scopes_
= std::set
<std::string
>(oauth2_info
.scopes
.begin(),
720 oauth2_info
.scopes
.end());
724 IdentityAPI
* id_api() {
725 return IdentityAPI::GetFactoryInstance()->Get(browser()->profile());
728 const std::string
& GetPrimaryAccountId() {
729 SigninManagerBase
* signin_manager
=
730 SigninManagerFactory::GetForProfile(browser()->profile());
731 return signin_manager
->GetAuthenticatedAccountId();
734 void SetCachedToken(const IdentityTokenCacheValue
& token_data
) {
735 ExtensionTokenKey
key(extension_id_
, GetPrimaryAccountId(), oauth_scopes_
);
736 id_api()->SetCachedToken(key
, token_data
);
739 const IdentityTokenCacheValue
& GetCachedToken(std::string account_id
) {
740 if (account_id
.empty())
741 account_id
= GetPrimaryAccountId();
742 ExtensionTokenKey
key(extension_id_
, account_id
, oauth_scopes_
);
743 return id_api()->GetCachedToken(key
);
746 void QueueRequestStart(IdentityMintRequestQueue::MintType type
,
747 IdentityMintRequestQueue::Request
* request
) {
748 ExtensionTokenKey
key(extension_id_
, GetPrimaryAccountId(), oauth_scopes_
);
749 id_api()->mint_queue()->RequestStart(type
, key
, request
);
752 void QueueRequestComplete(IdentityMintRequestQueue::MintType type
,
753 IdentityMintRequestQueue::Request
* request
) {
754 ExtensionTokenKey
key(extension_id_
, GetPrimaryAccountId(), oauth_scopes_
);
755 id_api()->mint_queue()->RequestComplete(type
, key
, request
);
759 std::string extension_id_
;
760 std::set
<std::string
> oauth_scopes_
;
763 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
765 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
766 func
->set_extension(CreateExtension(SCOPES
));
767 std::string error
= utils::RunFunctionAndReturnError(
768 func
.get(), "[{}]", browser());
769 EXPECT_EQ(std::string(errors::kInvalidClientId
), error
);
770 EXPECT_FALSE(func
->login_ui_shown());
771 EXPECT_FALSE(func
->scope_ui_shown());
774 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
776 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
777 func
->set_extension(CreateExtension(CLIENT_ID
));
778 std::string error
= utils::RunFunctionAndReturnError(
779 func
.get(), "[{}]", browser());
780 EXPECT_EQ(std::string(errors::kInvalidScopes
), error
);
781 EXPECT_FALSE(func
->login_ui_shown());
782 EXPECT_FALSE(func
->scope_ui_shown());
785 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
786 NonInteractiveNotSignedIn
) {
787 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
788 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
789 std::string error
= utils::RunFunctionAndReturnError(
790 func
.get(), "[{}]", browser());
791 EXPECT_EQ(std::string(errors::kUserNotSignedIn
), error
);
792 EXPECT_FALSE(func
->login_ui_shown());
793 EXPECT_FALSE(func
->scope_ui_shown());
796 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
797 NonInteractiveMintFailure
) {
798 SignIn("primary@example.com");
799 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
800 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
801 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE
);
803 utils::RunFunctionAndReturnError(func
.get(), "[{}]", browser());
804 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
805 base::CompareCase::INSENSITIVE_ASCII
));
806 EXPECT_FALSE(func
->login_ui_shown());
807 EXPECT_FALSE(func
->scope_ui_shown());
810 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
811 NonInteractiveLoginAccessTokenFailure
) {
812 SignIn("primary@example.com");
813 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
814 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
815 func
->set_login_access_token_result(false);
816 std::string error
= utils::RunFunctionAndReturnError(
817 func
.get(), "[{}]", browser());
818 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
819 base::CompareCase::INSENSITIVE_ASCII
));
822 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
823 NonInteractiveMintAdviceSuccess
) {
824 SignIn("primary@example.com");
825 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
826 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
827 func
->set_extension(extension
.get());
828 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
830 utils::RunFunctionAndReturnError(func
.get(), "[{}]", browser());
831 EXPECT_EQ(std::string(errors::kNoGrant
), error
);
832 EXPECT_FALSE(func
->login_ui_shown());
833 EXPECT_FALSE(func
->scope_ui_shown());
835 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_ADVICE
,
836 GetCachedToken(std::string()).status());
839 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
840 NonInteractiveMintBadCredentials
) {
841 SignIn("primary@example.com");
842 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
843 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
844 func
->set_mint_token_result(
845 TestOAuth2MintTokenFlow::MINT_TOKEN_BAD_CREDENTIALS
);
847 utils::RunFunctionAndReturnError(func
.get(), "[{}]", browser());
848 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
849 base::CompareCase::INSENSITIVE_ASCII
));
850 EXPECT_FALSE(func
->login_ui_shown());
851 EXPECT_FALSE(func
->scope_ui_shown());
854 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
855 NonInteractiveMintServiceError
) {
856 SignIn("primary@example.com");
857 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
858 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
859 func
->set_mint_token_result(
860 TestOAuth2MintTokenFlow::MINT_TOKEN_SERVICE_ERROR
);
862 utils::RunFunctionAndReturnError(func
.get(), "[{}]", browser());
863 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
864 base::CompareCase::INSENSITIVE_ASCII
));
865 EXPECT_FALSE(func
->login_ui_shown());
866 EXPECT_FALSE(func
->scope_ui_shown());
869 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
871 SignIn("primary@example.com");
872 #if defined(OS_WIN) && defined(USE_ASH)
873 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
874 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
875 switches::kAshBrowserTests
))
879 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
880 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
881 func
->set_extension(extension
.get());
882 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
883 scoped_ptr
<base::Value
> value(
884 utils::RunFunctionAndReturnSingleResult(func
.get(), "[]", browser()));
885 std::string access_token
;
886 EXPECT_TRUE(value
->GetAsString(&access_token
));
887 EXPECT_EQ(std::string(kAccessToken
), access_token
);
888 EXPECT_FALSE(func
->login_ui_shown());
889 EXPECT_FALSE(func
->scope_ui_shown());
890 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
891 GetCachedToken(std::string()).status());
894 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
895 NonInteractiveSuccess
) {
896 SignIn("primary@example.com");
897 #if defined(OS_WIN) && defined(USE_ASH)
898 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
899 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
900 switches::kAshBrowserTests
))
904 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
905 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
906 func
->set_extension(extension
.get());
907 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
908 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
909 func
.get(), "[{}]", browser()));
910 std::string access_token
;
911 EXPECT_TRUE(value
->GetAsString(&access_token
));
912 EXPECT_EQ(std::string(kAccessToken
), access_token
);
913 EXPECT_FALSE(func
->login_ui_shown());
914 EXPECT_FALSE(func
->scope_ui_shown());
915 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
916 GetCachedToken(std::string()).status());
919 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
920 InteractiveLoginCanceled
) {
921 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
922 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
923 func
->set_login_ui_result(false);
924 std::string error
= utils::RunFunctionAndReturnError(
925 func
.get(), "[{\"interactive\": true}]", browser());
926 EXPECT_EQ(std::string(errors::kUserNotSignedIn
), error
);
927 EXPECT_TRUE(func
->login_ui_shown());
928 EXPECT_FALSE(func
->scope_ui_shown());
931 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
932 InteractiveMintBadCredentialsLoginCanceled
) {
933 SignIn("primary@example.com");
934 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
935 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
936 func
->set_mint_token_result(
937 TestOAuth2MintTokenFlow::MINT_TOKEN_BAD_CREDENTIALS
);
938 func
->set_login_ui_result(false);
939 std::string error
= utils::RunFunctionAndReturnError(
940 func
.get(), "[{\"interactive\": true}]", browser());
941 EXPECT_EQ(std::string(errors::kUserNotSignedIn
), error
);
942 EXPECT_TRUE(func
->login_ui_shown());
943 EXPECT_FALSE(func
->scope_ui_shown());
946 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
947 InteractiveLoginSuccessNoToken
) {
948 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
949 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
950 func
->set_login_ui_result(false);
951 std::string error
= utils::RunFunctionAndReturnError(
952 func
.get(), "[{\"interactive\": true}]", browser());
953 EXPECT_EQ(std::string(errors::kUserNotSignedIn
), error
);
954 EXPECT_TRUE(func
->login_ui_shown());
955 EXPECT_FALSE(func
->scope_ui_shown());
958 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
959 InteractiveLoginSuccessMintFailure
) {
960 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
961 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
962 func
->set_login_ui_result(true);
963 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE
);
964 std::string error
= utils::RunFunctionAndReturnError(
965 func
.get(), "[{\"interactive\": true}]", browser());
966 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
967 base::CompareCase::INSENSITIVE_ASCII
));
968 EXPECT_TRUE(func
->login_ui_shown());
969 EXPECT_FALSE(func
->scope_ui_shown());
972 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
973 InteractiveLoginSuccessLoginAccessTokenFailure
) {
974 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
975 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
976 func
->set_login_ui_result(true);
977 func
->set_login_access_token_result(false);
978 std::string error
= utils::RunFunctionAndReturnError(
979 func
.get(), "[{\"interactive\": true}]", browser());
980 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
981 base::CompareCase::INSENSITIVE_ASCII
));
982 EXPECT_TRUE(func
->login_ui_shown());
983 EXPECT_FALSE(func
->scope_ui_shown());
986 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
987 InteractiveLoginSuccessMintSuccess
) {
988 // TODO(courage): verify that account_id in token service requests
989 // is correct once manual token minting for tests is implemented.
990 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
991 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
992 func
->set_login_ui_result(true);
993 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
994 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
995 func
.get(), "[{\"interactive\": true}]", browser()));
996 std::string access_token
;
997 EXPECT_TRUE(value
->GetAsString(&access_token
));
998 EXPECT_EQ(std::string(kAccessToken
), access_token
);
999 EXPECT_TRUE(func
->login_ui_shown());
1000 EXPECT_FALSE(func
->scope_ui_shown());
1003 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1004 InteractiveLoginSuccessApprovalAborted
) {
1005 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1006 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
1007 func
->set_login_ui_result(true);
1008 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1009 func
->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED
);
1010 std::string error
= utils::RunFunctionAndReturnError(
1011 func
.get(), "[{\"interactive\": true}]", browser());
1012 EXPECT_EQ(std::string(errors::kUserRejected
), error
);
1013 EXPECT_TRUE(func
->login_ui_shown());
1014 EXPECT_TRUE(func
->scope_ui_shown());
1017 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1018 InteractiveLoginSuccessApprovalSuccess
) {
1019 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1020 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1021 func
->set_extension(extension
.get());
1022 func
->set_login_ui_result(true);
1023 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1025 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1026 func
.get(), "[{\"interactive\": true}]", browser()));
1027 std::string access_token
;
1028 EXPECT_TRUE(value
->GetAsString(&access_token
));
1029 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1030 EXPECT_TRUE(func
->login_ui_shown());
1031 EXPECT_TRUE(func
->scope_ui_shown());
1034 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1035 InteractiveApprovalAborted
) {
1036 SignIn("primary@example.com");
1037 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1038 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
1039 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1040 func
->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED
);
1041 std::string error
= utils::RunFunctionAndReturnError(
1042 func
.get(), "[{\"interactive\": true}]", browser());
1043 EXPECT_EQ(std::string(errors::kUserRejected
), error
);
1044 EXPECT_FALSE(func
->login_ui_shown());
1045 EXPECT_TRUE(func
->scope_ui_shown());
1048 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1049 InteractiveApprovalLoadFailed
) {
1050 SignIn("primary@example.com");
1051 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1052 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
1053 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1054 func
->set_scope_ui_failure(GaiaWebAuthFlow::LOAD_FAILED
);
1055 std::string error
= utils::RunFunctionAndReturnError(
1056 func
.get(), "[{\"interactive\": true}]", browser());
1057 EXPECT_EQ(std::string(errors::kPageLoadFailure
), error
);
1058 EXPECT_FALSE(func
->login_ui_shown());
1059 EXPECT_TRUE(func
->scope_ui_shown());
1062 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1063 InteractiveApprovalInvalidRedirect
) {
1064 SignIn("primary@example.com");
1065 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1066 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
1067 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1068 func
->set_scope_ui_failure(GaiaWebAuthFlow::INVALID_REDIRECT
);
1069 std::string error
= utils::RunFunctionAndReturnError(
1070 func
.get(), "[{\"interactive\": true}]", browser());
1071 EXPECT_EQ(std::string(errors::kInvalidRedirect
), error
);
1072 EXPECT_FALSE(func
->login_ui_shown());
1073 EXPECT_TRUE(func
->scope_ui_shown());
1076 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1077 InteractiveApprovalConnectionFailure
) {
1078 SignIn("primary@example.com");
1079 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1080 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
1081 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1082 func
->set_scope_ui_failure(GaiaWebAuthFlow::SERVICE_AUTH_ERROR
);
1083 std::string error
= utils::RunFunctionAndReturnError(
1084 func
.get(), "[{\"interactive\": true}]", browser());
1085 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
1086 base::CompareCase::INSENSITIVE_ASCII
));
1087 EXPECT_FALSE(func
->login_ui_shown());
1088 EXPECT_TRUE(func
->scope_ui_shown());
1091 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1092 InteractiveApprovalOAuthErrors
) {
1093 SignIn("primary@example.com");
1094 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1096 std::map
<std::string
, std::string
> error_map
;
1097 error_map
.insert(std::make_pair("access_denied", errors::kUserRejected
));
1098 error_map
.insert(std::make_pair("invalid_scope", errors::kInvalidScopes
));
1099 error_map
.insert(std::make_pair(
1100 "unmapped_error", std::string(errors::kAuthFailure
) + "unmapped_error"));
1102 for (std::map
<std::string
, std::string
>::const_iterator
1103 it
= error_map
.begin();
1104 it
!= error_map
.end();
1106 scoped_refptr
<FakeGetAuthTokenFunction
> func(
1107 new FakeGetAuthTokenFunction());
1108 func
->set_extension(extension
.get());
1109 // Make sure we don't get a cached issue_advice result, which would cause
1110 // flow to be leaked.
1111 id_api()->EraseAllCachedTokens();
1112 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1113 func
->set_scope_ui_oauth_error(it
->first
);
1114 std::string error
= utils::RunFunctionAndReturnError(
1115 func
.get(), "[{\"interactive\": true}]", browser());
1116 EXPECT_EQ(it
->second
, error
);
1117 EXPECT_FALSE(func
->login_ui_shown());
1118 EXPECT_TRUE(func
->scope_ui_shown());
1122 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1123 InteractiveApprovalSuccess
) {
1124 SignIn("primary@example.com");
1125 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1126 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1127 func
->set_extension(extension
.get());
1128 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1130 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1131 func
.get(), "[{\"interactive\": true}]", browser()));
1132 std::string access_token
;
1133 EXPECT_TRUE(value
->GetAsString(&access_token
));
1134 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1135 EXPECT_FALSE(func
->login_ui_shown());
1136 EXPECT_TRUE(func
->scope_ui_shown());
1138 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
1139 GetCachedToken(std::string()).status());
1142 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, NoninteractiveQueue
) {
1143 SignIn("primary@example.com");
1144 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1145 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1146 func
->set_extension(extension
.get());
1148 // Create a fake request to block the queue.
1149 MockQueuedMintRequest queued_request
;
1150 IdentityMintRequestQueue::MintType type
=
1151 IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE
;
1153 EXPECT_CALL(queued_request
, StartMintToken(type
)).Times(1);
1154 QueueRequestStart(type
, &queued_request
);
1156 // The real request will start processing, but wait in the queue behind
1158 RunFunctionAsync(func
.get(), "[{}]");
1159 // Verify that we have fetched the login token at this point.
1160 testing::Mock::VerifyAndClearExpectations(func
.get());
1162 // The flow will be created after the first queued request clears.
1163 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
1165 QueueRequestComplete(type
, &queued_request
);
1167 scoped_ptr
<base::Value
> value(WaitForSingleResult(func
.get()));
1168 std::string access_token
;
1169 EXPECT_TRUE(value
->GetAsString(&access_token
));
1170 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1171 EXPECT_FALSE(func
->login_ui_shown());
1172 EXPECT_FALSE(func
->scope_ui_shown());
1175 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, InteractiveQueue
) {
1176 SignIn("primary@example.com");
1177 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1178 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1179 func
->set_extension(extension
.get());
1181 // Create a fake request to block the queue.
1182 MockQueuedMintRequest queued_request
;
1183 IdentityMintRequestQueue::MintType type
=
1184 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE
;
1186 EXPECT_CALL(queued_request
, StartMintToken(type
)).Times(1);
1187 QueueRequestStart(type
, &queued_request
);
1189 // The real request will start processing, but wait in the queue behind
1191 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1192 RunFunctionAsync(func
.get(), "[{\"interactive\": true}]");
1193 // Verify that we have fetched the login token and run the first flow.
1194 testing::Mock::VerifyAndClearExpectations(func
.get());
1195 EXPECT_FALSE(func
->scope_ui_shown());
1197 // The UI will be displayed and a token retrieved after the first
1198 // queued request clears.
1199 QueueRequestComplete(type
, &queued_request
);
1201 scoped_ptr
<base::Value
> value(WaitForSingleResult(func
.get()));
1202 std::string access_token
;
1203 EXPECT_TRUE(value
->GetAsString(&access_token
));
1204 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1205 EXPECT_FALSE(func
->login_ui_shown());
1206 EXPECT_TRUE(func
->scope_ui_shown());
1209 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, InteractiveQueueShutdown
) {
1210 SignIn("primary@example.com");
1211 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1212 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1213 func
->set_extension(extension
.get());
1215 // Create a fake request to block the queue.
1216 MockQueuedMintRequest queued_request
;
1217 IdentityMintRequestQueue::MintType type
=
1218 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE
;
1220 EXPECT_CALL(queued_request
, StartMintToken(type
)).Times(1);
1221 QueueRequestStart(type
, &queued_request
);
1223 // The real request will start processing, but wait in the queue behind
1225 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1226 RunFunctionAsync(func
.get(), "[{\"interactive\": true}]");
1227 // Verify that we have fetched the login token and run the first flow.
1228 testing::Mock::VerifyAndClearExpectations(func
.get());
1229 EXPECT_FALSE(func
->scope_ui_shown());
1231 // After the request is canceled, the function will complete.
1233 EXPECT_EQ(std::string(errors::kCanceled
), WaitForError(func
.get()));
1234 EXPECT_FALSE(func
->login_ui_shown());
1235 EXPECT_FALSE(func
->scope_ui_shown());
1237 QueueRequestComplete(type
, &queued_request
);
1240 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, NoninteractiveShutdown
) {
1241 SignIn("primary@example.com");
1242 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1243 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1244 func
->set_extension(extension
.get());
1246 func
->set_mint_token_flow(make_scoped_ptr(new TestHangOAuth2MintTokenFlow()));
1247 RunFunctionAsync(func
.get(), "[{\"interactive\": false}]");
1249 // After the request is canceled, the function will complete.
1251 EXPECT_EQ(std::string(errors::kCanceled
), WaitForError(func
.get()));
1254 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1255 InteractiveQueuedNoninteractiveFails
) {
1256 SignIn("primary@example.com");
1257 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1258 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1259 func
->set_extension(extension
.get());
1261 // Create a fake request to block the interactive queue.
1262 MockQueuedMintRequest queued_request
;
1263 IdentityMintRequestQueue::MintType type
=
1264 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE
;
1266 EXPECT_CALL(queued_request
, StartMintToken(type
)).Times(1);
1267 QueueRequestStart(type
, &queued_request
);
1269 // Non-interactive requests fail without hitting GAIA, because a
1270 // consent UI is known to be up.
1271 std::string error
= utils::RunFunctionAndReturnError(
1272 func
.get(), "[{}]", browser());
1273 EXPECT_EQ(std::string(errors::kNoGrant
), error
);
1274 EXPECT_FALSE(func
->login_ui_shown());
1275 EXPECT_FALSE(func
->scope_ui_shown());
1277 QueueRequestComplete(type
, &queued_request
);
1280 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1281 NonInteractiveCacheHit
) {
1282 SignIn("primary@example.com");
1283 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1284 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1285 func
->set_extension(extension
.get());
1287 // pre-populate the cache with a token
1288 IdentityTokenCacheValue
token(kAccessToken
,
1289 base::TimeDelta::FromSeconds(3600));
1290 SetCachedToken(token
);
1292 // Get a token. Should not require a GAIA request.
1293 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1294 func
.get(), "[{}]", browser()));
1295 std::string access_token
;
1296 EXPECT_TRUE(value
->GetAsString(&access_token
));
1297 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1298 EXPECT_FALSE(func
->login_ui_shown());
1299 EXPECT_FALSE(func
->scope_ui_shown());
1302 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1303 NonInteractiveIssueAdviceCacheHit
) {
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());
1309 // pre-populate the cache with advice
1310 IssueAdviceInfo info
;
1311 IdentityTokenCacheValue
token(info
);
1312 SetCachedToken(token
);
1314 // Should return an error without a GAIA request.
1315 std::string error
= utils::RunFunctionAndReturnError(
1316 func
.get(), "[{}]", browser());
1317 EXPECT_EQ(std::string(errors::kNoGrant
), error
);
1318 EXPECT_FALSE(func
->login_ui_shown());
1319 EXPECT_FALSE(func
->scope_ui_shown());
1322 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1323 InteractiveCacheHit
) {
1324 SignIn("primary@example.com");
1325 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1326 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1327 func
->set_extension(extension
.get());
1329 // Create a fake request to block the queue.
1330 MockQueuedMintRequest queued_request
;
1331 IdentityMintRequestQueue::MintType type
=
1332 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE
;
1334 EXPECT_CALL(queued_request
, StartMintToken(type
)).Times(1);
1335 QueueRequestStart(type
, &queued_request
);
1337 // The real request will start processing, but wait in the queue behind
1339 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1340 RunFunctionAsync(func
.get(), "[{\"interactive\": true}]");
1342 // Populate the cache with a token while the request is blocked.
1343 IdentityTokenCacheValue
token(kAccessToken
,
1344 base::TimeDelta::FromSeconds(3600));
1345 SetCachedToken(token
);
1347 // When we wake up the request, it returns the cached token without
1348 // displaying a UI, or hitting GAIA.
1350 QueueRequestComplete(type
, &queued_request
);
1352 scoped_ptr
<base::Value
> value(WaitForSingleResult(func
.get()));
1353 std::string access_token
;
1354 EXPECT_TRUE(value
->GetAsString(&access_token
));
1355 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1356 EXPECT_FALSE(func
->login_ui_shown());
1357 EXPECT_FALSE(func
->scope_ui_shown());
1360 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1361 LoginInvalidatesTokenCache
) {
1362 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1363 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1364 func
->set_extension(extension
.get());
1366 // pre-populate the cache with a token
1367 IdentityTokenCacheValue
token(kAccessToken
,
1368 base::TimeDelta::FromSeconds(3600));
1369 SetCachedToken(token
);
1371 // Because the user is not signed in, the token will be removed,
1372 // and we'll hit GAIA for new tokens.
1373 func
->set_login_ui_result(true);
1374 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1376 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1377 func
.get(), "[{\"interactive\": true}]", browser()));
1378 std::string access_token
;
1379 EXPECT_TRUE(value
->GetAsString(&access_token
));
1380 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1381 EXPECT_TRUE(func
->login_ui_shown());
1382 EXPECT_TRUE(func
->scope_ui_shown());
1383 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
1384 GetCachedToken(std::string()).status());
1387 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, ComponentWithChromeClientId
) {
1388 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1389 scoped_refptr
<const Extension
> extension(
1390 CreateExtension(SCOPES
| AS_COMPONENT
));
1391 func
->set_extension(extension
.get());
1392 const OAuth2Info
& oauth2_info
= OAuth2Info::GetOAuth2Info(extension
.get());
1393 EXPECT_TRUE(oauth2_info
.client_id
.empty());
1394 EXPECT_FALSE(func
->GetOAuth2ClientId().empty());
1395 EXPECT_NE("client1", func
->GetOAuth2ClientId());
1398 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, ComponentWithNormalClientId
) {
1399 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1400 scoped_refptr
<const Extension
> extension(
1401 CreateExtension(CLIENT_ID
| SCOPES
| AS_COMPONENT
));
1402 func
->set_extension(extension
.get());
1403 EXPECT_EQ("client1", func
->GetOAuth2ClientId());
1406 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, MultiDefaultUser
) {
1407 SignIn("primary@example.com");
1408 SetAccountState(CreateIds("primary@example.com", "1"), true);
1409 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1411 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1412 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1413 func
->set_extension(extension
.get());
1414 func
->set_auto_login_access_token(false);
1415 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
1417 RunFunctionAsync(func
.get(), "[{}]");
1419 IssueLoginAccessTokenForAccount("primary@example.com");
1421 scoped_ptr
<base::Value
> value(WaitForSingleResult(func
.get()));
1422 std::string access_token
;
1423 EXPECT_TRUE(value
->GetAsString(&access_token
));
1424 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1425 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
1426 GetCachedToken(std::string()).status());
1427 EXPECT_EQ("access_token-primary@example.com", func
->login_access_token());
1430 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, MultiPrimaryUser
) {
1431 SignIn("primary@example.com");
1432 IssueLoginRefreshTokenForAccount("secondary@example.com");
1433 SetAccountState(CreateIds("primary@example.com", "1"), true);
1434 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1436 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1437 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1438 func
->set_extension(extension
.get());
1439 func
->set_auto_login_access_token(false);
1440 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
1442 RunFunctionAsync(func
.get(), "[{\"account\": { \"id\": \"1\" } }]");
1444 IssueLoginAccessTokenForAccount("primary@example.com");
1446 scoped_ptr
<base::Value
> value(WaitForSingleResult(func
.get()));
1447 std::string access_token
;
1448 EXPECT_TRUE(value
->GetAsString(&access_token
));
1449 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1450 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
1451 GetCachedToken(std::string()).status());
1452 EXPECT_EQ("access_token-primary@example.com", func
->login_access_token());
1455 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, MultiSecondaryUser
) {
1456 SignIn("primary@example.com");
1457 IssueLoginRefreshTokenForAccount("secondary@example.com");
1458 SetAccountState(CreateIds("primary@example.com", "1"), true);
1459 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1461 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1462 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1463 func
->set_extension(extension
.get());
1464 func
->set_auto_login_access_token(false);
1465 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
1467 RunFunctionAsync(func
.get(), "[{\"account\": { \"id\": \"2\" } }]");
1469 IssueLoginAccessTokenForAccount("secondary@example.com");
1471 scoped_ptr
<base::Value
> value(WaitForSingleResult(func
.get()));
1472 std::string access_token
;
1473 EXPECT_TRUE(value
->GetAsString(&access_token
));
1474 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1475 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
1476 GetCachedToken("secondary@example.com").status());
1477 EXPECT_EQ("access_token-secondary@example.com", func
->login_access_token());
1480 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, MultiUnknownUser
) {
1481 SignIn("primary@example.com");
1482 IssueLoginRefreshTokenForAccount("secondary@example.com");
1483 SetAccountState(CreateIds("primary@example.com", "1"), true);
1484 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1486 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1487 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1488 func
->set_extension(extension
.get());
1489 func
->set_auto_login_access_token(false);
1491 std::string error
= utils::RunFunctionAndReturnError(
1492 func
.get(), "[{\"account\": { \"id\": \"3\" } }]", browser());
1493 EXPECT_EQ(std::string(errors::kUserNotSignedIn
), error
);
1496 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1497 MultiSecondaryNonInteractiveMintFailure
) {
1498 SignIn("primary@example.com");
1499 IssueLoginRefreshTokenForAccount("secondary@example.com");
1500 SetAccountState(CreateIds("primary@example.com", "1"), true);
1501 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1503 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1504 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
1505 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE
);
1506 std::string error
= utils::RunFunctionAndReturnError(
1507 func
.get(), "[{\"account\": { \"id\": \"2\" } }]", browser());
1508 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
1509 base::CompareCase::INSENSITIVE_ASCII
));
1510 EXPECT_FALSE(func
->login_ui_shown());
1511 EXPECT_FALSE(func
->scope_ui_shown());
1514 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1515 MultiSecondaryNonInteractiveLoginAccessTokenFailure
) {
1516 SignIn("primary@example.com");
1517 IssueLoginRefreshTokenForAccount("secondary@example.com");
1518 SetAccountState(CreateIds("primary@example.com", "1"), true);
1519 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1521 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1522 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
1523 func
->set_login_access_token_result(false);
1524 std::string error
= utils::RunFunctionAndReturnError(
1525 func
.get(), "[{\"account\": { \"id\": \"2\" } }]", browser());
1526 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
1527 base::CompareCase::INSENSITIVE_ASCII
));
1530 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1531 MultiSecondaryInteractiveApprovalAborted
) {
1532 SignIn("primary@example.com");
1533 IssueLoginRefreshTokenForAccount("secondary@example.com");
1534 SetAccountState(CreateIds("primary@example.com", "1"), true);
1535 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1537 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1538 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
1539 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1540 func
->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED
);
1541 std::string error
= utils::RunFunctionAndReturnError(
1543 "[{\"account\": { \"id\": \"2\" }, \"interactive\": true}]",
1545 EXPECT_EQ(std::string(errors::kUserRejected
), error
);
1546 EXPECT_FALSE(func
->login_ui_shown());
1547 EXPECT_TRUE(func
->scope_ui_shown());
1550 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, ScopesDefault
) {
1551 SignIn("primary@example.com");
1552 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1553 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1554 func
->set_extension(extension
.get());
1555 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
1556 scoped_ptr
<base::Value
> value(
1557 utils::RunFunctionAndReturnSingleResult(func
.get(), "[{}]", browser()));
1558 std::string access_token
;
1559 EXPECT_TRUE(value
->GetAsString(&access_token
));
1560 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1562 const ExtensionTokenKey
* token_key
= func
->GetExtensionTokenKeyForTest();
1563 EXPECT_EQ(2ul, token_key
->scopes
.size());
1564 EXPECT_TRUE(ContainsKey(token_key
->scopes
, "scope1"));
1565 EXPECT_TRUE(ContainsKey(token_key
->scopes
, "scope2"));
1568 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, ScopesEmpty
) {
1569 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1570 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1571 func
->set_extension(extension
.get());
1573 std::string
error(utils::RunFunctionAndReturnError(
1574 func
.get(), "[{\"scopes\": []}]", browser()));
1576 EXPECT_EQ(errors::kInvalidScopes
, error
);
1579 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, ScopesEmail
) {
1580 SignIn("primary@example.com");
1581 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1582 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1583 func
->set_extension(extension
.get());
1584 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
1585 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1586 func
.get(), "[{\"scopes\": [\"email\"]}]", browser()));
1587 std::string access_token
;
1588 EXPECT_TRUE(value
->GetAsString(&access_token
));
1589 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1591 const ExtensionTokenKey
* token_key
= func
->GetExtensionTokenKeyForTest();
1592 EXPECT_EQ(1ul, token_key
->scopes
.size());
1593 EXPECT_TRUE(ContainsKey(token_key
->scopes
, "email"));
1596 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, ScopesEmailFooBar
) {
1597 SignIn("primary@example.com");
1598 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1599 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1600 func
->set_extension(extension
.get());
1601 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
1602 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1603 func
.get(), "[{\"scopes\": [\"email\", \"foo\", \"bar\"]}]", browser()));
1604 std::string access_token
;
1605 EXPECT_TRUE(value
->GetAsString(&access_token
));
1606 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1608 const ExtensionTokenKey
* token_key
= func
->GetExtensionTokenKeyForTest();
1609 EXPECT_EQ(3ul, token_key
->scopes
.size());
1610 EXPECT_TRUE(ContainsKey(token_key
->scopes
, "email"));
1611 EXPECT_TRUE(ContainsKey(token_key
->scopes
, "foo"));
1612 EXPECT_TRUE(ContainsKey(token_key
->scopes
, "bar"));
1615 class RemoveCachedAuthTokenFunctionTest
: public ExtensionBrowserTest
{
1617 bool InvalidateDefaultToken() {
1618 scoped_refptr
<IdentityRemoveCachedAuthTokenFunction
> func(
1619 new IdentityRemoveCachedAuthTokenFunction
);
1620 func
->set_extension(test_util::CreateEmptyExtension(kExtensionId
).get());
1621 return utils::RunFunction(
1623 std::string("[{\"token\": \"") + kAccessToken
+ "\"}]",
1625 extension_function_test_utils::NONE
);
1628 IdentityAPI
* id_api() {
1629 return IdentityAPI::GetFactoryInstance()->Get(browser()->profile());
1632 void SetCachedToken(IdentityTokenCacheValue
& token_data
) {
1633 ExtensionTokenKey
key(
1634 kExtensionId
, "test@example.com", std::set
<std::string
>());
1635 id_api()->SetCachedToken(key
, token_data
);
1638 const IdentityTokenCacheValue
& GetCachedToken() {
1639 return id_api()->GetCachedToken(ExtensionTokenKey(
1640 kExtensionId
, "test@example.com", std::set
<std::string
>()));
1644 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest
, NotFound
) {
1645 EXPECT_TRUE(InvalidateDefaultToken());
1646 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND
,
1647 GetCachedToken().status());
1650 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest
, Advice
) {
1651 IssueAdviceInfo info
;
1652 IdentityTokenCacheValue
advice(info
);
1653 SetCachedToken(advice
);
1654 EXPECT_TRUE(InvalidateDefaultToken());
1655 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_ADVICE
,
1656 GetCachedToken().status());
1659 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest
, NonMatchingToken
) {
1660 IdentityTokenCacheValue
token("non_matching_token",
1661 base::TimeDelta::FromSeconds(3600));
1662 SetCachedToken(token
);
1663 EXPECT_TRUE(InvalidateDefaultToken());
1664 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
1665 GetCachedToken().status());
1666 EXPECT_EQ("non_matching_token", GetCachedToken().token());
1669 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest
, MatchingToken
) {
1670 IdentityTokenCacheValue
token(kAccessToken
,
1671 base::TimeDelta::FromSeconds(3600));
1672 SetCachedToken(token
);
1673 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
1674 GetCachedToken().status());
1675 EXPECT_TRUE(InvalidateDefaultToken());
1676 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND
,
1677 GetCachedToken().status());
1680 class LaunchWebAuthFlowFunctionTest
: public AsyncExtensionBrowserTest
{
1682 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
1683 AsyncExtensionBrowserTest::SetUpCommandLine(command_line
);
1684 // Reduce performance test variance by disabling background networking.
1685 command_line
->AppendSwitch(switches::kDisableBackgroundNetworking
);
1689 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest
, UserCloseWindow
) {
1690 net::SpawnedTestServer
https_server(
1691 net::SpawnedTestServer::TYPE_HTTPS
,
1692 net::SpawnedTestServer::kLocalhost
,
1693 base::FilePath(FILE_PATH_LITERAL(
1694 "chrome/test/data/extensions/api_test/identity")));
1695 ASSERT_TRUE(https_server
.Start());
1696 GURL
auth_url(https_server
.GetURL("files/interaction_required.html"));
1698 scoped_refptr
<IdentityLaunchWebAuthFlowFunction
> function(
1699 new IdentityLaunchWebAuthFlowFunction());
1700 scoped_refptr
<Extension
> empty_extension(test_util::CreateEmptyExtension());
1701 function
->set_extension(empty_extension
.get());
1703 WaitForGURLAndCloseWindow
popup_observer(auth_url
);
1705 std::string args
= "[{\"interactive\": true, \"url\": \"" +
1706 auth_url
.spec() + "\"}]";
1707 RunFunctionAsync(function
.get(), args
);
1709 popup_observer
.Wait();
1710 popup_observer
.CloseEmbedderWebContents();
1712 EXPECT_EQ(std::string(errors::kUserRejected
), WaitForError(function
.get()));
1715 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest
, InteractionRequired
) {
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/interaction_required.html"));
1724 scoped_refptr
<IdentityLaunchWebAuthFlowFunction
> function(
1725 new IdentityLaunchWebAuthFlowFunction());
1726 scoped_refptr
<Extension
> empty_extension(test_util::CreateEmptyExtension());
1727 function
->set_extension(empty_extension
.get());
1729 std::string args
= "[{\"interactive\": false, \"url\": \"" +
1730 auth_url
.spec() + "\"}]";
1732 utils::RunFunctionAndReturnError(function
.get(), args
, browser());
1734 EXPECT_EQ(std::string(errors::kInteractionRequired
), error
);
1737 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest
, LoadFailed
) {
1738 net::SpawnedTestServer
https_server(
1739 net::SpawnedTestServer::TYPE_HTTPS
,
1740 net::SpawnedTestServer::kLocalhost
,
1741 base::FilePath(FILE_PATH_LITERAL(
1742 "chrome/test/data/extensions/api_test/identity")));
1743 ASSERT_TRUE(https_server
.Start());
1744 GURL
auth_url(https_server
.GetURL("files/five_hundred.html"));
1746 scoped_refptr
<IdentityLaunchWebAuthFlowFunction
> function(
1747 new IdentityLaunchWebAuthFlowFunction());
1748 scoped_refptr
<Extension
> empty_extension(test_util::CreateEmptyExtension());
1749 function
->set_extension(empty_extension
.get());
1751 std::string args
= "[{\"interactive\": true, \"url\": \"" +
1752 auth_url
.spec() + "\"}]";
1754 utils::RunFunctionAndReturnError(function
.get(), args
, browser());
1756 EXPECT_EQ(std::string(errors::kPageLoadFailure
), error
);
1759 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest
, NonInteractiveSuccess
) {
1760 #if defined(OS_WIN) && defined(USE_ASH)
1761 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
1762 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1763 switches::kAshBrowserTests
))
1767 scoped_refptr
<IdentityLaunchWebAuthFlowFunction
> function(
1768 new IdentityLaunchWebAuthFlowFunction());
1769 scoped_refptr
<Extension
> empty_extension(test_util::CreateEmptyExtension());
1770 function
->set_extension(empty_extension
.get());
1772 function
->InitFinalRedirectURLPrefixForTest("abcdefghij");
1773 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1775 "[{\"interactive\": false,"
1776 "\"url\": \"https://abcdefghij.chromiumapp.org/callback#test\"}]",
1780 EXPECT_TRUE(value
->GetAsString(&url
));
1781 EXPECT_EQ(std::string("https://abcdefghij.chromiumapp.org/callback#test"),
1785 IN_PROC_BROWSER_TEST_F(
1786 LaunchWebAuthFlowFunctionTest
, InteractiveFirstNavigationSuccess
) {
1787 #if defined(OS_WIN) && defined(USE_ASH)
1788 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
1789 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1790 switches::kAshBrowserTests
))
1794 scoped_refptr
<IdentityLaunchWebAuthFlowFunction
> function(
1795 new IdentityLaunchWebAuthFlowFunction());
1796 scoped_refptr
<Extension
> empty_extension(test_util::CreateEmptyExtension());
1797 function
->set_extension(empty_extension
.get());
1799 function
->InitFinalRedirectURLPrefixForTest("abcdefghij");
1800 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1802 "[{\"interactive\": true,"
1803 "\"url\": \"https://abcdefghij.chromiumapp.org/callback#test\"}]",
1807 EXPECT_TRUE(value
->GetAsString(&url
));
1808 EXPECT_EQ(std::string("https://abcdefghij.chromiumapp.org/callback#test"),
1812 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest
,
1813 DISABLED_InteractiveSecondNavigationSuccess
) {
1814 net::SpawnedTestServer
https_server(
1815 net::SpawnedTestServer::TYPE_HTTPS
,
1816 net::SpawnedTestServer::kLocalhost
,
1817 base::FilePath(FILE_PATH_LITERAL(
1818 "chrome/test/data/extensions/api_test/identity")));
1819 ASSERT_TRUE(https_server
.Start());
1820 GURL
auth_url(https_server
.GetURL("files/redirect_to_chromiumapp.html"));
1822 scoped_refptr
<IdentityLaunchWebAuthFlowFunction
> function(
1823 new IdentityLaunchWebAuthFlowFunction());
1824 scoped_refptr
<Extension
> empty_extension(test_util::CreateEmptyExtension());
1825 function
->set_extension(empty_extension
.get());
1827 function
->InitFinalRedirectURLPrefixForTest("abcdefghij");
1828 std::string args
= "[{\"interactive\": true, \"url\": \"" +
1829 auth_url
.spec() + "\"}]";
1830 scoped_ptr
<base::Value
> value(
1831 utils::RunFunctionAndReturnSingleResult(function
.get(), args
, browser()));
1834 EXPECT_TRUE(value
->GetAsString(&url
));
1835 EXPECT_EQ(std::string("https://abcdefghij.chromiumapp.org/callback#test"),
1839 } // namespace extensions
1841 // Tests the chrome.identity API implemented by custom JS bindings .
1842 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, ChromeIdentityJsBindings
) {
1843 ASSERT_TRUE(RunExtensionTest("identity/js_bindings")) << message_
;