1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/password_manager/content/browser/credential_manager_dispatcher.h"
8 #include "base/command_line.h"
9 #include "base/prefs/pref_registry_simple.h"
10 #include "base/prefs/testing_pref_service.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "components/password_manager/content/common/credential_manager_messages.h"
16 #include "components/password_manager/core/browser/credential_manager_password_form_manager.h"
17 #include "components/password_manager/core/browser/stub_password_manager_client.h"
18 #include "components/password_manager/core/browser/stub_password_manager_driver.h"
19 #include "components/password_manager/core/browser/test_password_store.h"
20 #include "components/password_manager/core/common/credential_manager_types.h"
21 #include "components/password_manager/core/common/password_manager_pref_names.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/test/mock_render_process_host.h"
24 #include "content/public/test/test_renderer_host.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 using content::BrowserContext
;
29 using content::WebContents
;
35 // Chosen by fair dice roll. Guaranteed to be random.
36 const int kRequestId
= 4;
38 class MockPasswordManagerClient
39 : public password_manager::StubPasswordManagerClient
{
41 MOCK_CONST_METHOD0(IsSavingEnabledForCurrentPage
, bool());
42 MOCK_CONST_METHOD0(IsOffTheRecord
, bool());
43 MOCK_METHOD1(NotifyUserAutoSigninPtr
,
44 bool(const std::vector
<autofill::PasswordForm
*>& local_forms
));
45 MOCK_METHOD2(PromptUserToSavePasswordPtr
,
46 void(password_manager::PasswordFormManager
*,
47 password_manager::CredentialSourceType type
));
48 MOCK_METHOD4(PromptUserToChooseCredentialsPtr
,
49 bool(const std::vector
<autofill::PasswordForm
*>& local_forms
,
50 const std::vector
<autofill::PasswordForm
*>& federated_forms
,
53 const password_manager::CredentialInfo
&)> callback
));
55 MockPasswordManagerClient(password_manager::PasswordStore
* store
)
57 prefs_
.registry()->RegisterBooleanPref(
58 password_manager::prefs::kPasswordManagerAutoSignin
, true);
60 ~MockPasswordManagerClient() override
{}
62 bool PromptUserToSavePassword(
63 scoped_ptr
<password_manager::PasswordFormManager
> manager
,
64 password_manager::CredentialSourceType type
) override
{
65 manager_
.swap(manager
);
66 PromptUserToSavePasswordPtr(manager_
.get(), type
);
70 password_manager::PasswordStore
* GetPasswordStore() const override
{
74 PrefService
* GetPrefs() override
{ return &prefs_
; }
76 bool PromptUserToChooseCredentials(
77 ScopedVector
<autofill::PasswordForm
> local_forms
,
78 ScopedVector
<autofill::PasswordForm
> federated_forms
,
80 base::Callback
<void(const password_manager::CredentialInfo
&)> callback
) {
81 EXPECT_FALSE(local_forms
.empty() && federated_forms
.empty());
82 password_manager::CredentialInfo
info(
83 local_forms
.empty() ? *federated_forms
[0] : *local_forms
[0],
85 ? password_manager::CredentialType::CREDENTIAL_TYPE_FEDERATED
86 : password_manager::CredentialType::CREDENTIAL_TYPE_PASSWORD
);
87 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
88 base::Bind(callback
, info
));
89 PromptUserToChooseCredentialsPtr(local_forms
.get(), federated_forms
.get(),
94 void NotifyUserAutoSignin(
95 ScopedVector
<autofill::PasswordForm
> local_forms
) override
{
96 EXPECT_FALSE(local_forms
.empty());
97 NotifyUserAutoSigninPtr(local_forms
.get());
100 password_manager::PasswordFormManager
* pending_manager() const {
101 return manager_
.get();
104 void set_zero_click_enabled(bool zero_click_enabled
) {
105 prefs_
.SetBoolean(password_manager::prefs::kPasswordManagerAutoSignin
,
110 TestingPrefServiceSimple prefs_
;
111 password_manager::PasswordStore
* store_
;
112 scoped_ptr
<password_manager::PasswordFormManager
> manager_
;
114 DISALLOW_COPY_AND_ASSIGN(MockPasswordManagerClient
);
117 class TestCredentialManagerDispatcher
118 : public password_manager::CredentialManagerDispatcher
{
120 TestCredentialManagerDispatcher(
121 content::WebContents
* web_contents
,
122 password_manager::PasswordManagerClient
* client
,
123 password_manager::PasswordManagerDriver
* driver
);
126 base::WeakPtr
<password_manager::PasswordManagerDriver
> GetDriver() override
;
128 base::WeakPtr
<password_manager::PasswordManagerDriver
> driver_
;
131 TestCredentialManagerDispatcher::TestCredentialManagerDispatcher(
132 content::WebContents
* web_contents
,
133 password_manager::PasswordManagerClient
* client
,
134 password_manager::PasswordManagerDriver
* driver
)
135 : CredentialManagerDispatcher(web_contents
, client
),
136 driver_(driver
->AsWeakPtr()) {
139 base::WeakPtr
<password_manager::PasswordManagerDriver
>
140 TestCredentialManagerDispatcher::GetDriver() {
144 void RunAllPendingTasks() {
145 base::RunLoop run_loop
;
146 base::MessageLoop::current()->PostTask(
147 FROM_HERE
, base::MessageLoop::QuitWhenIdleClosure());
153 namespace password_manager
{
155 class CredentialManagerDispatcherTest
156 : public content::RenderViewHostTestHarness
{
158 CredentialManagerDispatcherTest() {}
160 void SetUp() override
{
161 content::RenderViewHostTestHarness::SetUp();
162 store_
= new TestPasswordStore
;
163 client_
.reset(new MockPasswordManagerClient(store_
.get()));
164 dispatcher_
.reset(new TestCredentialManagerDispatcher(
165 web_contents(), client_
.get(), &stub_driver_
));
166 ON_CALL(*client_
, IsSavingEnabledForCurrentPage())
167 .WillByDefault(testing::Return(true));
168 ON_CALL(*client_
, IsOffTheRecord()).WillByDefault(testing::Return(false));
170 NavigateAndCommit(GURL("https://example.com/test.html"));
172 form_
.username_value
= base::ASCIIToUTF16("Username");
173 form_
.display_name
= base::ASCIIToUTF16("Display Name");
174 form_
.password_value
= base::ASCIIToUTF16("Password");
175 form_
.origin
= web_contents()->GetLastCommittedURL().GetOrigin();
176 form_
.signon_realm
= form_
.origin
.spec();
177 form_
.scheme
= autofill::PasswordForm::SCHEME_HTML
;
178 form_
.skip_zero_click
= false;
180 origin_path_form_
.username_value
= base::ASCIIToUTF16("Username 2");
181 origin_path_form_
.display_name
= base::ASCIIToUTF16("Display Name 2");
182 origin_path_form_
.password_value
= base::ASCIIToUTF16("Password 2");
183 origin_path_form_
.origin
= GURL("https://example.com/path");
184 origin_path_form_
.signon_realm
= origin_path_form_
.origin
.spec();
185 origin_path_form_
.scheme
= autofill::PasswordForm::SCHEME_HTML
;
186 origin_path_form_
.skip_zero_click
= false;
188 cross_origin_form_
.username_value
= base::ASCIIToUTF16("Username");
189 cross_origin_form_
.display_name
= base::ASCIIToUTF16("Display Name");
190 cross_origin_form_
.password_value
= base::ASCIIToUTF16("Password");
191 cross_origin_form_
.origin
= GURL("https://example.net/");
192 cross_origin_form_
.signon_realm
= cross_origin_form_
.origin
.spec();
193 cross_origin_form_
.scheme
= autofill::PasswordForm::SCHEME_HTML
;
194 cross_origin_form_
.skip_zero_click
= false;
197 EXPECT_TRUE(store_
->IsEmpty());
200 void TearDown() override
{
202 content::RenderViewHostTestHarness::TearDown();
205 CredentialManagerDispatcher
* dispatcher() { return dispatcher_
.get(); }
208 autofill::PasswordForm form_
;
209 autofill::PasswordForm origin_path_form_
;
210 autofill::PasswordForm cross_origin_form_
;
211 scoped_refptr
<TestPasswordStore
> store_
;
212 scoped_ptr
<MockPasswordManagerClient
> client_
;
213 StubPasswordManagerDriver stub_driver_
;
214 scoped_ptr
<CredentialManagerDispatcher
> dispatcher_
;
217 TEST_F(CredentialManagerDispatcherTest
, CredentialManagerOnNotifyFailedSignIn
) {
219 info
.type
= CredentialType::CREDENTIAL_TYPE_PASSWORD
;
220 dispatcher()->OnNotifyFailedSignIn(kRequestId
, info
);
222 const uint32 kMsgID
= CredentialManagerMsg_AcknowledgeFailedSignIn::ID
;
223 const IPC::Message
* message
=
224 process()->sink().GetFirstMessageMatching(kMsgID
);
225 EXPECT_TRUE(message
);
226 process()->sink().ClearMessages();
229 TEST_F(CredentialManagerDispatcherTest
, CredentialManagerOnNotifySignedIn
) {
231 form_
, password_manager::CredentialType::CREDENTIAL_TYPE_PASSWORD
);
234 PromptUserToSavePasswordPtr(
235 _
, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API
))
236 .Times(testing::Exactly(1));
238 dispatcher()->OnNotifySignedIn(kRequestId
, info
);
240 const uint32 kMsgID
= CredentialManagerMsg_AcknowledgeSignedIn::ID
;
241 const IPC::Message
* message
=
242 process()->sink().GetFirstMessageMatching(kMsgID
);
243 EXPECT_TRUE(message
);
244 process()->sink().ClearMessages();
246 // Allow the PasswordFormManager to talk to the password store, determine
247 // that the form is new, and set it as pending.
248 RunAllPendingTasks();
250 EXPECT_TRUE(client_
->pending_manager()->HasCompletedMatching());
252 autofill::PasswordForm new_form
=
253 client_
->pending_manager()->pending_credentials();
254 EXPECT_EQ(form_
.username_value
, new_form
.username_value
);
255 EXPECT_EQ(form_
.display_name
, new_form
.display_name
);
256 EXPECT_EQ(form_
.password_value
, new_form
.password_value
);
257 EXPECT_EQ(form_
.origin
, new_form
.origin
);
258 EXPECT_EQ(form_
.signon_realm
, new_form
.signon_realm
);
259 EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML
, new_form
.scheme
);
262 TEST_F(CredentialManagerDispatcherTest
,
263 CredentialManagerSignInWithSavingDisabledForCurrentPage
) {
264 CredentialInfo
info(form_
, CredentialType::CREDENTIAL_TYPE_PASSWORD
);
265 EXPECT_CALL(*client_
, IsSavingEnabledForCurrentPage())
266 .WillRepeatedly(testing::Return(false));
269 PromptUserToSavePasswordPtr(
270 _
, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API
))
271 .Times(testing::Exactly(0));
273 dispatcher()->OnNotifySignedIn(kRequestId
, info
);
275 const uint32 kMsgID
= CredentialManagerMsg_AcknowledgeSignedIn::ID
;
276 const IPC::Message
* message
=
277 process()->sink().GetFirstMessageMatching(kMsgID
);
278 EXPECT_TRUE(message
);
279 process()->sink().ClearMessages();
281 RunAllPendingTasks();
283 EXPECT_FALSE(client_
->pending_manager());
286 TEST_F(CredentialManagerDispatcherTest
,
287 CredentialManagerOnRequireUserMediation
) {
288 store_
->AddLogin(form_
);
289 store_
->AddLogin(cross_origin_form_
);
290 RunAllPendingTasks();
292 TestPasswordStore::PasswordMap passwords
= store_
->stored_passwords();
293 EXPECT_EQ(2U, passwords
.size());
294 EXPECT_EQ(1U, passwords
[form_
.signon_realm
].size());
295 EXPECT_EQ(1U, passwords
[cross_origin_form_
.signon_realm
].size());
296 EXPECT_FALSE(passwords
[form_
.signon_realm
][0].skip_zero_click
);
297 EXPECT_FALSE(passwords
[cross_origin_form_
.signon_realm
][0].skip_zero_click
);
299 dispatcher()->OnRequireUserMediation(kRequestId
);
300 RunAllPendingTasks();
302 const uint32 kMsgID
=
303 CredentialManagerMsg_AcknowledgeRequireUserMediation::ID
;
304 const IPC::Message
* message
=
305 process()->sink().GetFirstMessageMatching(kMsgID
);
306 EXPECT_TRUE(message
);
307 process()->sink().ClearMessages();
309 passwords
= store_
->stored_passwords();
310 EXPECT_EQ(2U, passwords
.size());
311 EXPECT_EQ(1U, passwords
[form_
.signon_realm
].size());
312 EXPECT_EQ(1U, passwords
[cross_origin_form_
.signon_realm
].size());
313 EXPECT_TRUE(passwords
[form_
.signon_realm
][0].skip_zero_click
);
314 EXPECT_FALSE(passwords
[cross_origin_form_
.signon_realm
][0].skip_zero_click
);
317 TEST_F(CredentialManagerDispatcherTest
,
318 CredentialManagerOnRequestCredentialWithEmptyPasswordStore
) {
319 std::vector
<GURL
> federations
;
322 PromptUserToSavePasswordPtr(
323 _
, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API
))
324 .Times(testing::Exactly(0));
325 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
326 .Times(testing::Exactly(0));
327 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
329 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
331 RunAllPendingTasks();
333 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
334 const IPC::Message
* message
=
335 process()->sink().GetFirstMessageMatching(kMsgID
);
336 EXPECT_TRUE(message
);
337 CredentialManagerMsg_SendCredential::Param param
;
338 CredentialManagerMsg_SendCredential::Read(message
, ¶m
);
339 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
, base::get
<1>(param
).type
);
340 process()->sink().ClearMessages();
343 TEST_F(CredentialManagerDispatcherTest
,
344 CredentialManagerOnRequestCredentialWithCrossOriginPasswordStore
) {
345 store_
->AddLogin(cross_origin_form_
);
347 std::vector
<GURL
> federations
;
350 PromptUserToSavePasswordPtr(
351 _
, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API
))
352 .Times(testing::Exactly(0));
353 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
354 .Times(testing::Exactly(0));
355 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
357 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
359 RunAllPendingTasks();
361 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
362 const IPC::Message
* message
=
363 process()->sink().GetFirstMessageMatching(kMsgID
);
364 EXPECT_TRUE(message
);
365 CredentialManagerMsg_SendCredential::Param param
;
366 CredentialManagerMsg_SendCredential::Read(message
, ¶m
);
367 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
, base::get
<1>(param
).type
);
368 process()->sink().ClearMessages();
371 TEST_F(CredentialManagerDispatcherTest
,
372 CredentialManagerOnRequestCredentialWithFullPasswordStore
) {
373 client_
->set_zero_click_enabled(false);
374 store_
->AddLogin(form_
);
376 std::vector
<GURL
> federations
;
377 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
378 .Times(testing::Exactly(1));
379 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
381 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
383 RunAllPendingTasks();
385 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
386 const IPC::Message
* message
=
387 process()->sink().GetFirstMessageMatching(kMsgID
);
388 EXPECT_TRUE(message
);
392 CredentialManagerDispatcherTest
,
393 CredentialManagerOnRequestCredentialWithZeroClickOnlyEmptyPasswordStore
) {
394 std::vector
<GURL
> federations
;
395 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
396 .Times(testing::Exactly(0));
397 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
399 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
401 RunAllPendingTasks();
403 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
404 const IPC::Message
* message
=
405 process()->sink().GetFirstMessageMatching(kMsgID
);
406 EXPECT_TRUE(message
);
407 CredentialManagerMsg_SendCredential::Param send_param
;
408 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
409 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
,
410 base::get
<1>(send_param
).type
);
413 TEST_F(CredentialManagerDispatcherTest
,
414 CredentialManagerOnRequestCredentialWithZeroClickOnlyFullPasswordStore
) {
415 store_
->AddLogin(form_
);
417 std::vector
<GURL
> federations
;
418 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
419 .Times(testing::Exactly(0));
420 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(1));
422 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
424 RunAllPendingTasks();
426 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
427 const IPC::Message
* message
=
428 process()->sink().GetFirstMessageMatching(kMsgID
);
429 EXPECT_TRUE(message
);
430 CredentialManagerMsg_SendCredential::Param send_param
;
431 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
432 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_PASSWORD
,
433 base::get
<1>(send_param
).type
);
436 TEST_F(CredentialManagerDispatcherTest
,
437 CredentialManagerOnRequestCredentialWithZeroClickOnlyTwoPasswordStore
) {
438 store_
->AddLogin(form_
);
439 store_
->AddLogin(origin_path_form_
);
441 std::vector
<GURL
> federations
;
442 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
443 .Times(testing::Exactly(0));
444 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
446 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
448 RunAllPendingTasks();
450 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
451 const IPC::Message
* message
=
452 process()->sink().GetFirstMessageMatching(kMsgID
);
453 EXPECT_TRUE(message
);
454 CredentialManagerMsg_SendCredential::Param send_param
;
455 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
457 // With two items in the password store, we shouldn't get credentials back.
458 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
,
459 base::get
<1>(send_param
).type
);
462 TEST_F(CredentialManagerDispatcherTest
,
463 OnRequestCredentialWithZeroClickOnlyOnePasswordStore
) {
464 form_
.skip_zero_click
= true;
465 store_
->AddLogin(form_
);
466 store_
->AddLogin(origin_path_form_
);
468 std::vector
<GURL
> federations
;
469 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
470 .Times(testing::Exactly(0));
471 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(1));
473 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
475 RunAllPendingTasks();
477 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
478 const IPC::Message
* message
=
479 process()->sink().GetFirstMessageMatching(kMsgID
);
480 EXPECT_TRUE(message
);
481 CredentialManagerMsg_SendCredential::Param send_param
;
482 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
484 // We should get |origin_path_form_| back, as |form_| is marked as skipping
486 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_PASSWORD
,
487 base::get
<1>(send_param
).type
);
488 EXPECT_EQ(origin_path_form_
.username_value
, base::get
<1>(send_param
).id
);
489 EXPECT_EQ(origin_path_form_
.display_name
, base::get
<1>(send_param
).name
);
490 EXPECT_EQ(origin_path_form_
.password_value
,
491 base::get
<1>(send_param
).password
);
494 TEST_F(CredentialManagerDispatcherTest
,
495 OnRequestCredentialWithZeroClickOnlyCrossOriginPasswordStore
) {
496 store_
->AddLogin(cross_origin_form_
);
498 form_
.skip_zero_click
= true;
499 store_
->AddLogin(form_
);
501 std::vector
<GURL
> federations
;
502 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
503 .Times(testing::Exactly(0));
504 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
506 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
508 RunAllPendingTasks();
510 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
511 const IPC::Message
* message
=
512 process()->sink().GetFirstMessageMatching(kMsgID
);
513 EXPECT_TRUE(message
);
514 CredentialManagerMsg_SendCredential::Param send_param
;
515 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
517 // We only have cross-origin zero-click credentials; they should not be
519 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
,
520 base::get
<1>(send_param
).type
);
523 TEST_F(CredentialManagerDispatcherTest
,
524 CredentialManagerOnRequestCredentialWhileRequestPending
) {
525 client_
->set_zero_click_enabled(false);
526 store_
->AddLogin(form_
);
528 std::vector
<GURL
> federations
;
529 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
530 .Times(testing::Exactly(0));
531 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
533 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
534 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
536 // Check that the second request triggered a rejection.
537 uint32 kMsgID
= CredentialManagerMsg_RejectCredentialRequest::ID
;
538 const IPC::Message
* message
=
539 process()->sink().GetFirstMessageMatching(kMsgID
);
540 EXPECT_TRUE(message
);
542 CredentialManagerMsg_RejectCredentialRequest::Param reject_param
;
543 CredentialManagerMsg_RejectCredentialRequest::Read(message
, &reject_param
);
544 EXPECT_EQ(blink::WebCredentialManagerError::ErrorTypePendingRequest
,
545 base::get
<1>(reject_param
));
546 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
547 .Times(testing::Exactly(1));
548 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
550 process()->sink().ClearMessages();
552 // Execute the PasswordStore asynchronousness.
553 RunAllPendingTasks();
555 // Check that the first request resolves.
556 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
557 message
= process()->sink().GetFirstMessageMatching(kMsgID
);
558 EXPECT_TRUE(message
);
559 CredentialManagerMsg_SendCredential::Param send_param
;
560 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
561 EXPECT_NE(CredentialType::CREDENTIAL_TYPE_EMPTY
,
562 base::get
<1>(send_param
).type
);
563 process()->sink().ClearMessages();
566 TEST_F(CredentialManagerDispatcherTest
, ResetSkipZeroClickAfterPrompt
) {
567 // Turn on the global zero-click flag, and add two credentials in separate
568 // origins, both set to skip zero-click.
569 client_
->set_zero_click_enabled(true);
570 form_
.skip_zero_click
= true;
571 store_
->AddLogin(form_
);
572 cross_origin_form_
.skip_zero_click
= true;
573 store_
->AddLogin(cross_origin_form_
);
575 // Execute the PasswordStore asynchronousness to ensure everything is
576 // written before proceeding.
577 RunAllPendingTasks();
580 TestPasswordStore::PasswordMap passwords
= store_
->stored_passwords();
581 EXPECT_EQ(2U, passwords
.size());
582 EXPECT_EQ(1U, passwords
[form_
.signon_realm
].size());
583 EXPECT_EQ(1U, passwords
[cross_origin_form_
.signon_realm
].size());
584 EXPECT_TRUE(passwords
[form_
.signon_realm
][0].skip_zero_click
);
585 EXPECT_TRUE(passwords
[cross_origin_form_
.signon_realm
][0].skip_zero_click
);
587 // Trigger a request which should return the credential found in |form_|, and
588 // wait for it to process.
589 std::vector
<GURL
> federations
;
590 // Check that the form in the database has been updated. `OnRequestCredential`
591 // generates a call to prompt the user to choose a credential.
592 // MockPasswordManagerClient mocks a user choice, and when users choose a
593 // credential (and have the global zero-click flag enabled), we make sure that
594 // they'll be logged in again next time.
595 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
596 .Times(testing::Exactly(1));
597 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
599 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
600 RunAllPendingTasks();
602 passwords
= store_
->stored_passwords();
603 EXPECT_EQ(2U, passwords
.size());
604 EXPECT_EQ(1U, passwords
[form_
.signon_realm
].size());
605 EXPECT_EQ(1U, passwords
[cross_origin_form_
.signon_realm
].size());
606 EXPECT_FALSE(passwords
[form_
.signon_realm
][0].skip_zero_click
);
607 EXPECT_TRUE(passwords
[cross_origin_form_
.signon_realm
][0].skip_zero_click
);
610 TEST_F(CredentialManagerDispatcherTest
, IncognitoZeroClickRequestCredential
) {
611 EXPECT_CALL(*client_
, IsOffTheRecord()).WillRepeatedly(testing::Return(true));
612 store_
->AddLogin(form_
);
614 std::vector
<GURL
> federations
;
615 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
616 .Times(testing::Exactly(0));
617 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
619 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
621 RunAllPendingTasks();
623 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
624 const IPC::Message
* message
=
625 process()->sink().GetFirstMessageMatching(kMsgID
);
626 ASSERT_TRUE(message
);
627 CredentialManagerMsg_SendCredential::Param param
;
628 CredentialManagerMsg_SendCredential::Read(message
, ¶m
);
629 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
, base::get
<1>(param
).type
);
632 } // namespace password_manager