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
, CredentialManagerOnStore
) {
219 form_
, password_manager::CredentialType::CREDENTIAL_TYPE_PASSWORD
);
222 PromptUserToSavePasswordPtr(
223 _
, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API
))
224 .Times(testing::Exactly(1));
226 dispatcher()->OnStore(kRequestId
, info
);
228 const uint32 kMsgID
= CredentialManagerMsg_AcknowledgeStore::ID
;
229 const IPC::Message
* message
=
230 process()->sink().GetFirstMessageMatching(kMsgID
);
231 EXPECT_TRUE(message
);
232 process()->sink().ClearMessages();
234 // Allow the PasswordFormManager to talk to the password store, determine
235 // that the form is new, and set it as pending.
236 RunAllPendingTasks();
238 EXPECT_TRUE(client_
->pending_manager()->HasCompletedMatching());
240 autofill::PasswordForm new_form
=
241 client_
->pending_manager()->pending_credentials();
242 EXPECT_EQ(form_
.username_value
, new_form
.username_value
);
243 EXPECT_EQ(form_
.display_name
, new_form
.display_name
);
244 EXPECT_EQ(form_
.password_value
, new_form
.password_value
);
245 EXPECT_EQ(form_
.origin
, new_form
.origin
);
246 EXPECT_EQ(form_
.signon_realm
, new_form
.signon_realm
);
247 EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML
, new_form
.scheme
);
250 TEST_F(CredentialManagerDispatcherTest
,
251 CredentialManagerSignInWithSavingDisabledForCurrentPage
) {
252 CredentialInfo
info(form_
, CredentialType::CREDENTIAL_TYPE_PASSWORD
);
253 EXPECT_CALL(*client_
, IsSavingEnabledForCurrentPage())
254 .WillRepeatedly(testing::Return(false));
257 PromptUserToSavePasswordPtr(
258 _
, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API
))
259 .Times(testing::Exactly(0));
261 dispatcher()->OnStore(kRequestId
, info
);
263 const uint32 kMsgID
= CredentialManagerMsg_AcknowledgeStore::ID
;
264 const IPC::Message
* message
=
265 process()->sink().GetFirstMessageMatching(kMsgID
);
266 EXPECT_TRUE(message
);
267 process()->sink().ClearMessages();
269 RunAllPendingTasks();
271 EXPECT_FALSE(client_
->pending_manager());
274 TEST_F(CredentialManagerDispatcherTest
,
275 CredentialManagerOnRequireUserMediation
) {
276 store_
->AddLogin(form_
);
277 store_
->AddLogin(cross_origin_form_
);
278 RunAllPendingTasks();
280 TestPasswordStore::PasswordMap passwords
= store_
->stored_passwords();
281 EXPECT_EQ(2U, passwords
.size());
282 EXPECT_EQ(1U, passwords
[form_
.signon_realm
].size());
283 EXPECT_EQ(1U, passwords
[cross_origin_form_
.signon_realm
].size());
284 EXPECT_FALSE(passwords
[form_
.signon_realm
][0].skip_zero_click
);
285 EXPECT_FALSE(passwords
[cross_origin_form_
.signon_realm
][0].skip_zero_click
);
287 dispatcher()->OnRequireUserMediation(kRequestId
);
288 RunAllPendingTasks();
290 const uint32 kMsgID
=
291 CredentialManagerMsg_AcknowledgeRequireUserMediation::ID
;
292 const IPC::Message
* message
=
293 process()->sink().GetFirstMessageMatching(kMsgID
);
294 EXPECT_TRUE(message
);
295 process()->sink().ClearMessages();
297 passwords
= store_
->stored_passwords();
298 EXPECT_EQ(2U, passwords
.size());
299 EXPECT_EQ(1U, passwords
[form_
.signon_realm
].size());
300 EXPECT_EQ(1U, passwords
[cross_origin_form_
.signon_realm
].size());
301 EXPECT_TRUE(passwords
[form_
.signon_realm
][0].skip_zero_click
);
302 EXPECT_FALSE(passwords
[cross_origin_form_
.signon_realm
][0].skip_zero_click
);
305 TEST_F(CredentialManagerDispatcherTest
,
306 CredentialManagerOnRequestCredentialWithEmptyPasswordStore
) {
307 std::vector
<GURL
> federations
;
310 PromptUserToSavePasswordPtr(
311 _
, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API
))
312 .Times(testing::Exactly(0));
313 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
314 .Times(testing::Exactly(0));
315 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
317 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
319 RunAllPendingTasks();
321 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
322 const IPC::Message
* message
=
323 process()->sink().GetFirstMessageMatching(kMsgID
);
324 EXPECT_TRUE(message
);
325 CredentialManagerMsg_SendCredential::Param param
;
326 CredentialManagerMsg_SendCredential::Read(message
, ¶m
);
327 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
, base::get
<1>(param
).type
);
328 process()->sink().ClearMessages();
331 TEST_F(CredentialManagerDispatcherTest
,
332 CredentialManagerOnRequestCredentialWithCrossOriginPasswordStore
) {
333 store_
->AddLogin(cross_origin_form_
);
335 std::vector
<GURL
> federations
;
338 PromptUserToSavePasswordPtr(
339 _
, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API
))
340 .Times(testing::Exactly(0));
341 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
342 .Times(testing::Exactly(0));
343 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
345 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
347 RunAllPendingTasks();
349 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
350 const IPC::Message
* message
=
351 process()->sink().GetFirstMessageMatching(kMsgID
);
352 EXPECT_TRUE(message
);
353 CredentialManagerMsg_SendCredential::Param param
;
354 CredentialManagerMsg_SendCredential::Read(message
, ¶m
);
355 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
, base::get
<1>(param
).type
);
356 process()->sink().ClearMessages();
359 TEST_F(CredentialManagerDispatcherTest
,
360 CredentialManagerOnRequestCredentialWithFullPasswordStore
) {
361 client_
->set_zero_click_enabled(false);
362 store_
->AddLogin(form_
);
364 std::vector
<GURL
> federations
;
365 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
366 .Times(testing::Exactly(1));
367 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
369 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
371 RunAllPendingTasks();
373 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
374 const IPC::Message
* message
=
375 process()->sink().GetFirstMessageMatching(kMsgID
);
376 EXPECT_TRUE(message
);
380 CredentialManagerDispatcherTest
,
381 CredentialManagerOnRequestCredentialWithZeroClickOnlyEmptyPasswordStore
) {
382 std::vector
<GURL
> federations
;
383 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
384 .Times(testing::Exactly(0));
385 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
387 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
389 RunAllPendingTasks();
391 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
392 const IPC::Message
* message
=
393 process()->sink().GetFirstMessageMatching(kMsgID
);
394 EXPECT_TRUE(message
);
395 CredentialManagerMsg_SendCredential::Param send_param
;
396 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
397 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
,
398 base::get
<1>(send_param
).type
);
401 TEST_F(CredentialManagerDispatcherTest
,
402 CredentialManagerOnRequestCredentialWithZeroClickOnlyFullPasswordStore
) {
403 store_
->AddLogin(form_
);
405 std::vector
<GURL
> federations
;
406 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
407 .Times(testing::Exactly(0));
408 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(1));
410 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
412 RunAllPendingTasks();
414 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
415 const IPC::Message
* message
=
416 process()->sink().GetFirstMessageMatching(kMsgID
);
417 EXPECT_TRUE(message
);
418 CredentialManagerMsg_SendCredential::Param send_param
;
419 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
420 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_PASSWORD
,
421 base::get
<1>(send_param
).type
);
424 TEST_F(CredentialManagerDispatcherTest
,
425 CredentialManagerOnRequestCredentialWithZeroClickOnlyTwoPasswordStore
) {
426 store_
->AddLogin(form_
);
427 store_
->AddLogin(origin_path_form_
);
429 std::vector
<GURL
> federations
;
430 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
431 .Times(testing::Exactly(0));
432 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
434 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
436 RunAllPendingTasks();
438 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
439 const IPC::Message
* message
=
440 process()->sink().GetFirstMessageMatching(kMsgID
);
441 EXPECT_TRUE(message
);
442 CredentialManagerMsg_SendCredential::Param send_param
;
443 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
445 // With two items in the password store, we shouldn't get credentials back.
446 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
,
447 base::get
<1>(send_param
).type
);
450 TEST_F(CredentialManagerDispatcherTest
,
451 OnRequestCredentialWithZeroClickOnlyOnePasswordStore
) {
452 form_
.skip_zero_click
= true;
453 store_
->AddLogin(form_
);
454 store_
->AddLogin(origin_path_form_
);
456 std::vector
<GURL
> federations
;
457 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
458 .Times(testing::Exactly(0));
459 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(1));
461 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
463 RunAllPendingTasks();
465 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
466 const IPC::Message
* message
=
467 process()->sink().GetFirstMessageMatching(kMsgID
);
468 EXPECT_TRUE(message
);
469 CredentialManagerMsg_SendCredential::Param send_param
;
470 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
472 // We should get |origin_path_form_| back, as |form_| is marked as skipping
474 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_PASSWORD
,
475 base::get
<1>(send_param
).type
);
476 EXPECT_EQ(origin_path_form_
.username_value
, base::get
<1>(send_param
).id
);
477 EXPECT_EQ(origin_path_form_
.display_name
, base::get
<1>(send_param
).name
);
478 EXPECT_EQ(origin_path_form_
.password_value
,
479 base::get
<1>(send_param
).password
);
482 TEST_F(CredentialManagerDispatcherTest
,
483 OnRequestCredentialWithZeroClickOnlyCrossOriginPasswordStore
) {
484 store_
->AddLogin(cross_origin_form_
);
486 form_
.skip_zero_click
= true;
487 store_
->AddLogin(form_
);
489 std::vector
<GURL
> federations
;
490 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
491 .Times(testing::Exactly(0));
492 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
494 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
496 RunAllPendingTasks();
498 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
499 const IPC::Message
* message
=
500 process()->sink().GetFirstMessageMatching(kMsgID
);
501 EXPECT_TRUE(message
);
502 CredentialManagerMsg_SendCredential::Param send_param
;
503 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
505 // We only have cross-origin zero-click credentials; they should not be
507 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
,
508 base::get
<1>(send_param
).type
);
511 TEST_F(CredentialManagerDispatcherTest
,
512 CredentialManagerOnRequestCredentialWhileRequestPending
) {
513 client_
->set_zero_click_enabled(false);
514 store_
->AddLogin(form_
);
516 std::vector
<GURL
> federations
;
517 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
518 .Times(testing::Exactly(0));
519 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
521 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
522 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
524 // Check that the second request triggered a rejection.
525 uint32 kMsgID
= CredentialManagerMsg_RejectCredentialRequest::ID
;
526 const IPC::Message
* message
=
527 process()->sink().GetFirstMessageMatching(kMsgID
);
528 EXPECT_TRUE(message
);
530 CredentialManagerMsg_RejectCredentialRequest::Param reject_param
;
531 CredentialManagerMsg_RejectCredentialRequest::Read(message
, &reject_param
);
532 EXPECT_EQ(blink::WebCredentialManagerError::ErrorTypePendingRequest
,
533 base::get
<1>(reject_param
));
534 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
535 .Times(testing::Exactly(1));
536 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
538 process()->sink().ClearMessages();
540 // Execute the PasswordStore asynchronousness.
541 RunAllPendingTasks();
543 // Check that the first request resolves.
544 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
545 message
= process()->sink().GetFirstMessageMatching(kMsgID
);
546 EXPECT_TRUE(message
);
547 CredentialManagerMsg_SendCredential::Param send_param
;
548 CredentialManagerMsg_SendCredential::Read(message
, &send_param
);
549 EXPECT_NE(CredentialType::CREDENTIAL_TYPE_EMPTY
,
550 base::get
<1>(send_param
).type
);
551 process()->sink().ClearMessages();
554 TEST_F(CredentialManagerDispatcherTest
, ResetSkipZeroClickAfterPrompt
) {
555 // Turn on the global zero-click flag, and add two credentials in separate
556 // origins, both set to skip zero-click.
557 client_
->set_zero_click_enabled(true);
558 form_
.skip_zero_click
= true;
559 store_
->AddLogin(form_
);
560 cross_origin_form_
.skip_zero_click
= true;
561 store_
->AddLogin(cross_origin_form_
);
563 // Execute the PasswordStore asynchronousness to ensure everything is
564 // written before proceeding.
565 RunAllPendingTasks();
568 TestPasswordStore::PasswordMap passwords
= store_
->stored_passwords();
569 EXPECT_EQ(2U, passwords
.size());
570 EXPECT_EQ(1U, passwords
[form_
.signon_realm
].size());
571 EXPECT_EQ(1U, passwords
[cross_origin_form_
.signon_realm
].size());
572 EXPECT_TRUE(passwords
[form_
.signon_realm
][0].skip_zero_click
);
573 EXPECT_TRUE(passwords
[cross_origin_form_
.signon_realm
][0].skip_zero_click
);
575 // Trigger a request which should return the credential found in |form_|, and
576 // wait for it to process.
577 std::vector
<GURL
> federations
;
578 // Check that the form in the database has been updated. `OnRequestCredential`
579 // generates a call to prompt the user to choose a credential.
580 // MockPasswordManagerClient mocks a user choice, and when users choose a
581 // credential (and have the global zero-click flag enabled), we make sure that
582 // they'll be logged in again next time.
583 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
584 .Times(testing::Exactly(1));
585 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
587 dispatcher()->OnRequestCredential(kRequestId
, false, federations
);
588 RunAllPendingTasks();
590 passwords
= store_
->stored_passwords();
591 EXPECT_EQ(2U, passwords
.size());
592 EXPECT_EQ(1U, passwords
[form_
.signon_realm
].size());
593 EXPECT_EQ(1U, passwords
[cross_origin_form_
.signon_realm
].size());
594 EXPECT_FALSE(passwords
[form_
.signon_realm
][0].skip_zero_click
);
595 EXPECT_TRUE(passwords
[cross_origin_form_
.signon_realm
][0].skip_zero_click
);
598 TEST_F(CredentialManagerDispatcherTest
, IncognitoZeroClickRequestCredential
) {
599 EXPECT_CALL(*client_
, IsOffTheRecord()).WillRepeatedly(testing::Return(true));
600 store_
->AddLogin(form_
);
602 std::vector
<GURL
> federations
;
603 EXPECT_CALL(*client_
, PromptUserToChooseCredentialsPtr(_
, _
, _
, _
))
604 .Times(testing::Exactly(0));
605 EXPECT_CALL(*client_
, NotifyUserAutoSigninPtr(_
)).Times(testing::Exactly(0));
607 dispatcher()->OnRequestCredential(kRequestId
, true, federations
);
609 RunAllPendingTasks();
611 const uint32 kMsgID
= CredentialManagerMsg_SendCredential::ID
;
612 const IPC::Message
* message
=
613 process()->sink().GetFirstMessageMatching(kMsgID
);
614 ASSERT_TRUE(message
);
615 CredentialManagerMsg_SendCredential::Param param
;
616 CredentialManagerMsg_SendCredential::Read(message
, ¶m
);
617 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY
, base::get
<1>(param
).type
);
620 } // namespace password_manager