Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: components/password_manager/content/browser/credential_manager_dispatcher_unittest.cc

Issue 1762603002: Switch components/password_manager code from IPC messages to Mojo. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase only Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "components/password_manager/content/browser/credential_manager_dispatc her.h"
6
7 #include <stdint.h>
8
9 #include <string>
10 #include <tuple>
11 #include <vector>
12
13 #include "base/bind.h"
14 #include "base/command_line.h"
15 #include "base/macros.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/run_loop.h"
18 #include "base/strings/string16.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/thread_task_runner_handle.h"
21 #include "components/password_manager/content/common/credential_manager_messages .h"
22 #include "components/password_manager/core/browser/credential_manager_password_f orm_manager.h"
23 #include "components/password_manager/core/browser/mock_affiliated_match_helper. h"
24 #include "components/password_manager/core/browser/password_manager.h"
25 #include "components/password_manager/core/browser/stub_password_manager_client. h"
26 #include "components/password_manager/core/browser/stub_password_manager_driver. h"
27 #include "components/password_manager/core/browser/test_password_store.h"
28 #include "components/password_manager/core/common/credential_manager_types.h"
29 #include "components/password_manager/core/common/password_manager_pref_names.h"
30 #include "components/prefs/pref_registry_simple.h"
31 #include "components/prefs/testing_pref_service.h"
32 #include "content/public/browser/web_contents.h"
33 #include "content/public/test/mock_render_process_host.h"
34 #include "content/public/test/test_renderer_host.h"
35 #include "testing/gmock/include/gmock/gmock.h"
36 #include "testing/gtest/include/gtest/gtest.h"
37
38 using content::BrowserContext;
39 using content::WebContents;
40
41 using testing::_;
42
43 namespace password_manager {
44
45 namespace {
46
47 // Chosen by fair dice roll. Guaranteed to be random.
48 const int kRequestId = 4;
49
50 const char kTestWebOrigin[] = "https://example.com/";
51 const char kTestAndroidRealm1[] = "android://hash@com.example.one.android/";
52 const char kTestAndroidRealm2[] = "android://hash@com.example.two.android/";
53
54 class MockPasswordManagerClient : public StubPasswordManagerClient {
55 public:
56 MOCK_CONST_METHOD0(IsSavingAndFillingEnabledForCurrentPage, bool());
57 MOCK_CONST_METHOD0(IsOffTheRecord, bool());
58 MOCK_CONST_METHOD0(DidLastPageLoadEncounterSSLErrors, bool());
59 MOCK_METHOD1(NotifyUserAutoSigninPtr,
60 bool(const std::vector<autofill::PasswordForm*>& local_forms));
61 MOCK_METHOD1(NotifyUserCouldBeAutoSignedInPtr,
62 bool(autofill::PasswordForm* form));
63 MOCK_METHOD2(PromptUserToSavePasswordPtr,
64 void(PasswordFormManager*, CredentialSourceType type));
65 MOCK_METHOD4(PromptUserToChooseCredentialsPtr,
66 bool(const std::vector<autofill::PasswordForm*>& local_forms,
67 const std::vector<autofill::PasswordForm*>& federated_forms,
68 const GURL& origin,
69 const CredentialsCallback& callback));
70
71 explicit MockPasswordManagerClient(PasswordStore* store) : store_(store) {
72 prefs_.registry()->RegisterBooleanPref(prefs::kCredentialsEnableAutosignin,
73 true);
74 prefs_.registry()->RegisterBooleanPref(
75 prefs::kWasAutoSignInFirstRunExperienceShown, true);
76 }
77 ~MockPasswordManagerClient() override {}
78
79 bool PromptUserToSaveOrUpdatePassword(
80 std::unique_ptr<PasswordFormManager> manager,
81 CredentialSourceType type,
82 bool update_password) override {
83 manager_.swap(manager);
84 PromptUserToSavePasswordPtr(manager_.get(), type);
85 return true;
86 }
87
88 void NotifyUserCouldBeAutoSignedIn(
89 std::unique_ptr<autofill::PasswordForm> form) override {
90 NotifyUserCouldBeAutoSignedInPtr(form.get());
91 }
92
93 PasswordStore* GetPasswordStore() const override { return store_; }
94
95 PrefService* GetPrefs() override { return &prefs_; }
96
97 bool PromptUserToChooseCredentials(
98 ScopedVector<autofill::PasswordForm> local_forms,
99 ScopedVector<autofill::PasswordForm> federated_forms,
100 const GURL& origin,
101 const CredentialsCallback& callback) {
102 EXPECT_FALSE(local_forms.empty() && federated_forms.empty());
103 const autofill::PasswordForm* form =
104 local_forms.empty() ? federated_forms[0] : local_forms[0];
105 base::ThreadTaskRunnerHandle::Get()->PostTask(
106 FROM_HERE,
107 base::Bind(callback, base::Owned(new autofill::PasswordForm(*form))));
108 PromptUserToChooseCredentialsPtr(local_forms.get(), federated_forms.get(),
109 origin, callback);
110 return true;
111 }
112
113 void NotifyUserAutoSignin(ScopedVector<autofill::PasswordForm> local_forms,
114 const GURL& origin) override {
115 EXPECT_FALSE(local_forms.empty());
116 NotifyUserAutoSigninPtr(local_forms.get());
117 }
118
119 PasswordFormManager* pending_manager() const { return manager_.get(); }
120
121 void set_zero_click_enabled(bool zero_click_enabled) {
122 prefs_.SetBoolean(prefs::kCredentialsEnableAutosignin, zero_click_enabled);
123 }
124
125 void set_first_run_seen(bool first_run_seen) {
126 prefs_.SetBoolean(prefs::kWasAutoSignInFirstRunExperienceShown,
127 first_run_seen);
128 }
129
130 private:
131 TestingPrefServiceSimple prefs_;
132 PasswordStore* store_;
133 std::unique_ptr<PasswordFormManager> manager_;
134
135 DISALLOW_COPY_AND_ASSIGN(MockPasswordManagerClient);
136 };
137
138 class TestCredentialManagerDispatcher : public CredentialManagerDispatcher {
139 public:
140 TestCredentialManagerDispatcher(content::WebContents* web_contents,
141 PasswordManagerClient* client,
142 PasswordManagerDriver* driver);
143
144 private:
145 base::WeakPtr<PasswordManagerDriver> GetDriver() override;
146
147 base::WeakPtr<PasswordManagerDriver> driver_;
148 };
149
150 TestCredentialManagerDispatcher::TestCredentialManagerDispatcher(
151 content::WebContents* web_contents,
152 PasswordManagerClient* client,
153 PasswordManagerDriver* driver)
154 : CredentialManagerDispatcher(web_contents, client),
155 driver_(driver->AsWeakPtr()) {}
156
157 base::WeakPtr<PasswordManagerDriver>
158 TestCredentialManagerDispatcher::GetDriver() {
159 return driver_;
160 }
161
162 void RunAllPendingTasks() {
163 base::RunLoop run_loop;
164 base::MessageLoop::current()->PostTask(
165 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
166 run_loop.Run();
167 }
168
169 class SlightlyLessStubbyPasswordManagerDriver
170 : public StubPasswordManagerDriver {
171 public:
172 explicit SlightlyLessStubbyPasswordManagerDriver(
173 PasswordManagerClient* client)
174 : password_manager_(client) {}
175
176 PasswordManager* GetPasswordManager() override { return &password_manager_; }
177
178 private:
179 PasswordManager password_manager_;
180 };
181
182 } // namespace
183
184 class CredentialManagerDispatcherTest
185 : public content::RenderViewHostTestHarness {
186 public:
187 CredentialManagerDispatcherTest() {}
188
189 void SetUp() override {
190 content::RenderViewHostTestHarness::SetUp();
191 store_ = new TestPasswordStore;
192 client_.reset(
193 new testing::NiceMock<MockPasswordManagerClient>(store_.get()));
194 stub_driver_.reset(
195 new SlightlyLessStubbyPasswordManagerDriver(client_.get()));
196 dispatcher_.reset(new TestCredentialManagerDispatcher(
197 web_contents(), client_.get(), stub_driver_.get()));
198 ON_CALL(*client_, IsSavingAndFillingEnabledForCurrentPage())
199 .WillByDefault(testing::Return(true));
200 ON_CALL(*client_, IsOffTheRecord()).WillByDefault(testing::Return(false));
201 ON_CALL(*client_, DidLastPageLoadEncounterSSLErrors())
202 .WillByDefault(testing::Return(false));
203
204 NavigateAndCommit(GURL("https://example.com/test.html"));
205
206 form_.username_value = base::ASCIIToUTF16("Username");
207 form_.display_name = base::ASCIIToUTF16("Display Name");
208 form_.password_value = base::ASCIIToUTF16("Password");
209 form_.origin = web_contents()->GetLastCommittedURL().GetOrigin();
210 form_.signon_realm = form_.origin.spec();
211 form_.scheme = autofill::PasswordForm::SCHEME_HTML;
212 form_.skip_zero_click = false;
213 form_.ssl_valid = true;
214
215 affiliated_form1_.username_value = base::ASCIIToUTF16("Affiliated 1");
216 affiliated_form1_.display_name = base::ASCIIToUTF16("Display Name");
217 affiliated_form1_.password_value = base::ASCIIToUTF16("Password");
218 affiliated_form1_.origin = GURL();
219 affiliated_form1_.signon_realm = kTestAndroidRealm1;
220 affiliated_form1_.scheme = autofill::PasswordForm::SCHEME_HTML;
221 affiliated_form1_.skip_zero_click = false;
222 affiliated_form1_.ssl_valid = true;
223
224 affiliated_form2_.username_value = base::ASCIIToUTF16("Affiliated 2");
225 affiliated_form2_.display_name = base::ASCIIToUTF16("Display Name");
226 affiliated_form2_.password_value = base::ASCIIToUTF16("Password");
227 affiliated_form2_.origin = GURL();
228 affiliated_form2_.signon_realm = kTestAndroidRealm2;
229 affiliated_form2_.scheme = autofill::PasswordForm::SCHEME_HTML;
230 affiliated_form2_.skip_zero_click = false;
231 affiliated_form2_.ssl_valid = true;
232
233 origin_path_form_.username_value = base::ASCIIToUTF16("Username 2");
234 origin_path_form_.display_name = base::ASCIIToUTF16("Display Name 2");
235 origin_path_form_.password_value = base::ASCIIToUTF16("Password 2");
236 origin_path_form_.origin = GURL("https://example.com/path");
237 origin_path_form_.signon_realm = origin_path_form_.origin.spec();
238 origin_path_form_.scheme = autofill::PasswordForm::SCHEME_HTML;
239 origin_path_form_.skip_zero_click = false;
240
241 cross_origin_form_.username_value = base::ASCIIToUTF16("Username");
242 cross_origin_form_.display_name = base::ASCIIToUTF16("Display Name");
243 cross_origin_form_.password_value = base::ASCIIToUTF16("Password");
244 cross_origin_form_.origin = GURL("https://example.net/");
245 cross_origin_form_.signon_realm = cross_origin_form_.origin.spec();
246 cross_origin_form_.scheme = autofill::PasswordForm::SCHEME_HTML;
247 cross_origin_form_.skip_zero_click = false;
248
249 store_->Clear();
250 EXPECT_TRUE(store_->IsEmpty());
251 }
252
253 void TearDown() override {
254 store_->ShutdownOnUIThread();
255 content::RenderViewHostTestHarness::TearDown();
256 }
257
258 void ExpectZeroClickSignInFailure() {
259 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
260 .Times(testing::Exactly(0));
261 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_))
262 .Times(testing::Exactly(0));
263
264 RunAllPendingTasks();
265
266 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
267 const IPC::Message* message =
268 process()->sink().GetFirstMessageMatching(kMsgID);
269 ASSERT_TRUE(message);
270 CredentialManagerMsg_SendCredential::Param send_param;
271 CredentialManagerMsg_SendCredential::Read(message, &send_param);
272
273 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY,
274 std::get<1>(send_param).type);
275 }
276
277 void ExpectZeroClickSignInSuccess(CredentialType type) {
278 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
279 .Times(testing::Exactly(0));
280 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_))
281 .Times(testing::Exactly(1));
282
283 RunAllPendingTasks();
284
285 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
286 const IPC::Message* message =
287 process()->sink().GetFirstMessageMatching(kMsgID);
288 ASSERT_TRUE(message);
289 CredentialManagerMsg_SendCredential::Param send_param;
290 CredentialManagerMsg_SendCredential::Read(message, &send_param);
291
292 EXPECT_EQ(type, std::get<1>(send_param).type);
293 }
294
295 CredentialManagerDispatcher* dispatcher() { return dispatcher_.get(); }
296
297 protected:
298 autofill::PasswordForm form_;
299 autofill::PasswordForm affiliated_form1_;
300 autofill::PasswordForm affiliated_form2_;
301 autofill::PasswordForm origin_path_form_;
302 autofill::PasswordForm cross_origin_form_;
303 scoped_refptr<TestPasswordStore> store_;
304 std::unique_ptr<testing::NiceMock<MockPasswordManagerClient>> client_;
305 std::unique_ptr<SlightlyLessStubbyPasswordManagerDriver> stub_driver_;
306 std::unique_ptr<CredentialManagerDispatcher> dispatcher_;
307 };
308
309 TEST_F(CredentialManagerDispatcherTest, IsZeroClickAllowed) {
310 // IsZeroClickAllowed is uneffected by the first-run status.
311 client_->set_zero_click_enabled(true);
312 client_->set_first_run_seen(true);
313 EXPECT_TRUE(dispatcher()->IsZeroClickAllowed());
314
315 client_->set_zero_click_enabled(true);
316 client_->set_first_run_seen(false);
317 EXPECT_TRUE(dispatcher()->IsZeroClickAllowed());
318
319 client_->set_zero_click_enabled(false);
320 client_->set_first_run_seen(true);
321 EXPECT_FALSE(dispatcher()->IsZeroClickAllowed());
322
323 client_->set_zero_click_enabled(false);
324 client_->set_first_run_seen(false);
325 EXPECT_FALSE(dispatcher()->IsZeroClickAllowed());
326 }
327
328 TEST_F(CredentialManagerDispatcherTest, CredentialManagerOnStore) {
329 CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_PASSWORD);
330 EXPECT_CALL(*client_, PromptUserToSavePasswordPtr(
331 _, CredentialSourceType::CREDENTIAL_SOURCE_API))
332 .Times(testing::Exactly(1));
333
334 dispatcher()->OnStore(kRequestId, info);
335
336 const uint32_t kMsgID = CredentialManagerMsg_AcknowledgeStore::ID;
337 const IPC::Message* message =
338 process()->sink().GetFirstMessageMatching(kMsgID);
339 EXPECT_TRUE(message);
340 process()->sink().ClearMessages();
341
342 // Allow the PasswordFormManager to talk to the password store, determine
343 // that the form is new, and set it as pending.
344 RunAllPendingTasks();
345
346 EXPECT_TRUE(client_->pending_manager()->HasCompletedMatching());
347
348 autofill::PasswordForm new_form =
349 client_->pending_manager()->pending_credentials();
350 EXPECT_EQ(form_.username_value, new_form.username_value);
351 EXPECT_EQ(form_.display_name, new_form.display_name);
352 EXPECT_EQ(form_.password_value, new_form.password_value);
353 EXPECT_EQ(form_.origin, new_form.origin);
354 EXPECT_EQ(form_.signon_realm, new_form.signon_realm);
355 EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML, new_form.scheme);
356 }
357
358 TEST_F(CredentialManagerDispatcherTest, CredentialManagerStoreOverwrite) {
359 // Populate the PasswordStore with a form.
360 store_->AddLogin(form_);
361 RunAllPendingTasks();
362
363 // Calling 'OnStore' with a credential that matches |form_| should update
364 // the password without prompting the user.
365 CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_PASSWORD);
366 info.password = base::ASCIIToUTF16("Totally new password.");
367 dispatcher()->OnStore(kRequestId, info);
368
369 EXPECT_CALL(*client_, PromptUserToSavePasswordPtr(
370 _, CredentialSourceType::CREDENTIAL_SOURCE_API))
371 .Times(testing::Exactly(0));
372
373 const uint32_t kMsgID = CredentialManagerMsg_AcknowledgeStore::ID;
374 const IPC::Message* message =
375 process()->sink().GetFirstMessageMatching(kMsgID);
376 EXPECT_TRUE(message);
377 process()->sink().ClearMessages();
378
379 // Allow the PasswordFormManager to talk to the password store, determine
380 // the form is a match for an existing form, and update the PasswordStore.
381 RunAllPendingTasks();
382
383 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
384 EXPECT_EQ(1U, passwords.size());
385 EXPECT_EQ(1U, passwords[form_.signon_realm].size());
386 EXPECT_EQ(base::ASCIIToUTF16("Totally new password."),
387 passwords[form_.signon_realm][0].password_value);
388 }
389
390 TEST_F(CredentialManagerDispatcherTest,
391 CredentialManagerStoreOverwriteZeroClick) {
392 // Set the global zero click flag on, and populate the PasswordStore with a
393 // form that's set to skip zero click.
394 client_->set_zero_click_enabled(true);
395 form_.skip_zero_click = true;
396 store_->AddLogin(form_);
397 RunAllPendingTasks();
398
399 // Calling 'OnStore' with a credential that matches |form_| should update
400 // the password without prompting the user.
401 CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_PASSWORD);
402 info.password = base::ASCIIToUTF16("Totally new password.");
403 dispatcher()->OnStore(kRequestId, info);
404 process()->sink().ClearMessages();
405
406 // Allow the PasswordFormManager to talk to the password store, determine
407 // the form is a match for an existing form, and update the PasswordStore.
408 RunAllPendingTasks();
409
410 // Verify that the update didn't toggle the skip_zero_click flag off.
411 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
412 EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click);
413 }
414
415 TEST_F(CredentialManagerDispatcherTest,
416 CredentialManagerGetOverwriteZeroClick) {
417 // Set the global zero click flag on, and populate the PasswordStore with a
418 // form that's set to skip zero click and has a primary key that won't match
419 // credentials initially created via `store()`.
420 client_->set_zero_click_enabled(true);
421 form_.skip_zero_click = true;
422 form_.username_element = base::ASCIIToUTF16("username-element");
423 form_.password_element = base::ASCIIToUTF16("password-element");
424 form_.signon_realm = "this is a realm";
425 form_.origin = GURL("https://example.com/old_form.html");
426 store_->AddLogin(form_);
427 RunAllPendingTasks();
428
429 std::vector<GURL> federations;
430 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
431 .Times(testing::Exactly(1));
432 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
433
434 dispatcher()->OnRequestCredential(kRequestId, false, true, federations);
435
436 RunAllPendingTasks();
437
438 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
439 const IPC::Message* message =
440 process()->sink().GetFirstMessageMatching(kMsgID);
441 EXPECT_TRUE(message);
442
443 // Verify that the update toggled the skip_zero_click flag.
444 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
445 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
446 }
447
448 TEST_F(CredentialManagerDispatcherTest,
449 CredentialManagerSignInWithSavingDisabledForCurrentPage) {
450 CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_PASSWORD);
451 EXPECT_CALL(*client_, IsSavingAndFillingEnabledForCurrentPage())
452 .WillRepeatedly(testing::Return(false));
453 EXPECT_CALL(*client_, PromptUserToSavePasswordPtr(
454 _, CredentialSourceType::CREDENTIAL_SOURCE_API))
455 .Times(testing::Exactly(0));
456
457 dispatcher()->OnStore(kRequestId, info);
458
459 const uint32_t kMsgID = CredentialManagerMsg_AcknowledgeStore::ID;
460 const IPC::Message* message =
461 process()->sink().GetFirstMessageMatching(kMsgID);
462 EXPECT_TRUE(message);
463 process()->sink().ClearMessages();
464
465 RunAllPendingTasks();
466
467 EXPECT_FALSE(client_->pending_manager());
468 }
469
470 TEST_F(CredentialManagerDispatcherTest,
471 CredentialManagerOnRequireUserMediation) {
472 store_->AddLogin(form_);
473 store_->AddLogin(cross_origin_form_);
474 RunAllPendingTasks();
475
476 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
477 EXPECT_EQ(2U, passwords.size());
478 EXPECT_EQ(1U, passwords[form_.signon_realm].size());
479 EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
480 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
481 EXPECT_FALSE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
482
483 dispatcher()->OnRequireUserMediation(kRequestId);
484 RunAllPendingTasks();
485
486 const uint32_t kMsgID =
487 CredentialManagerMsg_AcknowledgeRequireUserMediation::ID;
488 const IPC::Message* message =
489 process()->sink().GetFirstMessageMatching(kMsgID);
490 EXPECT_TRUE(message);
491 process()->sink().ClearMessages();
492
493 passwords = store_->stored_passwords();
494 EXPECT_EQ(2U, passwords.size());
495 EXPECT_EQ(1U, passwords[form_.signon_realm].size());
496 EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
497 EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click);
498 EXPECT_FALSE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
499 }
500
501 TEST_F(CredentialManagerDispatcherTest,
502 CredentialManagerOnRequireUserMediationIncognito) {
503 EXPECT_CALL(*client_, IsOffTheRecord()).WillRepeatedly(testing::Return(true));
504 store_->AddLogin(form_);
505 RunAllPendingTasks();
506
507 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
508 ASSERT_EQ(1U, passwords.size());
509 ASSERT_EQ(1U, passwords[form_.signon_realm].size());
510 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
511
512 dispatcher()->OnRequireUserMediation(kRequestId);
513 RunAllPendingTasks();
514
515 const uint32_t kMsgID =
516 CredentialManagerMsg_AcknowledgeRequireUserMediation::ID;
517 const IPC::Message* message =
518 process()->sink().GetFirstMessageMatching(kMsgID);
519 EXPECT_TRUE(message);
520 process()->sink().ClearMessages();
521
522 passwords = store_->stored_passwords();
523 ASSERT_EQ(1U, passwords.size());
524 ASSERT_EQ(1U, passwords[form_.signon_realm].size());
525 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
526 }
527
528 TEST_F(CredentialManagerDispatcherTest,
529 CredentialManagerOnRequireUserMediationWithAffiliation) {
530 store_->AddLogin(form_);
531 store_->AddLogin(cross_origin_form_);
532 store_->AddLogin(affiliated_form1_);
533 store_->AddLogin(affiliated_form2_);
534
535 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
536 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
537
538 std::vector<GURL> federations;
539 std::vector<std::string> affiliated_realms;
540 affiliated_realms.push_back(kTestAndroidRealm1);
541 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
542 ->ExpectCallToGetAffiliatedAndroidRealms(
543 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
544 RunAllPendingTasks();
545
546 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
547 EXPECT_EQ(4U, passwords.size());
548 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
549 EXPECT_FALSE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
550 EXPECT_FALSE(passwords[affiliated_form1_.signon_realm][0].skip_zero_click);
551 EXPECT_FALSE(passwords[affiliated_form2_.signon_realm][0].skip_zero_click);
552
553 dispatcher()->OnRequireUserMediation(kRequestId);
554 RunAllPendingTasks();
555 process()->sink().ClearMessages();
556
557 passwords = store_->stored_passwords();
558 EXPECT_EQ(4U, passwords.size());
559 EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click);
560 EXPECT_FALSE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
561 EXPECT_TRUE(passwords[affiliated_form1_.signon_realm][0].skip_zero_click);
562 EXPECT_FALSE(passwords[affiliated_form2_.signon_realm][0].skip_zero_click);
563 }
564
565 TEST_F(CredentialManagerDispatcherTest,
566 CredentialManagerOnRequestCredentialWithEmptyPasswordStore) {
567 std::vector<GURL> federations;
568 EXPECT_CALL(*client_, PromptUserToSavePasswordPtr(
569 _, CredentialSourceType::CREDENTIAL_SOURCE_API))
570 .Times(testing::Exactly(0));
571 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
572 .Times(testing::Exactly(0));
573 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
574
575 dispatcher()->OnRequestCredential(kRequestId, false, true, federations);
576
577 RunAllPendingTasks();
578
579 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
580 const IPC::Message* message =
581 process()->sink().GetFirstMessageMatching(kMsgID);
582 EXPECT_TRUE(message);
583 CredentialManagerMsg_SendCredential::Param param;
584 CredentialManagerMsg_SendCredential::Read(message, &param);
585 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, std::get<1>(param).type);
586 process()->sink().ClearMessages();
587 }
588
589 TEST_F(CredentialManagerDispatcherTest,
590 CredentialManagerOnRequestCredentialWithCrossOriginPasswordStore) {
591 store_->AddLogin(cross_origin_form_);
592
593 std::vector<GURL> federations;
594 EXPECT_CALL(*client_, PromptUserToSavePasswordPtr(
595 _, CredentialSourceType::CREDENTIAL_SOURCE_API))
596 .Times(testing::Exactly(0));
597 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
598 .Times(testing::Exactly(0));
599 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
600
601 dispatcher()->OnRequestCredential(kRequestId, false, true, federations);
602
603 RunAllPendingTasks();
604
605 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
606 const IPC::Message* message =
607 process()->sink().GetFirstMessageMatching(kMsgID);
608 EXPECT_TRUE(message);
609 CredentialManagerMsg_SendCredential::Param param;
610 CredentialManagerMsg_SendCredential::Read(message, &param);
611 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, std::get<1>(param).type);
612 process()->sink().ClearMessages();
613 }
614
615 TEST_F(CredentialManagerDispatcherTest,
616 CredentialManagerOnRequestCredentialWithFullPasswordStore) {
617 client_->set_zero_click_enabled(false);
618 store_->AddLogin(form_);
619
620 std::vector<GURL> federations;
621 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
622 .Times(testing::Exactly(1));
623 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
624
625 dispatcher()->OnRequestCredential(kRequestId, false, true, federations);
626
627 RunAllPendingTasks();
628
629 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
630 const IPC::Message* message =
631 process()->sink().GetFirstMessageMatching(kMsgID);
632 EXPECT_TRUE(message);
633 }
634
635 TEST_F(
636 CredentialManagerDispatcherTest,
637 CredentialManagerOnRequestCredentialWithZeroClickOnlyEmptyPasswordStore) {
638 std::vector<GURL> federations;
639 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
640 .Times(testing::Exactly(0));
641 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
642
643 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
644
645 RunAllPendingTasks();
646
647 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
648 const IPC::Message* message =
649 process()->sink().GetFirstMessageMatching(kMsgID);
650 EXPECT_TRUE(message);
651 CredentialManagerMsg_SendCredential::Param send_param;
652 CredentialManagerMsg_SendCredential::Read(message, &send_param);
653 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY,
654 std::get<1>(send_param).type);
655 }
656
657 TEST_F(CredentialManagerDispatcherTest,
658 CredentialManagerOnRequestCredentialWithZeroClickOnlyFullPasswordStore) {
659 store_->AddLogin(form_);
660 client_->set_first_run_seen(true);
661
662 std::vector<GURL> federations;
663
664 EXPECT_CALL(*client_, NotifyUserCouldBeAutoSignedInPtr(_)).Times(0);
665 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
666
667 ExpectZeroClickSignInSuccess(CredentialType::CREDENTIAL_TYPE_PASSWORD);
668 }
669
670 TEST_F(CredentialManagerDispatcherTest,
671 CredentialManagerOnRequestCredentialWithoutPasswords) {
672 store_->AddLogin(form_);
673 client_->set_first_run_seen(true);
674
675 std::vector<GURL> federations;
676
677 EXPECT_CALL(*client_, NotifyUserCouldBeAutoSignedInPtr(_)).Times(0);
678 dispatcher()->OnRequestCredential(kRequestId, true, false, federations);
679
680 ExpectZeroClickSignInFailure();
681 }
682
683 TEST_F(CredentialManagerDispatcherTest,
684 CredentialManagerOnRequestCredentialFederatedMatch) {
685 form_.federation_origin = url::Origin(GURL("https://example.com/"));
686 store_->AddLogin(form_);
687 client_->set_first_run_seen(true);
688
689 std::vector<GURL> federations;
690 federations.push_back(GURL("https://example.com/"));
691
692 EXPECT_CALL(*client_, NotifyUserCouldBeAutoSignedInPtr(_)).Times(0);
693 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
694
695 ExpectZeroClickSignInSuccess(CredentialType::CREDENTIAL_TYPE_FEDERATED);
696 }
697
698 TEST_F(CredentialManagerDispatcherTest,
699 CredentialManagerOnRequestCredentialFederatedNoMatch) {
700 form_.federation_origin = url::Origin(GURL("https://example.com/"));
701 store_->AddLogin(form_);
702 client_->set_first_run_seen(true);
703
704 std::vector<GURL> federations;
705 federations.push_back(GURL("https://not-example.com/"));
706
707 EXPECT_CALL(*client_, NotifyUserCouldBeAutoSignedInPtr(_)).Times(0);
708 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
709
710 ExpectZeroClickSignInFailure();
711 }
712
713 TEST_F(CredentialManagerDispatcherTest,
714 CredentialManagerOnRequestCredentialAffiliatedPasswordMatch) {
715 store_->AddLogin(affiliated_form1_);
716 client_->set_first_run_seen(true);
717 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
718 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
719
720 std::vector<GURL> federations;
721 std::vector<std::string> affiliated_realms;
722 affiliated_realms.push_back(kTestAndroidRealm1);
723 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
724 ->ExpectCallToGetAffiliatedAndroidRealms(
725 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
726
727 // We pass in 'true' for the 'include_passwords' argument to ensure that
728 // password-type credentials are included as potential matches.
729 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
730
731 ExpectZeroClickSignInSuccess(CredentialType::CREDENTIAL_TYPE_PASSWORD);
732 }
733
734 TEST_F(CredentialManagerDispatcherTest,
735 CredentialManagerOnRequestCredentialAffiliatedPasswordNoMatch) {
736 store_->AddLogin(affiliated_form1_);
737 client_->set_first_run_seen(true);
738 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
739 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
740
741 std::vector<GURL> federations;
742 std::vector<std::string> affiliated_realms;
743 affiliated_realms.push_back(kTestAndroidRealm1);
744 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
745 ->ExpectCallToGetAffiliatedAndroidRealms(
746 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
747
748 // We pass in 'false' for the 'include_passwords' argument to ensure that
749 // password-type credentials are excluded as potential matches.
750 dispatcher()->OnRequestCredential(kRequestId, true, false, federations);
751
752 ExpectZeroClickSignInFailure();
753 }
754
755 TEST_F(CredentialManagerDispatcherTest,
756 CredentialManagerOnRequestCredentialAffiliatedFederatedMatch) {
757 affiliated_form1_.federation_origin =
758 url::Origin(GURL("https://example.com/"));
759 store_->AddLogin(affiliated_form1_);
760 client_->set_first_run_seen(true);
761 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
762 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
763
764 std::vector<GURL> federations;
765 federations.push_back(GURL("https://example.com/"));
766
767 std::vector<std::string> affiliated_realms;
768 affiliated_realms.push_back(kTestAndroidRealm1);
769 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
770 ->ExpectCallToGetAffiliatedAndroidRealms(
771 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
772
773 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
774
775 ExpectZeroClickSignInSuccess(CredentialType::CREDENTIAL_TYPE_FEDERATED);
776 }
777
778 TEST_F(CredentialManagerDispatcherTest,
779 CredentialManagerOnRequestCredentialAffiliatedFederatedNoMatch) {
780 affiliated_form1_.federation_origin =
781 url::Origin(GURL("https://example.com/"));
782 store_->AddLogin(affiliated_form1_);
783 client_->set_first_run_seen(true);
784 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
785 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
786
787 std::vector<GURL> federations;
788 federations.push_back(GURL("https://not-example.com/"));
789
790 std::vector<std::string> affiliated_realms;
791 affiliated_realms.push_back(kTestAndroidRealm1);
792 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
793 ->ExpectCallToGetAffiliatedAndroidRealms(
794 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
795
796 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
797
798 ExpectZeroClickSignInFailure();
799 }
800
801 TEST_F(CredentialManagerDispatcherTest, RequestCredentialWithoutFirstRun) {
802 client_->set_first_run_seen(false);
803
804 store_->AddLogin(form_);
805
806 std::vector<GURL> federations;
807 EXPECT_CALL(*client_,
808 NotifyUserCouldBeAutoSignedInPtr(testing::Pointee(form_)))
809 .Times(1);
810 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
811
812 ExpectZeroClickSignInFailure();
813 }
814
815 TEST_F(CredentialManagerDispatcherTest, RequestCredentialWithFirstRunAndSkip) {
816 client_->set_first_run_seen(true);
817
818 form_.skip_zero_click = true;
819 store_->AddLogin(form_);
820
821 std::vector<GURL> federations;
822 EXPECT_CALL(*client_,
823 NotifyUserCouldBeAutoSignedInPtr(testing::Pointee(form_)))
824 .Times(1);
825 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
826
827 ExpectZeroClickSignInFailure();
828 }
829
830 TEST_F(CredentialManagerDispatcherTest, RequestCredentialWithTLSErrors) {
831 // If we encounter TLS errors, we won't return credentials.
832 EXPECT_CALL(*client_, DidLastPageLoadEncounterSSLErrors())
833 .WillRepeatedly(testing::Return(true));
834
835 store_->AddLogin(form_);
836
837 std::vector<GURL> federations;
838 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
839
840 ExpectZeroClickSignInFailure();
841 }
842
843 TEST_F(CredentialManagerDispatcherTest,
844 CredentialManagerOnRequestCredentialWithZeroClickOnlyTwoPasswordStore) {
845 store_->AddLogin(form_);
846 store_->AddLogin(origin_path_form_);
847
848 std::vector<GURL> federations;
849 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
850 .Times(testing::Exactly(0));
851 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
852
853 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
854
855 RunAllPendingTasks();
856
857 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
858 const IPC::Message* message =
859 process()->sink().GetFirstMessageMatching(kMsgID);
860 EXPECT_TRUE(message);
861 CredentialManagerMsg_SendCredential::Param send_param;
862 CredentialManagerMsg_SendCredential::Read(message, &send_param);
863
864 // With two items in the password store, we shouldn't get credentials back.
865 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY,
866 std::get<1>(send_param).type);
867 }
868
869 TEST_F(CredentialManagerDispatcherTest,
870 OnRequestCredentialWithZeroClickOnlyAndSkipZeroClickPasswordStore) {
871 form_.skip_zero_click = true;
872 store_->AddLogin(form_);
873 store_->AddLogin(origin_path_form_);
874
875 std::vector<GURL> federations;
876 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
877 .Times(testing::Exactly(0));
878 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
879
880 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
881
882 RunAllPendingTasks();
883
884 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
885 const IPC::Message* message =
886 process()->sink().GetFirstMessageMatching(kMsgID);
887 EXPECT_TRUE(message);
888 CredentialManagerMsg_SendCredential::Param send_param;
889 CredentialManagerMsg_SendCredential::Read(message, &send_param);
890
891 // With two items in the password store, we shouldn't get credentials back,
892 // even though only one item has |skip_zero_click| set |false|.
893 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY,
894 std::get<1>(send_param).type);
895 }
896
897 TEST_F(CredentialManagerDispatcherTest,
898 OnRequestCredentialWithZeroClickOnlyCrossOriginPasswordStore) {
899 store_->AddLogin(cross_origin_form_);
900
901 form_.skip_zero_click = true;
902 store_->AddLogin(form_);
903
904 std::vector<GURL> federations;
905 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
906 .Times(testing::Exactly(0));
907 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
908
909 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
910
911 RunAllPendingTasks();
912
913 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
914 const IPC::Message* message =
915 process()->sink().GetFirstMessageMatching(kMsgID);
916 EXPECT_TRUE(message);
917 CredentialManagerMsg_SendCredential::Param send_param;
918 CredentialManagerMsg_SendCredential::Read(message, &send_param);
919
920 // We only have cross-origin zero-click credentials; they should not be
921 // returned.
922 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY,
923 std::get<1>(send_param).type);
924 }
925
926 TEST_F(CredentialManagerDispatcherTest,
927 CredentialManagerOnRequestCredentialWhileRequestPending) {
928 client_->set_zero_click_enabled(false);
929 store_->AddLogin(form_);
930
931 std::vector<GURL> federations;
932 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
933 .Times(testing::Exactly(0));
934 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
935
936 dispatcher()->OnRequestCredential(kRequestId, false, true, federations);
937 dispatcher()->OnRequestCredential(kRequestId + 1, false, true, federations);
938
939 // Check that the second request triggered a rejection.
940 uint32_t kMsgID = CredentialManagerMsg_RejectCredentialRequest::ID;
941 const IPC::Message* message =
942 process()->sink().GetFirstMessageMatching(kMsgID);
943 EXPECT_TRUE(message);
944
945 CredentialManagerMsg_RejectCredentialRequest::Param reject_param;
946 CredentialManagerMsg_RejectCredentialRequest::Read(message, &reject_param);
947 EXPECT_EQ(blink::WebCredentialManagerPendingRequestError,
948 std::get<1>(reject_param));
949 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
950 .Times(testing::Exactly(1));
951 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
952
953 process()->sink().ClearMessages();
954
955 // Execute the PasswordStore asynchronousness.
956 RunAllPendingTasks();
957
958 // Check that the first request resolves.
959 kMsgID = CredentialManagerMsg_SendCredential::ID;
960 message = process()->sink().GetFirstMessageMatching(kMsgID);
961 EXPECT_TRUE(message);
962 CredentialManagerMsg_SendCredential::Param send_param;
963 CredentialManagerMsg_SendCredential::Read(message, &send_param);
964 EXPECT_NE(CredentialType::CREDENTIAL_TYPE_EMPTY,
965 std::get<1>(send_param).type);
966 process()->sink().ClearMessages();
967 }
968
969 TEST_F(CredentialManagerDispatcherTest, ResetSkipZeroClickAfterPrompt) {
970 // Turn on the global zero-click flag, and add two credentials in separate
971 // origins, both set to skip zero-click.
972 client_->set_zero_click_enabled(true);
973 form_.skip_zero_click = true;
974 store_->AddLogin(form_);
975 cross_origin_form_.skip_zero_click = true;
976 store_->AddLogin(cross_origin_form_);
977
978 // Execute the PasswordStore asynchronousness to ensure everything is
979 // written before proceeding.
980 RunAllPendingTasks();
981
982 // Sanity check.
983 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
984 EXPECT_EQ(2U, passwords.size());
985 EXPECT_EQ(1U, passwords[form_.signon_realm].size());
986 EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
987 EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click);
988 EXPECT_TRUE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
989
990 // Trigger a request which should return the credential found in |form_|, and
991 // wait for it to process.
992 std::vector<GURL> federations;
993 // Check that the form in the database has been updated. `OnRequestCredential`
994 // generates a call to prompt the user to choose a credential.
995 // MockPasswordManagerClient mocks a user choice, and when users choose a
996 // credential (and have the global zero-click flag enabled), we make sure that
997 // they'll be logged in again next time.
998 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
999 .Times(testing::Exactly(1));
1000 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
1001
1002 dispatcher()->OnRequestCredential(kRequestId, false, true, federations);
1003 RunAllPendingTasks();
1004
1005 passwords = store_->stored_passwords();
1006 EXPECT_EQ(2U, passwords.size());
1007 EXPECT_EQ(1U, passwords[form_.signon_realm].size());
1008 EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
1009 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
1010 EXPECT_TRUE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
1011 }
1012
1013 TEST_F(CredentialManagerDispatcherTest,
1014 NoResetSkipZeroClickAfterPromptInIncognito) {
1015 EXPECT_CALL(*client_, IsOffTheRecord()).WillRepeatedly(testing::Return(true));
1016 // Turn on the global zero-click flag which should be overriden by Incognito.
1017 client_->set_zero_click_enabled(true);
1018 form_.skip_zero_click = true;
1019 store_->AddLogin(form_);
1020 RunAllPendingTasks();
1021
1022 // Sanity check.
1023 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
1024 ASSERT_EQ(1U, passwords.size());
1025 ASSERT_EQ(1U, passwords[form_.signon_realm].size());
1026 EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click);
1027
1028 // Trigger a request which should return the credential found in |form_|, and
1029 // wait for it to process.
1030 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
1031 .Times(testing::Exactly(1));
1032 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
1033
1034 dispatcher()->OnRequestCredential(kRequestId, false, true,
1035 std::vector<GURL>());
1036 RunAllPendingTasks();
1037
1038 // The form shouldn't become a zero-click one.
1039 passwords = store_->stored_passwords();
1040 ASSERT_EQ(1U, passwords.size());
1041 ASSERT_EQ(1U, passwords[form_.signon_realm].size());
1042 EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click);
1043 }
1044
1045 TEST_F(CredentialManagerDispatcherTest, IncognitoZeroClickRequestCredential) {
1046 EXPECT_CALL(*client_, IsOffTheRecord()).WillRepeatedly(testing::Return(true));
1047 store_->AddLogin(form_);
1048
1049 std::vector<GURL> federations;
1050 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
1051 .Times(testing::Exactly(0));
1052 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
1053
1054 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
1055
1056 RunAllPendingTasks();
1057
1058 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
1059 const IPC::Message* message =
1060 process()->sink().GetFirstMessageMatching(kMsgID);
1061 ASSERT_TRUE(message);
1062 CredentialManagerMsg_SendCredential::Param param;
1063 CredentialManagerMsg_SendCredential::Read(message, &param);
1064 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, std::get<1>(param).type);
1065 }
1066
1067 TEST_F(CredentialManagerDispatcherTest,
1068 ZeroClickWithAffiliatedFormInPasswordStore) {
1069 // Insert the affiliated form into the store, and mock out the association
1070 // with the current origin. As it's the only form matching the origin, it
1071 // ought to be returned automagically.
1072 store_->AddLogin(affiliated_form1_);
1073
1074 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
1075 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
1076
1077 std::vector<GURL> federations;
1078 std::vector<std::string> affiliated_realms;
1079 affiliated_realms.push_back(kTestAndroidRealm1);
1080 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
1081 ->ExpectCallToGetAffiliatedAndroidRealms(
1082 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
1083
1084 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
1085
1086 ExpectZeroClickSignInSuccess(CredentialType::CREDENTIAL_TYPE_PASSWORD);
1087 }
1088
1089 TEST_F(CredentialManagerDispatcherTest,
1090 ZeroClickWithTwoAffiliatedFormsInPasswordStore) {
1091 // Insert two affiliated forms into the store, and mock out the association
1092 // with the current origin. Multiple forms === no zero-click sign in.
1093 store_->AddLogin(affiliated_form1_);
1094 store_->AddLogin(affiliated_form2_);
1095
1096 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
1097 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
1098
1099 std::vector<GURL> federations;
1100 std::vector<std::string> affiliated_realms;
1101 affiliated_realms.push_back(kTestAndroidRealm1);
1102 affiliated_realms.push_back(kTestAndroidRealm2);
1103 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
1104 ->ExpectCallToGetAffiliatedAndroidRealms(
1105 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
1106
1107 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
1108
1109 ExpectZeroClickSignInFailure();
1110 }
1111
1112 TEST_F(CredentialManagerDispatcherTest,
1113 ZeroClickWithUnaffiliatedFormsInPasswordStore) {
1114 // Insert the affiliated form into the store, but don't mock out the
1115 // association with the current origin. No association === no zero-click sign
1116 // in.
1117 store_->AddLogin(affiliated_form1_);
1118
1119 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
1120 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
1121
1122 std::vector<GURL> federations;
1123 std::vector<std::string> affiliated_realms;
1124 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
1125 ->ExpectCallToGetAffiliatedAndroidRealms(
1126 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
1127
1128 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
1129
1130 ExpectZeroClickSignInFailure();
1131 }
1132
1133 TEST_F(CredentialManagerDispatcherTest,
1134 ZeroClickWithFormAndUnaffiliatedFormsInPasswordStore) {
1135 // Insert the affiliated form into the store, along with a real form for the
1136 // origin, and don't mock out the association with the current origin. No
1137 // association + existing form === zero-click sign in.
1138 store_->AddLogin(form_);
1139 store_->AddLogin(affiliated_form1_);
1140
1141 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
1142 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
1143
1144 std::vector<GURL> federations;
1145 std::vector<std::string> affiliated_realms;
1146 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
1147 ->ExpectCallToGetAffiliatedAndroidRealms(
1148 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
1149
1150 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
1151
1152 ExpectZeroClickSignInSuccess(CredentialType::CREDENTIAL_TYPE_PASSWORD);
1153 }
1154
1155 TEST_F(CredentialManagerDispatcherTest, GetSynthesizedFormForOrigin) {
1156 autofill::PasswordForm synthesized =
1157 dispatcher_->GetSynthesizedFormForOrigin();
1158 EXPECT_EQ(kTestWebOrigin, synthesized.origin.spec());
1159 EXPECT_EQ(kTestWebOrigin, synthesized.signon_realm);
1160 EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML, synthesized.scheme);
1161 EXPECT_TRUE(synthesized.ssl_valid);
1162 }
1163
1164 } // namespace password_manager
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698