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 "components/password_manager/content/common/credential_manager_messages.h"
15 #include "components/password_manager/core/browser/credential_manager_password_form_manager.h"
16 #include "components/password_manager/core/browser/stub_password_manager_client.h"
17 #include "components/password_manager/core/browser/stub_password_manager_driver.h"
18 #include "components/password_manager/core/browser/test_password_store.h"
19 #include "components/password_manager/core/common/credential_manager_types.h"
20 #include "components/password_manager/core/common/password_manager_pref_names.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/test/mock_render_process_host.h"
23 #include "content/public/test/test_renderer_host.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 using content::BrowserContext
;
28 using content::WebContents
;
34 // Chosen by fair dice roll. Guaranteed to be random.
35 const int kRequestId
= 4;
37 class MockPasswordManagerClient
38 : public password_manager::StubPasswordManagerClient
{
40 MOCK_CONST_METHOD0(IsSavingEnabledForCurrentPage
, bool());
41 MOCK_CONST_METHOD0(IsOffTheRecord
, bool());
42 MOCK_METHOD1(NotifyUserAutoSigninPtr
,
43 bool(const std::vector
<autofill::PasswordForm
*>& local_forms
));
44 MOCK_METHOD2(PromptUserToSavePasswordPtr
,
45 void(password_manager::PasswordFormManager
*,
46 password_manager::CredentialSourceType type
));
47 MOCK_METHOD4(PromptUserToChooseCredentialsPtr
,
48 bool(const std::vector
<autofill::PasswordForm
*>& local_forms
,
49 const std::vector
<autofill::PasswordForm
*>& federated_forms
,
52 const password_manager::CredentialInfo
&)> callback
));
54 MockPasswordManagerClient(password_manager::PasswordStore
* store
)
56 prefs_
.registry()->RegisterBooleanPref(
57 password_manager::prefs::kPasswordManagerAutoSignin
, true);
59 ~MockPasswordManagerClient() override
{}
61 bool PromptUserToSavePassword(
62 scoped_ptr
<password_manager::PasswordFormManager
> manager
,
63 password_manager::CredentialSourceType type
) override
{
64 manager_
.swap(manager
);
65 PromptUserToSavePasswordPtr(manager_
.get(), type
);
69 password_manager::PasswordStore
* GetPasswordStore() const override
{
73 PrefService
* GetPrefs() override
{ return &prefs_
; }
75 bool PromptUserToChooseCredentials(
76 ScopedVector
<autofill::PasswordForm
> local_forms
,
77 ScopedVector
<autofill::PasswordForm
> federated_forms
,
79 base::Callback
<void(const password_manager::CredentialInfo
&)> callback
) {
80 EXPECT_FALSE(local_forms
.empty() && federated_forms
.empty());
81 password_manager::CredentialInfo
info(
82 local_forms
.empty() ? *federated_forms
[0] : *local_forms
[0],
84 ? password_manager::CredentialType::CREDENTIAL_TYPE_FEDERATED
85 : password_manager::CredentialType::CREDENTIAL_TYPE_LOCAL
);
86 base::MessageLoop::current()->PostTask(FROM_HERE
,
87 base::Bind(callback
, info
));
88 PromptUserToChooseCredentialsPtr(local_forms
.get(), federated_forms
.get(),
93 void NotifyUserAutoSignin(
94 ScopedVector
<autofill::PasswordForm
> local_forms
) override
{
95 EXPECT_FALSE(local_forms
.empty());
96 NotifyUserAutoSigninPtr(local_forms
.get());
99 password_manager::PasswordFormManager
* pending_manager() const {
100 return manager_
.get();
103 void set_zero_click_enabled(bool zero_click_enabled
) {
104 prefs_
.SetBoolean(password_manager::prefs::kPasswordManagerAutoSignin
,
109 TestingPrefServiceSimple prefs_
;
110 password_manager::PasswordStore
* store_
;
111 scoped_ptr
<password_manager::PasswordFormManager
> manager_
;
113 DISALLOW_COPY_AND_ASSIGN(MockPasswordManagerClient
);
116 class TestCredentialManagerDispatcher
117 : public password_manager::CredentialManagerDispatcher
{
119 TestCredentialManagerDispatcher(
120 content::WebContents
* web_contents
,
121 password_manager::PasswordManagerClient
* client
,
122 password_manager::PasswordManagerDriver
* driver
);
125 base::WeakPtr
<password_manager::PasswordManagerDriver
> GetDriver() override
;
127 base::WeakPtr
<password_manager::PasswordManagerDriver
> driver_
;
130 TestCredentialManagerDispatcher::TestCredentialManagerDispatcher(
131 content::WebContents
* web_contents
,
132 password_manager::PasswordManagerClient
* client
,
133 password_manager::PasswordManagerDriver
* driver
)
134 : CredentialManagerDispatcher(web_contents
, client
),
135 driver_(driver
->AsWeakPtr()) {
138 base::WeakPtr
<password_manager::PasswordManagerDriver
>
139 TestCredentialManagerDispatcher::GetDriver() {
143 void RunAllPendingTasks() {
144 base::RunLoop run_loop
;
145 base::MessageLoop::current()->PostTask(
146 FROM_HERE
, base::MessageLoop::QuitWhenIdleClosure());
152 namespace password_manager
{
154 class CredentialManagerDispatcherTest
155 : public content::RenderViewHostTestHarness
{
157 CredentialManagerDispatcherTest() {}
159 void SetUp() override
{
160 content::RenderViewHostTestHarness::SetUp();
161 store_
= new TestPasswordStore
;
162 client_
.reset(new MockPasswordManagerClient(store_
.get()));
163 dispatcher_
.reset(new TestCredentialManagerDispatcher(
164 web_contents(), client_
.get(), &stub_driver_
));
165 ON_CALL(*client_
, IsSavingEnabledForCurrentPage())
166 .WillByDefault(testing::Return(true));
167 ON_CALL(*client_
, IsOffTheRecord()).WillByDefault(testing::Return(false));
169 NavigateAndCommit(GURL("https://example.com/test.html"));
171 form_
.username_value
= base::ASCIIToUTF16("Username");
172 form_
.display_name
= base::ASCIIToUTF16("Display Name");
173 form_
.password_value
= base::ASCIIToUTF16("Password");
174 form_
.origin
= web_contents()->GetLastCommittedURL().GetOrigin();
175 form_
.signon_realm
= form_
.origin
.spec();
176 form_
.scheme
= autofill::PasswordForm::SCHEME_HTML
;
177 form_
.skip_zero_click
= false;
179 origin_path_form_
.username_value
= base::ASCIIToUTF16("Username 2");
180 origin_path_form_
.display_name
= base::ASCIIToUTF16("Display Name 2");
181 origin_path_form_
.password_value
= base::ASCIIToUTF16("Password 2");
182 origin_path_form_
.origin
= GURL("https://example.com/path");
183 origin_path_form_
.signon_realm
= origin_path_form_
.origin
.spec();
184 origin_path_form_
.scheme
= autofill::PasswordForm::SCHEME_HTML
;
185 origin_path_form_
.skip_zero_click
= false;
187 cross_origin_form_
.username_value
= base::ASCIIToUTF16("Username");
188 cross_origin_form_
.display_name
= base::ASCIIToUTF16("Display Name");
189 cross_origin_form_
.password_value
= base::ASCIIToUTF16("Password");
190 cross_origin_form_
.origin
= GURL("https://example.net/");
191 cross_origin_form_
.signon_realm
= cross_origin_form_
.origin
.spec();
192 cross_origin_form_
.scheme
= autofill::PasswordForm::SCHEME_HTML
;
193 cross_origin_form_
.skip_zero_click
= false;
196 EXPECT_TRUE(store_
->IsEmpty());
199 void TearDown() override
{
201 content::RenderViewHostTestHarness::TearDown();
204 CredentialManagerDispatcher
* dispatcher() { return dispatcher_
.get(); }
207 autofill::PasswordForm form_
;
208 autofill::PasswordForm origin_path_form_
;
209 autofill::PasswordForm cross_origin_form_
;
210 scoped_refptr
<TestPasswordStore
> store_
;
211 scoped_ptr
<MockPasswordManagerClient
> client_
;
212 StubPasswordManagerDriver stub_driver_
;
213 scoped_ptr
<CredentialManagerDispatcher
> dispatcher_
;
216 TEST_F(CredentialManagerDispatcherTest
, CredentialManagerOnNotifyFailedSignIn
) {
218 info
.type
= CredentialType::CREDENTIAL_TYPE_LOCAL
;
219 dispatcher()->OnNotifyFailedSignIn(kRequestId
, info
);
221 const uint32 kMsgID
= CredentialManagerMsg_AcknowledgeFailedSignIn::ID
;
222 const IPC::Message
* message
=
223 process()->sink().GetFirstMessageMatching(kMsgID
);
224 EXPECT_TRUE(message
);
225 process()->sink().ClearMessages();
228 TEST_F(CredentialManagerDispatcherTest
, CredentialManagerOnNotifySignedIn
) {
229 CredentialInfo
info(form_
,
230 password_manager::CredentialType::CREDENTIAL_TYPE_LOCAL
);
233 PromptUserToSavePasswordPtr(
234 _
, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API
))
235 .Times(testing::Exactly(1));
237 dispatcher()->OnNotifySignedIn(kRequestId
, info
);
239 const uint32 kMsgID
= CredentialManagerMsg_AcknowledgeSignedIn::ID
;
240 const IPC::Message
* message
=
241 process()->sink().GetFirstMessageMatching(kMsgID
);
242 EXPECT_TRUE(message
);
243 process()->sink().ClearMessages();
245 // Allow the PasswordFormManager to talk to the password store, determine
246 // that the form is new, and set it as pending.
247 RunAllPendingTasks();
249 EXPECT_TRUE(client_
->pending_manager()->HasCompletedMatching());
251 autofill::PasswordForm new_form
=
252 client_
->pending_manager()->pending_credentials();
253 EXPECT_EQ(form_
.username_value
, new_form
.username_value
);
254 EXPECT_EQ(form_
.display_name
, new_form
.display_name
);
255 EXPECT_EQ(form_
.password_value
, new_form
.password_value
);
256 EXPECT_EQ(form_
.origin
, new_form
.origin
);
257 EXPECT_EQ(form_
.signon_realm
, new_form
.signon_realm
);
258 EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML
, new_form
.scheme
);
261 TEST_F(CredentialManagerDispatcherTest
,
262 CredentialManagerSignInWithSavingDisabledForCurrentPage
) {
263 CredentialInfo
info(form_
, CredentialType::CREDENTIAL_TYPE_LOCAL
);
264 EXPECT_CALL(*client_
, IsSavingEnabledForCurrentPage())
265 .WillRepeatedly(testing::Return(false));
268 PromptUserToSavePasswordPtr(
269 _
, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API
))
270 .Times(testing::Exactly(0));
272 dispatcher()->OnNotifySignedIn(kRequestId
, info
);
274 const uint32 kMsgID
= CredentialManagerMsg_AcknowledgeSignedIn::ID
;
275 const IPC::Message
* message
=
276 process()->sink().GetFirstMessageMatching(kMsgID
);
277 EXPECT_TRUE(message
);
278 process()->sink().ClearMessages();
280 RunAllPendingTasks();
282 EXPECT_FALSE(client_
->pending_manager());
285 TEST_F(CredentialManagerDispatcherTest
, CredentialManagerOnNotifySignedOut
) {
286 store_
->AddLogin(form_
);
287 store_
->AddLogin(cross_origin_form_
);
288 RunAllPendingTasks();
290 TestPasswordStore::PasswordMap passwords
= store_
->stored_passwords();
291 EXPECT_EQ(2U, passwords
.size());
292 EXPECT_EQ(1U, passwords
[form_
.signon_realm
].size());
293 EXPECT_EQ(1U, passwords
[cross_origin_form_
.signon_realm
].size());
294 EXPECT_FALSE(passwords
[form_
.signon_realm
][0].skip_zero_click
);
295 EXPECT_FALSE(passwords
[cross_origin_form_
.signon_realm
][0].skip_zero_click
);
297 dispatcher()->OnNotifySignedOut(kRequestId
);
298 RunAllPendingTasks();
300 const uint32 kMsgID
= CredentialManagerMsg_AcknowledgeSignedOut::ID
;
301 const IPC::Message
* message
=
302 process()->sink().GetFirstMessageMatching(kMsgID
);
303 EXPECT_TRUE(message
);
304 process()->sink().ClearMessages();
306 passwords
= store_
->stored_passwords();
307 EXPECT_EQ(2U, passwords
.size());
308 EXPECT_EQ(1U, passwords
[form_
.signon_realm
].size());
309 EXPECT_EQ(1U, passwords
[cross_origin_form_
.signon_realm
].size());
310 EXPECT_TRUE(passwords
[form_
.signon_realm
][0].skip_zero_click
);
311 EXPECT_FALSE(passwords
[cross_origin_form_
.signon_realm
][0].skip_zero_click
);
314 TEST_F(CredentialManagerDispatcherTest
,
315 CredentialManagerOnRequestCredentialWithEmptyPasswordStore
) {
316 std::vector
<GURL
> federations
;
319 PromptUserToSavePasswordPtr(
320 _
, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API
))
321 .Times(testing::Exactly(0));
322 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
323 .Times(testing::Exactly(0));
324 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
326 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
328 RunAllPendingTasks();
330 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
331 const IPC::Message
* message
=
332 process()->sink().GetFirstMessageMatching(kMsgID
);
333 EXPECT_TRUE(message
);
334 CredentialManagerMsg_SendCredential::Param param
;
335 CredentialManagerMsg_SendCredential::Read(message
, ¶m
);
336 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
, base::get
<1>(param
).type
);
337 process()->sink().ClearMessages();
340 TEST_F(CredentialManagerDispatcherTest
,
341 CredentialManagerOnRequestCredentialWithCrossOriginPasswordStore
) {
342 store_
->AddLogin(cross_origin_form_
);
344 std::vector
<GURL
> federations
;
347 PromptUserToSavePasswordPtr(
348 _
, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API
))
349 .Times(testing::Exactly(0));
350 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
351 .Times(testing::Exactly(0));
352 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
354 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
356 RunAllPendingTasks();
358 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
359 const IPC::Message
* message
=
360 process()->sink().GetFirstMessageMatching(kMsgID
);
361 EXPECT_TRUE(message
);
362 CredentialManagerMsg_SendCredential::Param param
;
363 CredentialManagerMsg_SendCredential::Read(message
, ¶m
);
364 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
, base::get
<1>(param
).type
);
365 process()->sink().ClearMessages();
368 TEST_F(CredentialManagerDispatcherTest
,
369 CredentialManagerOnRequestCredentialWithFullPasswordStore
) {
370 client_
->set_zero_click_enabled(false);
371 store_
->AddLogin(form_
);
373 std::vector
<GURL
> federations
;
374 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
375 .Times(testing::Exactly(1));
376 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
378 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
380 RunAllPendingTasks();
382 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
383 const IPC::Message
* message
=
384 process()->sink().GetFirstMessageMatching(kMsgID
);
385 EXPECT_TRUE(message
);
389 CredentialManagerDispatcherTest
,
390 CredentialManagerOnRequestCredentialWithZeroClickOnlyEmptyPasswordStore
) {
391 std::vector
<GURL
> federations
;
392 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
393 .Times(testing::Exactly(0));
394 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
396 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
398 RunAllPendingTasks();
400 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
401 const IPC::Message
* message
=
402 process()->sink().GetFirstMessageMatching(kMsgID
);
403 EXPECT_TRUE(message
);
404 CredentialManagerMsg_SendCredential::Param send_param
;
405 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
406 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
,
407 base::get
<1>(send_param
).type
);
410 TEST_F(CredentialManagerDispatcherTest
,
411 CredentialManagerOnRequestCredentialWithZeroClickOnlyFullPasswordStore
) {
412 store_
->AddLogin(form_
);
414 std::vector
<GURL
> federations
;
415 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
416 .Times(testing::Exactly(0));
417 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(1));
419 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
421 RunAllPendingTasks();
423 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
424 const IPC::Message
* message
=
425 process()->sink().GetFirstMessageMatching(kMsgID
);
426 EXPECT_TRUE(message
);
427 CredentialManagerMsg_SendCredential::Param send_param
;
428 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
429 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_LOCAL
,
430 base::get
<1>(send_param
).type
);
433 TEST_F(CredentialManagerDispatcherTest
,
434 CredentialManagerOnRequestCredentialWithZeroClickOnlyTwoPasswordStore
) {
435 store_
->AddLogin(form_
);
436 store_
->AddLogin(origin_path_form_
);
438 std::vector
<GURL
> federations
;
439 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
440 .Times(testing::Exactly(0));
441 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
443 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
445 RunAllPendingTasks();
447 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
448 const IPC::Message
* message
=
449 process()->sink().GetFirstMessageMatching(kMsgID
);
450 EXPECT_TRUE(message
);
451 CredentialManagerMsg_SendCredential::Param send_param
;
452 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
454 // With two items in the password store, we shouldn't get credentials back.
455 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
,
456 base::get
<1>(send_param
).type
);
459 TEST_F(CredentialManagerDispatcherTest
,
460 OnRequestCredentialWithZeroClickOnlyOnePasswordStore
) {
461 form_
.skip_zero_click
= true;
462 store_
->AddLogin(form_
);
463 store_
->AddLogin(origin_path_form_
);
465 std::vector
<GURL
> federations
;
466 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
467 .Times(testing::Exactly(0));
468 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(1));
470 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
472 RunAllPendingTasks();
474 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
475 const IPC::Message
* message
=
476 process()->sink().GetFirstMessageMatching(kMsgID
);
477 EXPECT_TRUE(message
);
478 CredentialManagerMsg_SendCredential::Param send_param
;
479 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
481 // We should get |origin_path_form_| back, as |form_| is marked as skipping
483 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_LOCAL
,
484 base::get
<1>(send_param
).type
);
485 EXPECT_EQ(origin_path_form_
.username_value
, base::get
<1>(send_param
).id
);
486 EXPECT_EQ(origin_path_form_
.display_name
, base::get
<1>(send_param
).name
);
487 EXPECT_EQ(origin_path_form_
.password_value
,
488 base::get
<1>(send_param
).password
);
491 TEST_F(CredentialManagerDispatcherTest
,
492 OnRequestCredentialWithZeroClickOnlyCrossOriginPasswordStore
) {
493 store_
->AddLogin(cross_origin_form_
);
495 form_
.skip_zero_click
= true;
496 store_
->AddLogin(form_
);
498 std::vector
<GURL
> federations
;
499 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
500 .Times(testing::Exactly(0));
501 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
503 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
505 RunAllPendingTasks();
507 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
508 const IPC::Message
* message
=
509 process()->sink().GetFirstMessageMatching(kMsgID
);
510 EXPECT_TRUE(message
);
511 CredentialManagerMsg_SendCredential::Param send_param
;
512 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
514 // We only have cross-origin zero-click credentials; they should not be
516 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
,
517 base::get
<1>(send_param
).type
);
520 TEST_F(CredentialManagerDispatcherTest
,
521 CredentialManagerOnRequestCredentialWhileRequestPending
) {
522 client_
->set_zero_click_enabled(false);
523 store_
->AddLogin(form_
);
525 std::vector
<GURL
> federations
;
526 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
527 .Times(testing::Exactly(0));
528 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
530 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
531 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
533 // Check that the second request triggered a rejection.
534 uint32 kMsgID
= CredentialManagerMsg_RejectCredentialRequest::ID
;
535 const IPC::Message
* message
=
536 process()->sink().GetFirstMessageMatching(kMsgID
);
537 EXPECT_TRUE(message
);
539 CredentialManagerMsg_RejectCredentialRequest::Param reject_param
;
540 CredentialManagerMsg_RejectCredentialRequest::Read(message
, &reject_param
);
541 EXPECT_EQ(blink::WebCredentialManagerError::ErrorTypePendingRequest
,
542 base::get
<1>(reject_param
));
543 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
544 .Times(testing::Exactly(1));
545 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
547 process()->sink().ClearMessages();
549 // Execute the PasswordStore asynchronousness.
550 RunAllPendingTasks();
552 // Check that the first request resolves.
553 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
554 message
= process()->sink().GetFirstMessageMatching(kMsgID
);
555 EXPECT_TRUE(message
);
556 CredentialManagerMsg_SendCredential::Param send_param
;
557 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
558 EXPECT_NE(CredentialType::CREDENTIAL_TYPE_EMPTY
,
559 base::get
<1>(send_param
).type
);
560 process()->sink().ClearMessages();
563 TEST_F(CredentialManagerDispatcherTest
, ResetSkipZeroClickAfterPrompt
) {
564 // Turn on the global zero-click flag, and add two credentials in separate
565 // origins, both set to skip zero-click.
566 client_
->set_zero_click_enabled(true);
567 form_
.skip_zero_click
= true;
568 store_
->AddLogin(form_
);
569 cross_origin_form_
.skip_zero_click
= true;
570 store_
->AddLogin(cross_origin_form_
);
572 // Execute the PasswordStore asynchronousness to ensure everything is
573 // written before proceeding.
574 RunAllPendingTasks();
577 TestPasswordStore::PasswordMap passwords
= store_
->stored_passwords();
578 EXPECT_EQ(2U, passwords
.size());
579 EXPECT_EQ(1U, passwords
[form_
.signon_realm
].size());
580 EXPECT_EQ(1U, passwords
[cross_origin_form_
.signon_realm
].size());
581 EXPECT_TRUE(passwords
[form_
.signon_realm
][0].skip_zero_click
);
582 EXPECT_TRUE(passwords
[cross_origin_form_
.signon_realm
][0].skip_zero_click
);
584 // Trigger a request which should return the credential found in |form_|, and
585 // wait for it to process.
586 std::vector
<GURL
> federations
;
587 // Check that the form in the database has been updated. `OnRequestCredential`
588 // generates a call to prompt the user to choose a credential.
589 // MockPasswordManagerClient mocks a user choice, and when users choose a
590 // credential (and have the global zero-click flag enabled), we make sure that
591 // they'll be logged in again next time.
592 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
593 .Times(testing::Exactly(1));
594 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
596 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
597 RunAllPendingTasks();
599 passwords
= store_
->stored_passwords();
600 EXPECT_EQ(2U, passwords
.size());
601 EXPECT_EQ(1U, passwords
[form_
.signon_realm
].size());
602 EXPECT_EQ(1U, passwords
[cross_origin_form_
.signon_realm
].size());
603 EXPECT_FALSE(passwords
[form_
.signon_realm
][0].skip_zero_click
);
604 EXPECT_TRUE(passwords
[cross_origin_form_
.signon_realm
][0].skip_zero_click
);
607 TEST_F(CredentialManagerDispatcherTest
, IncognitoZeroClickRequestCredential
) {
608 EXPECT_CALL(*client_
, IsOffTheRecord()).WillRepeatedly(testing::Return(true));
609 store_
->AddLogin(form_
);
611 std::vector
<GURL
> federations
;
612 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
613 .Times(testing::Exactly(0));
614 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
616 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
618 RunAllPendingTasks();
620 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
621 const IPC::Message
* message
=
622 process()->sink().GetFirstMessageMatching(kMsgID
);
623 ASSERT_TRUE(message
);
624 CredentialManagerMsg_SendCredential::Param param
;
625 CredentialManagerMsg_SendCredential::Read(message
, ¶m
);
626 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
, base::get
<1>(param
).type
);
629 } // namespace password_manager