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()),
240 embedder_web_contents_(nullptr) {}
242 // NotificationObserver:
243 void Observe(int type
,
244 const content::NotificationSource
& source
,
245 const content::NotificationDetails
& details
) override
{
246 content::NavigationController
* web_auth_flow_controller
=
247 content::Source
<content::NavigationController
>(source
).ptr();
248 content::WebContents
* web_contents
=
249 web_auth_flow_controller
->GetWebContents();
251 if (web_contents
->GetURL() == url_
) {
252 // It is safe to keep the pointer here, because we know in a test, that
253 // the WebContents won't go away before CloseEmbedderWebContents is
254 // called. Don't copy this code to production.
255 GuestViewBase
* guest
= GuestViewBase::FromWebContents(web_contents
);
256 embedder_web_contents_
= guest
->embedder_web_contents();
257 // Condtionally invoke parent class so that Wait will not exit
258 // until the target URL arrives.
259 content::WindowedNotificationObserver::Observe(type
, source
, details
);
263 // Closes the window embedding the WebContents. The action is separated from
264 // the Observe method to make sure the list of observers is not deleted,
265 // while some event is already being processed. (That causes ASAN failures.)
266 void CloseEmbedderWebContents() {
267 if (embedder_web_contents_
)
268 embedder_web_contents_
->Close();
273 content::WebContents
* embedder_web_contents_
;
278 class FakeGetAuthTokenFunction
: public IdentityGetAuthTokenFunction
{
280 FakeGetAuthTokenFunction()
281 : login_access_token_result_(true),
282 auto_login_access_token_(true),
283 login_ui_result_(true),
284 scope_ui_result_(true),
285 scope_ui_failure_(GaiaWebAuthFlow::WINDOW_CLOSED
),
286 login_ui_shown_(false),
287 scope_ui_shown_(false) {}
289 void set_login_access_token_result(bool result
) {
290 login_access_token_result_
= result
;
293 void set_auto_login_access_token(bool automatic
) {
294 auto_login_access_token_
= automatic
;
297 void set_login_ui_result(bool result
) { login_ui_result_
= result
; }
299 void set_mint_token_flow(scoped_ptr
<OAuth2MintTokenFlow
> flow
) {
303 void set_mint_token_result(TestOAuth2MintTokenFlow::ResultType result_type
) {
305 make_scoped_ptr(new TestOAuth2MintTokenFlow(result_type
, this)));
308 void set_scope_ui_failure(GaiaWebAuthFlow::Failure failure
) {
309 scope_ui_result_
= false;
310 scope_ui_failure_
= failure
;
313 void set_scope_ui_oauth_error(const std::string
& oauth_error
) {
314 scope_ui_result_
= false;
315 scope_ui_failure_
= GaiaWebAuthFlow::OAUTH_ERROR
;
316 scope_ui_oauth_error_
= oauth_error
;
319 bool login_ui_shown() const { return login_ui_shown_
; }
321 bool scope_ui_shown() const { return scope_ui_shown_
; }
323 std::string
login_access_token() const { return login_access_token_
; }
325 void StartLoginAccessTokenRequest() override
{
326 if (auto_login_access_token_
) {
327 if (login_access_token_result_
) {
328 OnGetTokenSuccess(login_token_request_
.get(),
330 base::Time::Now() + base::TimeDelta::FromHours(1LL));
332 GoogleServiceAuthError
error(
333 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
);
334 OnGetTokenFailure(login_token_request_
.get(), error
);
337 // Make a request to the token service. The test now must tell
338 // the token service to issue an access token (or an error).
339 IdentityGetAuthTokenFunction::StartLoginAccessTokenRequest();
343 void ShowLoginPopup() override
{
344 EXPECT_FALSE(login_ui_shown_
);
345 login_ui_shown_
= true;
346 if (login_ui_result_
)
352 void ShowOAuthApprovalDialog(const IssueAdviceInfo
& issue_advice
) override
{
353 scope_ui_shown_
= true;
355 if (scope_ui_result_
) {
356 OnGaiaFlowCompleted(kAccessToken
, "3600");
357 } else if (scope_ui_failure_
== GaiaWebAuthFlow::SERVICE_AUTH_ERROR
) {
358 GoogleServiceAuthError
error(GoogleServiceAuthError::CONNECTION_FAILED
);
359 OnGaiaFlowFailure(scope_ui_failure_
, error
, "");
361 GoogleServiceAuthError
error(GoogleServiceAuthError::NONE
);
362 OnGaiaFlowFailure(scope_ui_failure_
, error
, scope_ui_oauth_error_
);
366 void StartGaiaRequest(const std::string
& login_access_token
) override
{
367 EXPECT_TRUE(login_access_token_
.empty());
368 // Save the login token used in the mint token flow so tests can see
369 // what account was used.
370 login_access_token_
= login_access_token
;
371 IdentityGetAuthTokenFunction::StartGaiaRequest(login_access_token
);
374 OAuth2MintTokenFlow
* CreateMintTokenFlow() override
{
375 return flow_
.release();
379 ~FakeGetAuthTokenFunction() override
{}
380 bool login_access_token_result_
;
381 bool auto_login_access_token_
;
382 bool login_ui_result_
;
383 bool scope_ui_result_
;
384 GaiaWebAuthFlow::Failure scope_ui_failure_
;
385 std::string scope_ui_oauth_error_
;
386 bool login_ui_shown_
;
387 bool scope_ui_shown_
;
389 scoped_ptr
<OAuth2MintTokenFlow
> flow_
;
391 std::string login_access_token_
;
394 class MockQueuedMintRequest
: public IdentityMintRequestQueue::Request
{
396 MOCK_METHOD1(StartMintToken
, void(IdentityMintRequestQueue::MintType
));
399 gaia::AccountIds
CreateIds(std::string email
, std::string obfid
) {
400 gaia::AccountIds ids
;
401 ids
.account_key
= email
;
407 class IdentityGetAccountsFunctionTest
: public ExtensionBrowserTest
{
408 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
409 ExtensionBrowserTest::SetUpCommandLine(command_line
);
410 command_line
->AppendSwitch(switches::kExtensionsMultiAccount
);
414 void SetAccountState(gaia::AccountIds ids
, bool is_signed_in
) {
415 IdentityAPI::GetFactoryInstance()->Get(profile())->SetAccountStateForTest(
419 testing::AssertionResult
ExpectGetAccounts(
420 const std::vector
<std::string
>& accounts
) {
421 scoped_refptr
<IdentityGetAccountsFunction
> func(
422 new IdentityGetAccountsFunction
);
423 func
->set_extension(test_util::CreateEmptyExtension(kExtensionId
).get());
424 if (!utils::RunFunction(
425 func
.get(), std::string("[]"), browser(), utils::NONE
)) {
426 return GenerateFailureResult(accounts
, NULL
)
427 << "getAccounts did not return a result.";
429 const base::ListValue
* callback_arguments
= func
->GetResultList();
430 if (!callback_arguments
)
431 return GenerateFailureResult(accounts
, NULL
) << "NULL result";
433 if (callback_arguments
->GetSize() != 1) {
434 return GenerateFailureResult(accounts
, NULL
)
435 << "Expected 1 argument but got " << callback_arguments
->GetSize();
438 const base::ListValue
* results
;
439 if (!callback_arguments
->GetList(0, &results
))
440 GenerateFailureResult(accounts
, NULL
) << "Result was not an array";
442 std::set
<std::string
> result_ids
;
443 for (base::ListValue::const_iterator it
= results
->begin();
444 it
!= results
->end();
446 scoped_ptr
<api::identity::AccountInfo
> info
=
447 api::identity::AccountInfo::FromValue(**it
);
449 result_ids
.insert(info
->id
);
451 return GenerateFailureResult(accounts
, results
);
454 for (std::vector
<std::string
>::const_iterator it
= accounts
.begin();
455 it
!= accounts
.end();
457 if (result_ids
.find(*it
) == result_ids
.end())
458 return GenerateFailureResult(accounts
, results
);
461 return testing::AssertionResult(true);
464 testing::AssertionResult
GenerateFailureResult(
465 const ::std::vector
<std::string
>& accounts
,
466 const base::ListValue
* results
) {
467 testing::Message
msg("Expected: ");
468 for (std::vector
<std::string
>::const_iterator it
= accounts
.begin();
469 it
!= accounts
.end();
477 for (base::ListValue::const_iterator it
= results
->begin();
478 it
!= results
->end();
480 scoped_ptr
<api::identity::AccountInfo
> info
=
481 api::identity::AccountInfo::FromValue(**it
);
483 msg
<< info
->id
<< " ";
485 msg
<< *it
<< "<-" << (*it
)->GetType() << " ";
489 return testing::AssertionFailure(msg
);
493 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest
, MultiAccountOn
) {
494 EXPECT_TRUE(switches::IsExtensionsMultiAccount());
497 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest
, NoneSignedIn
) {
498 EXPECT_TRUE(ExpectGetAccounts(std::vector
<std::string
>()));
501 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest
,
502 PrimaryAccountSignedIn
) {
503 SetAccountState(CreateIds("primary@example.com", "1"), true);
504 std::vector
<std::string
> primary
;
505 primary
.push_back("1");
506 EXPECT_TRUE(ExpectGetAccounts(primary
));
509 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest
, TwoAccountsSignedIn
) {
510 SetAccountState(CreateIds("primary@example.com", "1"), true);
511 SetAccountState(CreateIds("secondary@example.com", "2"), true);
512 std::vector
<std::string
> two_accounts
;
513 two_accounts
.push_back("1");
514 two_accounts
.push_back("2");
515 EXPECT_TRUE(ExpectGetAccounts(two_accounts
));
518 class IdentityOldProfilesGetAccountsFunctionTest
519 : public IdentityGetAccountsFunctionTest
{
520 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
521 // Don't add the multi-account switch that parent class would have.
525 IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest
,
527 EXPECT_FALSE(switches::IsExtensionsMultiAccount());
530 IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest
,
531 TwoAccountsSignedIn
) {
532 SetAccountState(CreateIds("primary@example.com", "1"), true);
533 SetAccountState(CreateIds("secondary@example.com", "2"), true);
534 std::vector
<std::string
> only_primary
;
535 only_primary
.push_back("1");
536 EXPECT_TRUE(ExpectGetAccounts(only_primary
));
539 class IdentityTestWithSignin
: public AsyncExtensionBrowserTest
{
541 void SetUpInProcessBrowserTestFixture() override
{
542 AsyncExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
544 will_create_browser_context_services_subscription_
=
545 BrowserContextDependencyManager::GetInstance()
546 ->RegisterWillCreateBrowserContextServicesCallbackForTesting(
547 base::Bind(&IdentityTestWithSignin::
548 OnWillCreateBrowserContextServices
,
549 base::Unretained(this)))
553 void OnWillCreateBrowserContextServices(content::BrowserContext
* context
) {
554 // Replace the signin manager and token service with fakes. Do this ahead of
555 // creating the browser so that a bunch of classes don't register as
556 // observers and end up needing to unregister when the fake is substituted.
557 SigninManagerFactory::GetInstance()->SetTestingFactory(
558 context
, &BuildFakeSigninManagerBase
);
559 ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory(
560 context
, &BuildFakeProfileOAuth2TokenService
);
561 GaiaCookieManagerServiceFactory::GetInstance()->SetTestingFactory(
562 context
, &FakeGaiaCookieManagerService::Build
);
565 void SetUpOnMainThread() override
{
566 AsyncExtensionBrowserTest::SetUpOnMainThread();
568 // Grab references to the fake signin manager and token service.
569 signin_manager_
= static_cast<FakeSigninManagerForTesting
*>(
570 SigninManagerFactory::GetInstance()->GetForProfile(profile()));
571 ASSERT_TRUE(signin_manager_
);
572 token_service_
= static_cast<FakeProfileOAuth2TokenService
*>(
573 ProfileOAuth2TokenServiceFactory::GetInstance()->GetForProfile(
575 ASSERT_TRUE(token_service_
);
576 GaiaCookieManagerServiceFactory::GetInstance()->GetForProfile(profile())
581 void SignIn(const std::string
& account_key
) {
582 SignIn(account_key
, account_key
);
585 void SignIn(const std::string
& email
, const std::string
& gaia
) {
586 AccountTrackerService
* account_tracker
=
587 AccountTrackerServiceFactory::GetForProfile(profile());
588 std::string account_id
=
589 account_tracker
->SeedAccountInfo(gaia
, email
);
591 #if defined(OS_CHROMEOS)
592 signin_manager_
->SetAuthenticatedAccountInfo(gaia
, email
);
594 signin_manager_
->SignIn(gaia
, email
, "password");
596 token_service_
->UpdateCredentials(account_id
, "refresh_token");
599 FakeSigninManagerForTesting
* signin_manager_
;
600 FakeProfileOAuth2TokenService
* token_service_
;
602 scoped_ptr
<base::CallbackList
<void(content::BrowserContext
*)>::Subscription
>
603 will_create_browser_context_services_subscription_
;
606 class IdentityGetProfileUserInfoFunctionTest
: public IdentityTestWithSignin
{
608 scoped_ptr
<api::identity::ProfileUserInfo
> RunGetProfileUserInfo() {
609 scoped_refptr
<IdentityGetProfileUserInfoFunction
> func(
610 new IdentityGetProfileUserInfoFunction
);
611 func
->set_extension(test_util::CreateEmptyExtension(kExtensionId
).get());
612 scoped_ptr
<base::Value
> value(
613 utils::RunFunctionAndReturnSingleResult(func
.get(), "[]", browser()));
614 return api::identity::ProfileUserInfo::FromValue(*value
.get());
617 scoped_ptr
<api::identity::ProfileUserInfo
> RunGetProfileUserInfoWithEmail() {
618 scoped_refptr
<IdentityGetProfileUserInfoFunction
> func(
619 new IdentityGetProfileUserInfoFunction
);
620 func
->set_extension(CreateExtensionWithEmailPermission());
621 scoped_ptr
<base::Value
> value(
622 utils::RunFunctionAndReturnSingleResult(func
.get(), "[]", browser()));
623 return api::identity::ProfileUserInfo::FromValue(*value
.get());
627 scoped_refptr
<Extension
> CreateExtensionWithEmailPermission() {
628 scoped_ptr
<base::DictionaryValue
> test_extension_value(
629 api_test_utils::ParseDictionary(
630 "{\"name\": \"Test\", \"version\": \"1.0\", "
631 "\"permissions\": [\"identity.email\"]}"));
632 return api_test_utils::CreateExtension(test_extension_value
.get());
636 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest
, NotSignedIn
) {
637 scoped_ptr
<api::identity::ProfileUserInfo
> info
=
638 RunGetProfileUserInfoWithEmail();
639 EXPECT_TRUE(info
->email
.empty());
640 EXPECT_TRUE(info
->id
.empty());
643 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest
, SignedIn
) {
644 SignIn("president@example.com", "12345");
645 scoped_ptr
<api::identity::ProfileUserInfo
> info
=
646 RunGetProfileUserInfoWithEmail();
647 EXPECT_EQ("president@example.com", info
->email
);
648 EXPECT_EQ("12345", info
->id
);
651 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest
,
652 NotSignedInNoEmail
) {
653 scoped_ptr
<api::identity::ProfileUserInfo
> info
= RunGetProfileUserInfo();
654 EXPECT_TRUE(info
->email
.empty());
655 EXPECT_TRUE(info
->id
.empty());
658 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest
,
660 SignIn("president@example.com", "12345");
661 scoped_ptr
<api::identity::ProfileUserInfo
> info
= RunGetProfileUserInfo();
662 EXPECT_TRUE(info
->email
.empty());
663 EXPECT_TRUE(info
->id
.empty());
666 class GetAuthTokenFunctionTest
: public IdentityTestWithSignin
{
668 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
669 IdentityTestWithSignin::SetUpCommandLine(command_line
);
670 command_line
->AppendSwitch(switches::kExtensionsMultiAccount
);
673 void IssueLoginRefreshTokenForAccount(const std::string account_key
) {
674 token_service_
->UpdateCredentials(account_key
, "refresh_token");
677 void IssueLoginAccessTokenForAccount(const std::string account_key
) {
678 token_service_
->IssueAllTokensForAccount(
680 "access_token-" + account_key
,
681 base::Time::Now() + base::TimeDelta::FromSeconds(3600));
684 void SetAccountState(gaia::AccountIds ids
, bool is_signed_in
) {
685 IdentityAPI::GetFactoryInstance()->Get(profile())->SetAccountStateForTest(
697 ~GetAuthTokenFunctionTest() override
{}
699 // Helper to create an extension with specific OAuth2Info fields set.
700 // |fields_to_set| should be computed by using fields of Oauth2Fields enum.
701 const Extension
* CreateExtension(int fields_to_set
) {
702 const Extension
* ext
;
703 base::FilePath manifest_path
=
704 test_data_dir_
.AppendASCII("platform_apps/oauth2");
705 base::FilePath component_manifest_path
=
706 test_data_dir_
.AppendASCII("packaged_app/component_oauth2");
707 if ((fields_to_set
& AS_COMPONENT
) == 0)
708 ext
= LoadExtension(manifest_path
);
710 ext
= LoadExtensionAsComponent(component_manifest_path
);
711 OAuth2Info
& oauth2_info
=
712 const_cast<OAuth2Info
&>(OAuth2Info::GetOAuth2Info(ext
));
713 if ((fields_to_set
& CLIENT_ID
) != 0)
714 oauth2_info
.client_id
= "client1";
715 if ((fields_to_set
& SCOPES
) != 0) {
716 oauth2_info
.scopes
.push_back("scope1");
717 oauth2_info
.scopes
.push_back("scope2");
720 extension_id_
= ext
->id();
721 oauth_scopes_
= std::set
<std::string
>(oauth2_info
.scopes
.begin(),
722 oauth2_info
.scopes
.end());
726 IdentityAPI
* id_api() {
727 return IdentityAPI::GetFactoryInstance()->Get(browser()->profile());
730 const std::string
& GetPrimaryAccountId() {
731 SigninManagerBase
* signin_manager
=
732 SigninManagerFactory::GetForProfile(browser()->profile());
733 return signin_manager
->GetAuthenticatedAccountId();
736 void SetCachedToken(const IdentityTokenCacheValue
& token_data
) {
737 ExtensionTokenKey
key(extension_id_
, GetPrimaryAccountId(), oauth_scopes_
);
738 id_api()->SetCachedToken(key
, token_data
);
741 const IdentityTokenCacheValue
& GetCachedToken(std::string account_id
) {
742 if (account_id
.empty())
743 account_id
= GetPrimaryAccountId();
744 ExtensionTokenKey
key(extension_id_
, account_id
, oauth_scopes_
);
745 return id_api()->GetCachedToken(key
);
748 void QueueRequestStart(IdentityMintRequestQueue::MintType type
,
749 IdentityMintRequestQueue::Request
* request
) {
750 ExtensionTokenKey
key(extension_id_
, GetPrimaryAccountId(), oauth_scopes_
);
751 id_api()->mint_queue()->RequestStart(type
, key
, request
);
754 void QueueRequestComplete(IdentityMintRequestQueue::MintType type
,
755 IdentityMintRequestQueue::Request
* request
) {
756 ExtensionTokenKey
key(extension_id_
, GetPrimaryAccountId(), oauth_scopes_
);
757 id_api()->mint_queue()->RequestComplete(type
, key
, request
);
761 std::string extension_id_
;
762 std::set
<std::string
> oauth_scopes_
;
765 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
767 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
768 func
->set_extension(CreateExtension(SCOPES
));
769 std::string error
= utils::RunFunctionAndReturnError(
770 func
.get(), "[{}]", browser());
771 EXPECT_EQ(std::string(errors::kInvalidClientId
), error
);
772 EXPECT_FALSE(func
->login_ui_shown());
773 EXPECT_FALSE(func
->scope_ui_shown());
776 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
778 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
779 func
->set_extension(CreateExtension(CLIENT_ID
));
780 std::string error
= utils::RunFunctionAndReturnError(
781 func
.get(), "[{}]", browser());
782 EXPECT_EQ(std::string(errors::kInvalidScopes
), error
);
783 EXPECT_FALSE(func
->login_ui_shown());
784 EXPECT_FALSE(func
->scope_ui_shown());
787 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
788 NonInteractiveNotSignedIn
) {
789 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
790 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
791 std::string error
= utils::RunFunctionAndReturnError(
792 func
.get(), "[{}]", browser());
793 EXPECT_EQ(std::string(errors::kUserNotSignedIn
), error
);
794 EXPECT_FALSE(func
->login_ui_shown());
795 EXPECT_FALSE(func
->scope_ui_shown());
798 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
799 NonInteractiveMintFailure
) {
800 SignIn("primary@example.com");
801 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
802 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
803 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE
);
805 utils::RunFunctionAndReturnError(func
.get(), "[{}]", browser());
806 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
807 base::CompareCase::INSENSITIVE_ASCII
));
808 EXPECT_FALSE(func
->login_ui_shown());
809 EXPECT_FALSE(func
->scope_ui_shown());
812 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
813 NonInteractiveLoginAccessTokenFailure
) {
814 SignIn("primary@example.com");
815 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
816 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
817 func
->set_login_access_token_result(false);
818 std::string error
= utils::RunFunctionAndReturnError(
819 func
.get(), "[{}]", browser());
820 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
821 base::CompareCase::INSENSITIVE_ASCII
));
824 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
825 NonInteractiveMintAdviceSuccess
) {
826 SignIn("primary@example.com");
827 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
828 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
829 func
->set_extension(extension
.get());
830 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
832 utils::RunFunctionAndReturnError(func
.get(), "[{}]", browser());
833 EXPECT_EQ(std::string(errors::kNoGrant
), error
);
834 EXPECT_FALSE(func
->login_ui_shown());
835 EXPECT_FALSE(func
->scope_ui_shown());
837 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_ADVICE
,
838 GetCachedToken(std::string()).status());
841 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
842 NonInteractiveMintBadCredentials
) {
843 SignIn("primary@example.com");
844 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
845 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
846 func
->set_mint_token_result(
847 TestOAuth2MintTokenFlow::MINT_TOKEN_BAD_CREDENTIALS
);
849 utils::RunFunctionAndReturnError(func
.get(), "[{}]", browser());
850 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
851 base::CompareCase::INSENSITIVE_ASCII
));
852 EXPECT_FALSE(func
->login_ui_shown());
853 EXPECT_FALSE(func
->scope_ui_shown());
856 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
857 NonInteractiveMintServiceError
) {
858 SignIn("primary@example.com");
859 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
860 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
861 func
->set_mint_token_result(
862 TestOAuth2MintTokenFlow::MINT_TOKEN_SERVICE_ERROR
);
864 utils::RunFunctionAndReturnError(func
.get(), "[{}]", browser());
865 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
866 base::CompareCase::INSENSITIVE_ASCII
));
867 EXPECT_FALSE(func
->login_ui_shown());
868 EXPECT_FALSE(func
->scope_ui_shown());
871 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
873 SignIn("primary@example.com");
874 #if defined(OS_WIN) && defined(USE_ASH)
875 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
876 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
877 switches::kAshBrowserTests
))
881 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
882 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
883 func
->set_extension(extension
.get());
884 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
885 scoped_ptr
<base::Value
> value(
886 utils::RunFunctionAndReturnSingleResult(func
.get(), "[]", browser()));
887 std::string access_token
;
888 EXPECT_TRUE(value
->GetAsString(&access_token
));
889 EXPECT_EQ(std::string(kAccessToken
), access_token
);
890 EXPECT_FALSE(func
->login_ui_shown());
891 EXPECT_FALSE(func
->scope_ui_shown());
892 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
893 GetCachedToken(std::string()).status());
896 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
897 NonInteractiveSuccess
) {
898 SignIn("primary@example.com");
899 #if defined(OS_WIN) && defined(USE_ASH)
900 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
901 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
902 switches::kAshBrowserTests
))
906 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
907 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
908 func
->set_extension(extension
.get());
909 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
910 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
911 func
.get(), "[{}]", browser()));
912 std::string access_token
;
913 EXPECT_TRUE(value
->GetAsString(&access_token
));
914 EXPECT_EQ(std::string(kAccessToken
), access_token
);
915 EXPECT_FALSE(func
->login_ui_shown());
916 EXPECT_FALSE(func
->scope_ui_shown());
917 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
918 GetCachedToken(std::string()).status());
921 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
922 InteractiveLoginCanceled
) {
923 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
924 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
925 func
->set_login_ui_result(false);
926 std::string error
= utils::RunFunctionAndReturnError(
927 func
.get(), "[{\"interactive\": true}]", browser());
928 EXPECT_EQ(std::string(errors::kUserNotSignedIn
), error
);
929 EXPECT_TRUE(func
->login_ui_shown());
930 EXPECT_FALSE(func
->scope_ui_shown());
933 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
934 InteractiveMintBadCredentialsLoginCanceled
) {
935 SignIn("primary@example.com");
936 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
937 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
938 func
->set_mint_token_result(
939 TestOAuth2MintTokenFlow::MINT_TOKEN_BAD_CREDENTIALS
);
940 func
->set_login_ui_result(false);
941 std::string error
= utils::RunFunctionAndReturnError(
942 func
.get(), "[{\"interactive\": true}]", browser());
943 EXPECT_EQ(std::string(errors::kUserNotSignedIn
), error
);
944 EXPECT_TRUE(func
->login_ui_shown());
945 EXPECT_FALSE(func
->scope_ui_shown());
948 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
949 InteractiveLoginSuccessNoToken
) {
950 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
951 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
952 func
->set_login_ui_result(false);
953 std::string error
= utils::RunFunctionAndReturnError(
954 func
.get(), "[{\"interactive\": true}]", browser());
955 EXPECT_EQ(std::string(errors::kUserNotSignedIn
), error
);
956 EXPECT_TRUE(func
->login_ui_shown());
957 EXPECT_FALSE(func
->scope_ui_shown());
960 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
961 InteractiveLoginSuccessMintFailure
) {
962 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
963 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
964 func
->set_login_ui_result(true);
965 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE
);
966 std::string error
= utils::RunFunctionAndReturnError(
967 func
.get(), "[{\"interactive\": true}]", browser());
968 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
969 base::CompareCase::INSENSITIVE_ASCII
));
970 EXPECT_TRUE(func
->login_ui_shown());
971 EXPECT_FALSE(func
->scope_ui_shown());
974 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
975 InteractiveLoginSuccessLoginAccessTokenFailure
) {
976 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
977 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
978 func
->set_login_ui_result(true);
979 func
->set_login_access_token_result(false);
980 std::string error
= utils::RunFunctionAndReturnError(
981 func
.get(), "[{\"interactive\": true}]", browser());
982 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
983 base::CompareCase::INSENSITIVE_ASCII
));
984 EXPECT_TRUE(func
->login_ui_shown());
985 EXPECT_FALSE(func
->scope_ui_shown());
988 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
989 InteractiveLoginSuccessMintSuccess
) {
990 // TODO(courage): verify that account_id in token service requests
991 // is correct once manual token minting for tests is implemented.
992 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
993 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
994 func
->set_login_ui_result(true);
995 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
996 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
997 func
.get(), "[{\"interactive\": true}]", browser()));
998 std::string access_token
;
999 EXPECT_TRUE(value
->GetAsString(&access_token
));
1000 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1001 EXPECT_TRUE(func
->login_ui_shown());
1002 EXPECT_FALSE(func
->scope_ui_shown());
1005 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1006 InteractiveLoginSuccessApprovalAborted
) {
1007 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1008 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
1009 func
->set_login_ui_result(true);
1010 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1011 func
->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED
);
1012 std::string error
= utils::RunFunctionAndReturnError(
1013 func
.get(), "[{\"interactive\": true}]", browser());
1014 EXPECT_EQ(std::string(errors::kUserRejected
), error
);
1015 EXPECT_TRUE(func
->login_ui_shown());
1016 EXPECT_TRUE(func
->scope_ui_shown());
1019 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1020 InteractiveLoginSuccessApprovalSuccess
) {
1021 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1022 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1023 func
->set_extension(extension
.get());
1024 func
->set_login_ui_result(true);
1025 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1027 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1028 func
.get(), "[{\"interactive\": true}]", browser()));
1029 std::string access_token
;
1030 EXPECT_TRUE(value
->GetAsString(&access_token
));
1031 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1032 EXPECT_TRUE(func
->login_ui_shown());
1033 EXPECT_TRUE(func
->scope_ui_shown());
1036 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1037 InteractiveApprovalAborted
) {
1038 SignIn("primary@example.com");
1039 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1040 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
1041 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1042 func
->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED
);
1043 std::string error
= utils::RunFunctionAndReturnError(
1044 func
.get(), "[{\"interactive\": true}]", browser());
1045 EXPECT_EQ(std::string(errors::kUserRejected
), error
);
1046 EXPECT_FALSE(func
->login_ui_shown());
1047 EXPECT_TRUE(func
->scope_ui_shown());
1050 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1051 InteractiveApprovalLoadFailed
) {
1052 SignIn("primary@example.com");
1053 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1054 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
1055 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1056 func
->set_scope_ui_failure(GaiaWebAuthFlow::LOAD_FAILED
);
1057 std::string error
= utils::RunFunctionAndReturnError(
1058 func
.get(), "[{\"interactive\": true}]", browser());
1059 EXPECT_EQ(std::string(errors::kPageLoadFailure
), error
);
1060 EXPECT_FALSE(func
->login_ui_shown());
1061 EXPECT_TRUE(func
->scope_ui_shown());
1064 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1065 InteractiveApprovalInvalidRedirect
) {
1066 SignIn("primary@example.com");
1067 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1068 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
1069 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1070 func
->set_scope_ui_failure(GaiaWebAuthFlow::INVALID_REDIRECT
);
1071 std::string error
= utils::RunFunctionAndReturnError(
1072 func
.get(), "[{\"interactive\": true}]", browser());
1073 EXPECT_EQ(std::string(errors::kInvalidRedirect
), error
);
1074 EXPECT_FALSE(func
->login_ui_shown());
1075 EXPECT_TRUE(func
->scope_ui_shown());
1078 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1079 InteractiveApprovalConnectionFailure
) {
1080 SignIn("primary@example.com");
1081 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1082 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
1083 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1084 func
->set_scope_ui_failure(GaiaWebAuthFlow::SERVICE_AUTH_ERROR
);
1085 std::string error
= utils::RunFunctionAndReturnError(
1086 func
.get(), "[{\"interactive\": true}]", browser());
1087 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
1088 base::CompareCase::INSENSITIVE_ASCII
));
1089 EXPECT_FALSE(func
->login_ui_shown());
1090 EXPECT_TRUE(func
->scope_ui_shown());
1093 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1094 InteractiveApprovalOAuthErrors
) {
1095 SignIn("primary@example.com");
1096 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1098 std::map
<std::string
, std::string
> error_map
;
1099 error_map
.insert(std::make_pair("access_denied", errors::kUserRejected
));
1100 error_map
.insert(std::make_pair("invalid_scope", errors::kInvalidScopes
));
1101 error_map
.insert(std::make_pair(
1102 "unmapped_error", std::string(errors::kAuthFailure
) + "unmapped_error"));
1104 for (std::map
<std::string
, std::string
>::const_iterator
1105 it
= error_map
.begin();
1106 it
!= error_map
.end();
1108 scoped_refptr
<FakeGetAuthTokenFunction
> func(
1109 new FakeGetAuthTokenFunction());
1110 func
->set_extension(extension
.get());
1111 // Make sure we don't get a cached issue_advice result, which would cause
1112 // flow to be leaked.
1113 id_api()->EraseAllCachedTokens();
1114 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1115 func
->set_scope_ui_oauth_error(it
->first
);
1116 std::string error
= utils::RunFunctionAndReturnError(
1117 func
.get(), "[{\"interactive\": true}]", browser());
1118 EXPECT_EQ(it
->second
, error
);
1119 EXPECT_FALSE(func
->login_ui_shown());
1120 EXPECT_TRUE(func
->scope_ui_shown());
1124 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1125 InteractiveApprovalSuccess
) {
1126 SignIn("primary@example.com");
1127 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1128 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1129 func
->set_extension(extension
.get());
1130 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1132 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1133 func
.get(), "[{\"interactive\": true}]", browser()));
1134 std::string access_token
;
1135 EXPECT_TRUE(value
->GetAsString(&access_token
));
1136 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1137 EXPECT_FALSE(func
->login_ui_shown());
1138 EXPECT_TRUE(func
->scope_ui_shown());
1140 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
1141 GetCachedToken(std::string()).status());
1144 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, NoninteractiveQueue
) {
1145 SignIn("primary@example.com");
1146 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1147 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1148 func
->set_extension(extension
.get());
1150 // Create a fake request to block the queue.
1151 MockQueuedMintRequest queued_request
;
1152 IdentityMintRequestQueue::MintType type
=
1153 IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE
;
1155 EXPECT_CALL(queued_request
, StartMintToken(type
)).Times(1);
1156 QueueRequestStart(type
, &queued_request
);
1158 // The real request will start processing, but wait in the queue behind
1160 RunFunctionAsync(func
.get(), "[{}]");
1161 // Verify that we have fetched the login token at this point.
1162 testing::Mock::VerifyAndClearExpectations(func
.get());
1164 // The flow will be created after the first queued request clears.
1165 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
1167 QueueRequestComplete(type
, &queued_request
);
1169 scoped_ptr
<base::Value
> value(WaitForSingleResult(func
.get()));
1170 std::string access_token
;
1171 EXPECT_TRUE(value
->GetAsString(&access_token
));
1172 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1173 EXPECT_FALSE(func
->login_ui_shown());
1174 EXPECT_FALSE(func
->scope_ui_shown());
1177 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, InteractiveQueue
) {
1178 SignIn("primary@example.com");
1179 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1180 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1181 func
->set_extension(extension
.get());
1183 // Create a fake request to block the queue.
1184 MockQueuedMintRequest queued_request
;
1185 IdentityMintRequestQueue::MintType type
=
1186 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE
;
1188 EXPECT_CALL(queued_request
, StartMintToken(type
)).Times(1);
1189 QueueRequestStart(type
, &queued_request
);
1191 // The real request will start processing, but wait in the queue behind
1193 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1194 RunFunctionAsync(func
.get(), "[{\"interactive\": true}]");
1195 // Verify that we have fetched the login token and run the first flow.
1196 testing::Mock::VerifyAndClearExpectations(func
.get());
1197 EXPECT_FALSE(func
->scope_ui_shown());
1199 // The UI will be displayed and a token retrieved after the first
1200 // queued request clears.
1201 QueueRequestComplete(type
, &queued_request
);
1203 scoped_ptr
<base::Value
> value(WaitForSingleResult(func
.get()));
1204 std::string access_token
;
1205 EXPECT_TRUE(value
->GetAsString(&access_token
));
1206 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1207 EXPECT_FALSE(func
->login_ui_shown());
1208 EXPECT_TRUE(func
->scope_ui_shown());
1211 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, InteractiveQueueShutdown
) {
1212 SignIn("primary@example.com");
1213 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1214 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1215 func
->set_extension(extension
.get());
1217 // Create a fake request to block the queue.
1218 MockQueuedMintRequest queued_request
;
1219 IdentityMintRequestQueue::MintType type
=
1220 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE
;
1222 EXPECT_CALL(queued_request
, StartMintToken(type
)).Times(1);
1223 QueueRequestStart(type
, &queued_request
);
1225 // The real request will start processing, but wait in the queue behind
1227 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1228 RunFunctionAsync(func
.get(), "[{\"interactive\": true}]");
1229 // Verify that we have fetched the login token and run the first flow.
1230 testing::Mock::VerifyAndClearExpectations(func
.get());
1231 EXPECT_FALSE(func
->scope_ui_shown());
1233 // After the request is canceled, the function will complete.
1235 EXPECT_EQ(std::string(errors::kCanceled
), WaitForError(func
.get()));
1236 EXPECT_FALSE(func
->login_ui_shown());
1237 EXPECT_FALSE(func
->scope_ui_shown());
1239 QueueRequestComplete(type
, &queued_request
);
1242 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, NoninteractiveShutdown
) {
1243 SignIn("primary@example.com");
1244 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1245 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1246 func
->set_extension(extension
.get());
1248 func
->set_mint_token_flow(make_scoped_ptr(new TestHangOAuth2MintTokenFlow()));
1249 RunFunctionAsync(func
.get(), "[{\"interactive\": false}]");
1251 // After the request is canceled, the function will complete.
1253 EXPECT_EQ(std::string(errors::kCanceled
), WaitForError(func
.get()));
1256 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1257 InteractiveQueuedNoninteractiveFails
) {
1258 SignIn("primary@example.com");
1259 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1260 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1261 func
->set_extension(extension
.get());
1263 // Create a fake request to block the interactive queue.
1264 MockQueuedMintRequest queued_request
;
1265 IdentityMintRequestQueue::MintType type
=
1266 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE
;
1268 EXPECT_CALL(queued_request
, StartMintToken(type
)).Times(1);
1269 QueueRequestStart(type
, &queued_request
);
1271 // Non-interactive requests fail without hitting GAIA, because a
1272 // consent UI is known to be up.
1273 std::string error
= utils::RunFunctionAndReturnError(
1274 func
.get(), "[{}]", browser());
1275 EXPECT_EQ(std::string(errors::kNoGrant
), error
);
1276 EXPECT_FALSE(func
->login_ui_shown());
1277 EXPECT_FALSE(func
->scope_ui_shown());
1279 QueueRequestComplete(type
, &queued_request
);
1282 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1283 NonInteractiveCacheHit
) {
1284 SignIn("primary@example.com");
1285 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1286 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1287 func
->set_extension(extension
.get());
1289 // pre-populate the cache with a token
1290 IdentityTokenCacheValue
token(kAccessToken
,
1291 base::TimeDelta::FromSeconds(3600));
1292 SetCachedToken(token
);
1294 // Get a token. Should not require a GAIA request.
1295 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1296 func
.get(), "[{}]", browser()));
1297 std::string access_token
;
1298 EXPECT_TRUE(value
->GetAsString(&access_token
));
1299 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1300 EXPECT_FALSE(func
->login_ui_shown());
1301 EXPECT_FALSE(func
->scope_ui_shown());
1304 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1305 NonInteractiveIssueAdviceCacheHit
) {
1306 SignIn("primary@example.com");
1307 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1308 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1309 func
->set_extension(extension
.get());
1311 // pre-populate the cache with advice
1312 IssueAdviceInfo info
;
1313 IdentityTokenCacheValue
token(info
);
1314 SetCachedToken(token
);
1316 // Should return an error without a GAIA request.
1317 std::string error
= utils::RunFunctionAndReturnError(
1318 func
.get(), "[{}]", browser());
1319 EXPECT_EQ(std::string(errors::kNoGrant
), error
);
1320 EXPECT_FALSE(func
->login_ui_shown());
1321 EXPECT_FALSE(func
->scope_ui_shown());
1324 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1325 InteractiveCacheHit
) {
1326 SignIn("primary@example.com");
1327 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1328 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1329 func
->set_extension(extension
.get());
1331 // Create a fake request to block the queue.
1332 MockQueuedMintRequest queued_request
;
1333 IdentityMintRequestQueue::MintType type
=
1334 IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE
;
1336 EXPECT_CALL(queued_request
, StartMintToken(type
)).Times(1);
1337 QueueRequestStart(type
, &queued_request
);
1339 // The real request will start processing, but wait in the queue behind
1341 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1342 RunFunctionAsync(func
.get(), "[{\"interactive\": true}]");
1344 // Populate the cache with a token while the request is blocked.
1345 IdentityTokenCacheValue
token(kAccessToken
,
1346 base::TimeDelta::FromSeconds(3600));
1347 SetCachedToken(token
);
1349 // When we wake up the request, it returns the cached token without
1350 // displaying a UI, or hitting GAIA.
1352 QueueRequestComplete(type
, &queued_request
);
1354 scoped_ptr
<base::Value
> value(WaitForSingleResult(func
.get()));
1355 std::string access_token
;
1356 EXPECT_TRUE(value
->GetAsString(&access_token
));
1357 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1358 EXPECT_FALSE(func
->login_ui_shown());
1359 EXPECT_FALSE(func
->scope_ui_shown());
1362 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1363 LoginInvalidatesTokenCache
) {
1364 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1365 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1366 func
->set_extension(extension
.get());
1368 // pre-populate the cache with a token
1369 IdentityTokenCacheValue
token(kAccessToken
,
1370 base::TimeDelta::FromSeconds(3600));
1371 SetCachedToken(token
);
1373 // Because the user is not signed in, the token will be removed,
1374 // and we'll hit GAIA for new tokens.
1375 func
->set_login_ui_result(true);
1376 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1378 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1379 func
.get(), "[{\"interactive\": true}]", browser()));
1380 std::string access_token
;
1381 EXPECT_TRUE(value
->GetAsString(&access_token
));
1382 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1383 EXPECT_TRUE(func
->login_ui_shown());
1384 EXPECT_TRUE(func
->scope_ui_shown());
1385 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
1386 GetCachedToken(std::string()).status());
1389 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, ComponentWithChromeClientId
) {
1390 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1391 scoped_refptr
<const Extension
> extension(
1392 CreateExtension(SCOPES
| AS_COMPONENT
));
1393 func
->set_extension(extension
.get());
1394 const OAuth2Info
& oauth2_info
= OAuth2Info::GetOAuth2Info(extension
.get());
1395 EXPECT_TRUE(oauth2_info
.client_id
.empty());
1396 EXPECT_FALSE(func
->GetOAuth2ClientId().empty());
1397 EXPECT_NE("client1", func
->GetOAuth2ClientId());
1400 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, ComponentWithNormalClientId
) {
1401 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1402 scoped_refptr
<const Extension
> extension(
1403 CreateExtension(CLIENT_ID
| SCOPES
| AS_COMPONENT
));
1404 func
->set_extension(extension
.get());
1405 EXPECT_EQ("client1", func
->GetOAuth2ClientId());
1408 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, MultiDefaultUser
) {
1409 SignIn("primary@example.com");
1410 SetAccountState(CreateIds("primary@example.com", "1"), true);
1411 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1413 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1414 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1415 func
->set_extension(extension
.get());
1416 func
->set_auto_login_access_token(false);
1417 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
1419 RunFunctionAsync(func
.get(), "[{}]");
1421 IssueLoginAccessTokenForAccount("primary@example.com");
1423 scoped_ptr
<base::Value
> value(WaitForSingleResult(func
.get()));
1424 std::string access_token
;
1425 EXPECT_TRUE(value
->GetAsString(&access_token
));
1426 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1427 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
1428 GetCachedToken(std::string()).status());
1429 EXPECT_EQ("access_token-primary@example.com", func
->login_access_token());
1432 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, MultiPrimaryUser
) {
1433 SignIn("primary@example.com");
1434 IssueLoginRefreshTokenForAccount("secondary@example.com");
1435 SetAccountState(CreateIds("primary@example.com", "1"), true);
1436 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1438 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1439 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1440 func
->set_extension(extension
.get());
1441 func
->set_auto_login_access_token(false);
1442 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
1444 RunFunctionAsync(func
.get(), "[{\"account\": { \"id\": \"1\" } }]");
1446 IssueLoginAccessTokenForAccount("primary@example.com");
1448 scoped_ptr
<base::Value
> value(WaitForSingleResult(func
.get()));
1449 std::string access_token
;
1450 EXPECT_TRUE(value
->GetAsString(&access_token
));
1451 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1452 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
1453 GetCachedToken(std::string()).status());
1454 EXPECT_EQ("access_token-primary@example.com", func
->login_access_token());
1457 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, MultiSecondaryUser
) {
1458 SignIn("primary@example.com");
1459 IssueLoginRefreshTokenForAccount("secondary@example.com");
1460 SetAccountState(CreateIds("primary@example.com", "1"), true);
1461 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1463 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1464 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1465 func
->set_extension(extension
.get());
1466 func
->set_auto_login_access_token(false);
1467 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
1469 RunFunctionAsync(func
.get(), "[{\"account\": { \"id\": \"2\" } }]");
1471 IssueLoginAccessTokenForAccount("secondary@example.com");
1473 scoped_ptr
<base::Value
> value(WaitForSingleResult(func
.get()));
1474 std::string access_token
;
1475 EXPECT_TRUE(value
->GetAsString(&access_token
));
1476 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1477 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
1478 GetCachedToken("secondary@example.com").status());
1479 EXPECT_EQ("access_token-secondary@example.com", func
->login_access_token());
1482 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, MultiUnknownUser
) {
1483 SignIn("primary@example.com");
1484 IssueLoginRefreshTokenForAccount("secondary@example.com");
1485 SetAccountState(CreateIds("primary@example.com", "1"), true);
1486 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1488 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1489 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1490 func
->set_extension(extension
.get());
1491 func
->set_auto_login_access_token(false);
1493 std::string error
= utils::RunFunctionAndReturnError(
1494 func
.get(), "[{\"account\": { \"id\": \"3\" } }]", browser());
1495 EXPECT_EQ(std::string(errors::kUserNotSignedIn
), error
);
1498 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1499 MultiSecondaryNonInteractiveMintFailure
) {
1500 SignIn("primary@example.com");
1501 IssueLoginRefreshTokenForAccount("secondary@example.com");
1502 SetAccountState(CreateIds("primary@example.com", "1"), true);
1503 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1505 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1506 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
1507 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE
);
1508 std::string error
= utils::RunFunctionAndReturnError(
1509 func
.get(), "[{\"account\": { \"id\": \"2\" } }]", browser());
1510 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
1511 base::CompareCase::INSENSITIVE_ASCII
));
1512 EXPECT_FALSE(func
->login_ui_shown());
1513 EXPECT_FALSE(func
->scope_ui_shown());
1516 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1517 MultiSecondaryNonInteractiveLoginAccessTokenFailure
) {
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_login_access_token_result(false);
1526 std::string error
= utils::RunFunctionAndReturnError(
1527 func
.get(), "[{\"account\": { \"id\": \"2\" } }]", browser());
1528 EXPECT_TRUE(base::StartsWith(error
, errors::kAuthFailure
,
1529 base::CompareCase::INSENSITIVE_ASCII
));
1532 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
,
1533 MultiSecondaryInteractiveApprovalAborted
) {
1534 SignIn("primary@example.com");
1535 IssueLoginRefreshTokenForAccount("secondary@example.com");
1536 SetAccountState(CreateIds("primary@example.com", "1"), true);
1537 SetAccountState(CreateIds("secondary@example.com", "2"), true);
1539 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1540 func
->set_extension(CreateExtension(CLIENT_ID
| SCOPES
));
1541 func
->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS
);
1542 func
->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED
);
1543 std::string error
= utils::RunFunctionAndReturnError(
1545 "[{\"account\": { \"id\": \"2\" }, \"interactive\": true}]",
1547 EXPECT_EQ(std::string(errors::kUserRejected
), error
);
1548 EXPECT_FALSE(func
->login_ui_shown());
1549 EXPECT_TRUE(func
->scope_ui_shown());
1552 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, ScopesDefault
) {
1553 SignIn("primary@example.com");
1554 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1555 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1556 func
->set_extension(extension
.get());
1557 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
1558 scoped_ptr
<base::Value
> value(
1559 utils::RunFunctionAndReturnSingleResult(func
.get(), "[{}]", browser()));
1560 std::string access_token
;
1561 EXPECT_TRUE(value
->GetAsString(&access_token
));
1562 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1564 const ExtensionTokenKey
* token_key
= func
->GetExtensionTokenKeyForTest();
1565 EXPECT_EQ(2ul, token_key
->scopes
.size());
1566 EXPECT_TRUE(ContainsKey(token_key
->scopes
, "scope1"));
1567 EXPECT_TRUE(ContainsKey(token_key
->scopes
, "scope2"));
1570 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, ScopesEmpty
) {
1571 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1572 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1573 func
->set_extension(extension
.get());
1575 std::string
error(utils::RunFunctionAndReturnError(
1576 func
.get(), "[{\"scopes\": []}]", browser()));
1578 EXPECT_EQ(errors::kInvalidScopes
, error
);
1581 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, ScopesEmail
) {
1582 SignIn("primary@example.com");
1583 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1584 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1585 func
->set_extension(extension
.get());
1586 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
1587 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1588 func
.get(), "[{\"scopes\": [\"email\"]}]", browser()));
1589 std::string access_token
;
1590 EXPECT_TRUE(value
->GetAsString(&access_token
));
1591 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1593 const ExtensionTokenKey
* token_key
= func
->GetExtensionTokenKeyForTest();
1594 EXPECT_EQ(1ul, token_key
->scopes
.size());
1595 EXPECT_TRUE(ContainsKey(token_key
->scopes
, "email"));
1598 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest
, ScopesEmailFooBar
) {
1599 SignIn("primary@example.com");
1600 scoped_refptr
<FakeGetAuthTokenFunction
> func(new FakeGetAuthTokenFunction());
1601 scoped_refptr
<const Extension
> extension(CreateExtension(CLIENT_ID
| SCOPES
));
1602 func
->set_extension(extension
.get());
1603 func
->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS
);
1604 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1605 func
.get(), "[{\"scopes\": [\"email\", \"foo\", \"bar\"]}]", browser()));
1606 std::string access_token
;
1607 EXPECT_TRUE(value
->GetAsString(&access_token
));
1608 EXPECT_EQ(std::string(kAccessToken
), access_token
);
1610 const ExtensionTokenKey
* token_key
= func
->GetExtensionTokenKeyForTest();
1611 EXPECT_EQ(3ul, token_key
->scopes
.size());
1612 EXPECT_TRUE(ContainsKey(token_key
->scopes
, "email"));
1613 EXPECT_TRUE(ContainsKey(token_key
->scopes
, "foo"));
1614 EXPECT_TRUE(ContainsKey(token_key
->scopes
, "bar"));
1617 class RemoveCachedAuthTokenFunctionTest
: public ExtensionBrowserTest
{
1619 bool InvalidateDefaultToken() {
1620 scoped_refptr
<IdentityRemoveCachedAuthTokenFunction
> func(
1621 new IdentityRemoveCachedAuthTokenFunction
);
1622 func
->set_extension(test_util::CreateEmptyExtension(kExtensionId
).get());
1623 return utils::RunFunction(
1625 std::string("[{\"token\": \"") + kAccessToken
+ "\"}]",
1627 extension_function_test_utils::NONE
);
1630 IdentityAPI
* id_api() {
1631 return IdentityAPI::GetFactoryInstance()->Get(browser()->profile());
1634 void SetCachedToken(IdentityTokenCacheValue
& token_data
) {
1635 ExtensionTokenKey
key(
1636 kExtensionId
, "test@example.com", std::set
<std::string
>());
1637 id_api()->SetCachedToken(key
, token_data
);
1640 const IdentityTokenCacheValue
& GetCachedToken() {
1641 return id_api()->GetCachedToken(ExtensionTokenKey(
1642 kExtensionId
, "test@example.com", std::set
<std::string
>()));
1646 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest
, NotFound
) {
1647 EXPECT_TRUE(InvalidateDefaultToken());
1648 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND
,
1649 GetCachedToken().status());
1652 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest
, Advice
) {
1653 IssueAdviceInfo info
;
1654 IdentityTokenCacheValue
advice(info
);
1655 SetCachedToken(advice
);
1656 EXPECT_TRUE(InvalidateDefaultToken());
1657 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_ADVICE
,
1658 GetCachedToken().status());
1661 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest
, NonMatchingToken
) {
1662 IdentityTokenCacheValue
token("non_matching_token",
1663 base::TimeDelta::FromSeconds(3600));
1664 SetCachedToken(token
);
1665 EXPECT_TRUE(InvalidateDefaultToken());
1666 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
1667 GetCachedToken().status());
1668 EXPECT_EQ("non_matching_token", GetCachedToken().token());
1671 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest
, MatchingToken
) {
1672 IdentityTokenCacheValue
token(kAccessToken
,
1673 base::TimeDelta::FromSeconds(3600));
1674 SetCachedToken(token
);
1675 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN
,
1676 GetCachedToken().status());
1677 EXPECT_TRUE(InvalidateDefaultToken());
1678 EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND
,
1679 GetCachedToken().status());
1682 class LaunchWebAuthFlowFunctionTest
: public AsyncExtensionBrowserTest
{
1684 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
1685 AsyncExtensionBrowserTest::SetUpCommandLine(command_line
);
1686 // Reduce performance test variance by disabling background networking.
1687 command_line
->AppendSwitch(switches::kDisableBackgroundNetworking
);
1691 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest
, UserCloseWindow
) {
1692 net::SpawnedTestServer
https_server(
1693 net::SpawnedTestServer::TYPE_HTTPS
,
1694 net::SpawnedTestServer::kLocalhost
,
1695 base::FilePath(FILE_PATH_LITERAL(
1696 "chrome/test/data/extensions/api_test/identity")));
1697 ASSERT_TRUE(https_server
.Start());
1698 GURL
auth_url(https_server
.GetURL("files/interaction_required.html"));
1700 scoped_refptr
<IdentityLaunchWebAuthFlowFunction
> function(
1701 new IdentityLaunchWebAuthFlowFunction());
1702 scoped_refptr
<Extension
> empty_extension(test_util::CreateEmptyExtension());
1703 function
->set_extension(empty_extension
.get());
1705 WaitForGURLAndCloseWindow
popup_observer(auth_url
);
1707 std::string args
= "[{\"interactive\": true, \"url\": \"" +
1708 auth_url
.spec() + "\"}]";
1709 RunFunctionAsync(function
.get(), args
);
1711 popup_observer
.Wait();
1712 popup_observer
.CloseEmbedderWebContents();
1714 EXPECT_EQ(std::string(errors::kUserRejected
), WaitForError(function
.get()));
1717 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest
, InteractionRequired
) {
1718 net::SpawnedTestServer
https_server(
1719 net::SpawnedTestServer::TYPE_HTTPS
,
1720 net::SpawnedTestServer::kLocalhost
,
1721 base::FilePath(FILE_PATH_LITERAL(
1722 "chrome/test/data/extensions/api_test/identity")));
1723 ASSERT_TRUE(https_server
.Start());
1724 GURL
auth_url(https_server
.GetURL("files/interaction_required.html"));
1726 scoped_refptr
<IdentityLaunchWebAuthFlowFunction
> function(
1727 new IdentityLaunchWebAuthFlowFunction());
1728 scoped_refptr
<Extension
> empty_extension(test_util::CreateEmptyExtension());
1729 function
->set_extension(empty_extension
.get());
1731 std::string args
= "[{\"interactive\": false, \"url\": \"" +
1732 auth_url
.spec() + "\"}]";
1734 utils::RunFunctionAndReturnError(function
.get(), args
, browser());
1736 EXPECT_EQ(std::string(errors::kInteractionRequired
), error
);
1739 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest
, LoadFailed
) {
1740 net::SpawnedTestServer
https_server(
1741 net::SpawnedTestServer::TYPE_HTTPS
,
1742 net::SpawnedTestServer::kLocalhost
,
1743 base::FilePath(FILE_PATH_LITERAL(
1744 "chrome/test/data/extensions/api_test/identity")));
1745 ASSERT_TRUE(https_server
.Start());
1746 GURL
auth_url(https_server
.GetURL("files/five_hundred.html"));
1748 scoped_refptr
<IdentityLaunchWebAuthFlowFunction
> function(
1749 new IdentityLaunchWebAuthFlowFunction());
1750 scoped_refptr
<Extension
> empty_extension(test_util::CreateEmptyExtension());
1751 function
->set_extension(empty_extension
.get());
1753 std::string args
= "[{\"interactive\": true, \"url\": \"" +
1754 auth_url
.spec() + "\"}]";
1756 utils::RunFunctionAndReturnError(function
.get(), args
, browser());
1758 EXPECT_EQ(std::string(errors::kPageLoadFailure
), error
);
1761 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest
, NonInteractiveSuccess
) {
1762 #if defined(OS_WIN) && defined(USE_ASH)
1763 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
1764 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1765 switches::kAshBrowserTests
))
1769 scoped_refptr
<IdentityLaunchWebAuthFlowFunction
> function(
1770 new IdentityLaunchWebAuthFlowFunction());
1771 scoped_refptr
<Extension
> empty_extension(test_util::CreateEmptyExtension());
1772 function
->set_extension(empty_extension
.get());
1774 function
->InitFinalRedirectURLPrefixForTest("abcdefghij");
1775 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1777 "[{\"interactive\": false,"
1778 "\"url\": \"https://abcdefghij.chromiumapp.org/callback#test\"}]",
1782 EXPECT_TRUE(value
->GetAsString(&url
));
1783 EXPECT_EQ(std::string("https://abcdefghij.chromiumapp.org/callback#test"),
1787 IN_PROC_BROWSER_TEST_F(
1788 LaunchWebAuthFlowFunctionTest
, InteractiveFirstNavigationSuccess
) {
1789 #if defined(OS_WIN) && defined(USE_ASH)
1790 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
1791 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1792 switches::kAshBrowserTests
))
1796 scoped_refptr
<IdentityLaunchWebAuthFlowFunction
> function(
1797 new IdentityLaunchWebAuthFlowFunction());
1798 scoped_refptr
<Extension
> empty_extension(test_util::CreateEmptyExtension());
1799 function
->set_extension(empty_extension
.get());
1801 function
->InitFinalRedirectURLPrefixForTest("abcdefghij");
1802 scoped_ptr
<base::Value
> value(utils::RunFunctionAndReturnSingleResult(
1804 "[{\"interactive\": true,"
1805 "\"url\": \"https://abcdefghij.chromiumapp.org/callback#test\"}]",
1809 EXPECT_TRUE(value
->GetAsString(&url
));
1810 EXPECT_EQ(std::string("https://abcdefghij.chromiumapp.org/callback#test"),
1814 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest
,
1815 DISABLED_InteractiveSecondNavigationSuccess
) {
1816 net::SpawnedTestServer
https_server(
1817 net::SpawnedTestServer::TYPE_HTTPS
,
1818 net::SpawnedTestServer::kLocalhost
,
1819 base::FilePath(FILE_PATH_LITERAL(
1820 "chrome/test/data/extensions/api_test/identity")));
1821 ASSERT_TRUE(https_server
.Start());
1822 GURL
auth_url(https_server
.GetURL("files/redirect_to_chromiumapp.html"));
1824 scoped_refptr
<IdentityLaunchWebAuthFlowFunction
> function(
1825 new IdentityLaunchWebAuthFlowFunction());
1826 scoped_refptr
<Extension
> empty_extension(test_util::CreateEmptyExtension());
1827 function
->set_extension(empty_extension
.get());
1829 function
->InitFinalRedirectURLPrefixForTest("abcdefghij");
1830 std::string args
= "[{\"interactive\": true, \"url\": \"" +
1831 auth_url
.spec() + "\"}]";
1832 scoped_ptr
<base::Value
> value(
1833 utils::RunFunctionAndReturnSingleResult(function
.get(), args
, browser()));
1836 EXPECT_TRUE(value
->GetAsString(&url
));
1837 EXPECT_EQ(std::string("https://abcdefghij.chromiumapp.org/callback#test"),
1841 } // namespace extensions
1843 // Tests the chrome.identity API implemented by custom JS bindings .
1844 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, ChromeIdentityJsBindings
) {
1845 ASSERT_TRUE(RunExtensionTest("identity/js_bindings")) << message_
;