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

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

Issue 1872133002: Revert of Reland: Switch components/password_manager code from IPC messages to Mojo. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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 client_->set_first_run_seen(true);
396 form_.skip_zero_click = true;
397 store_->AddLogin(form_);
398 RunAllPendingTasks();
399
400 // Calling 'OnStore' with a credential that matches |form_| should update
401 // the credential without prompting the user.
402 CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_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 toggled the skip_zero_click flag off.
411 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
412 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
413 }
414
415 TEST_F(CredentialManagerDispatcherTest,
416 CredentialManagerFederatedStoreOverwriteZeroClick) {
417 // Set the global zero click flag on, and populate the PasswordStore with a
418 // form that's set to skip zero click.
419 client_->set_zero_click_enabled(true);
420 client_->set_first_run_seen(true);
421 form_.federation_origin = url::Origin(GURL("https://example.com/"));
422 form_.skip_zero_click = true;
423 form_.signon_realm = "federation://example.com/example.com";
424 store_->AddLogin(form_);
425 RunAllPendingTasks();
426
427 // Calling 'OnStore' with a credential that matches |form_| should update
428 // the credential without prompting the user.
429 CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_FEDERATED);
430 dispatcher()->OnStore(kRequestId, info);
431 process()->sink().ClearMessages();
432
433 // Allow the PasswordFormManager to talk to the password store, determine
434 // the form is a match for an existing form, and update the PasswordStore.
435 RunAllPendingTasks();
436
437 // Verify that the update toggled the skip_zero_click flag off.
438 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
439 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
440 }
441
442 TEST_F(CredentialManagerDispatcherTest,
443 CredentialManagerGetOverwriteZeroClick) {
444 // Set the global zero click flag on, and populate the PasswordStore with a
445 // form that's set to skip zero click and has a primary key that won't match
446 // credentials initially created via `store()`.
447 client_->set_zero_click_enabled(true);
448 form_.skip_zero_click = true;
449 form_.username_element = base::ASCIIToUTF16("username-element");
450 form_.password_element = base::ASCIIToUTF16("password-element");
451 form_.signon_realm = "this is a realm";
452 form_.origin = GURL("https://example.com/old_form.html");
453 store_->AddLogin(form_);
454 RunAllPendingTasks();
455
456 std::vector<GURL> federations;
457 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
458 .Times(testing::Exactly(1));
459 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
460
461 dispatcher()->OnRequestCredential(kRequestId, false, true, federations);
462
463 RunAllPendingTasks();
464
465 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
466 const IPC::Message* message =
467 process()->sink().GetFirstMessageMatching(kMsgID);
468 EXPECT_TRUE(message);
469
470 // Verify that the update toggled the skip_zero_click flag.
471 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
472 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
473 }
474
475 TEST_F(CredentialManagerDispatcherTest,
476 CredentialManagerSignInWithSavingDisabledForCurrentPage) {
477 CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_PASSWORD);
478 EXPECT_CALL(*client_, IsSavingAndFillingEnabledForCurrentPage())
479 .WillRepeatedly(testing::Return(false));
480 EXPECT_CALL(*client_, PromptUserToSavePasswordPtr(
481 _, CredentialSourceType::CREDENTIAL_SOURCE_API))
482 .Times(testing::Exactly(0));
483
484 dispatcher()->OnStore(kRequestId, info);
485
486 const uint32_t kMsgID = CredentialManagerMsg_AcknowledgeStore::ID;
487 const IPC::Message* message =
488 process()->sink().GetFirstMessageMatching(kMsgID);
489 EXPECT_TRUE(message);
490 process()->sink().ClearMessages();
491
492 RunAllPendingTasks();
493
494 EXPECT_FALSE(client_->pending_manager());
495 }
496
497 TEST_F(CredentialManagerDispatcherTest,
498 CredentialManagerOnRequireUserMediation) {
499 store_->AddLogin(form_);
500 store_->AddLogin(cross_origin_form_);
501 RunAllPendingTasks();
502
503 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
504 EXPECT_EQ(2U, passwords.size());
505 EXPECT_EQ(1U, passwords[form_.signon_realm].size());
506 EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
507 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
508 EXPECT_FALSE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
509
510 dispatcher()->OnRequireUserMediation(kRequestId);
511 RunAllPendingTasks();
512
513 const uint32_t kMsgID =
514 CredentialManagerMsg_AcknowledgeRequireUserMediation::ID;
515 const IPC::Message* message =
516 process()->sink().GetFirstMessageMatching(kMsgID);
517 EXPECT_TRUE(message);
518 process()->sink().ClearMessages();
519
520 passwords = store_->stored_passwords();
521 EXPECT_EQ(2U, passwords.size());
522 EXPECT_EQ(1U, passwords[form_.signon_realm].size());
523 EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
524 EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click);
525 EXPECT_FALSE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
526 }
527
528 TEST_F(CredentialManagerDispatcherTest,
529 CredentialManagerOnRequireUserMediationIncognito) {
530 EXPECT_CALL(*client_, IsOffTheRecord()).WillRepeatedly(testing::Return(true));
531 store_->AddLogin(form_);
532 RunAllPendingTasks();
533
534 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
535 ASSERT_EQ(1U, passwords.size());
536 ASSERT_EQ(1U, passwords[form_.signon_realm].size());
537 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
538
539 dispatcher()->OnRequireUserMediation(kRequestId);
540 RunAllPendingTasks();
541
542 const uint32_t kMsgID =
543 CredentialManagerMsg_AcknowledgeRequireUserMediation::ID;
544 const IPC::Message* message =
545 process()->sink().GetFirstMessageMatching(kMsgID);
546 EXPECT_TRUE(message);
547 process()->sink().ClearMessages();
548
549 passwords = store_->stored_passwords();
550 ASSERT_EQ(1U, passwords.size());
551 ASSERT_EQ(1U, passwords[form_.signon_realm].size());
552 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
553 }
554
555 TEST_F(CredentialManagerDispatcherTest,
556 CredentialManagerOnRequireUserMediationWithAffiliation) {
557 store_->AddLogin(form_);
558 store_->AddLogin(cross_origin_form_);
559 store_->AddLogin(affiliated_form1_);
560 store_->AddLogin(affiliated_form2_);
561
562 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
563 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
564
565 std::vector<GURL> federations;
566 std::vector<std::string> affiliated_realms;
567 affiliated_realms.push_back(kTestAndroidRealm1);
568 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
569 ->ExpectCallToGetAffiliatedAndroidRealms(
570 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
571 RunAllPendingTasks();
572
573 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
574 EXPECT_EQ(4U, passwords.size());
575 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
576 EXPECT_FALSE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
577 EXPECT_FALSE(passwords[affiliated_form1_.signon_realm][0].skip_zero_click);
578 EXPECT_FALSE(passwords[affiliated_form2_.signon_realm][0].skip_zero_click);
579
580 dispatcher()->OnRequireUserMediation(kRequestId);
581 RunAllPendingTasks();
582 process()->sink().ClearMessages();
583
584 passwords = store_->stored_passwords();
585 EXPECT_EQ(4U, passwords.size());
586 EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click);
587 EXPECT_FALSE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
588 EXPECT_TRUE(passwords[affiliated_form1_.signon_realm][0].skip_zero_click);
589 EXPECT_FALSE(passwords[affiliated_form2_.signon_realm][0].skip_zero_click);
590 }
591
592 TEST_F(CredentialManagerDispatcherTest,
593 CredentialManagerOnRequestCredentialWithEmptyPasswordStore) {
594 std::vector<GURL> federations;
595 EXPECT_CALL(*client_, PromptUserToSavePasswordPtr(
596 _, CredentialSourceType::CREDENTIAL_SOURCE_API))
597 .Times(testing::Exactly(0));
598 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
599 .Times(testing::Exactly(0));
600 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
601
602 dispatcher()->OnRequestCredential(kRequestId, false, true, federations);
603
604 RunAllPendingTasks();
605
606 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
607 const IPC::Message* message =
608 process()->sink().GetFirstMessageMatching(kMsgID);
609 EXPECT_TRUE(message);
610 CredentialManagerMsg_SendCredential::Param param;
611 CredentialManagerMsg_SendCredential::Read(message, &param);
612 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, std::get<1>(param).type);
613 process()->sink().ClearMessages();
614 }
615
616 TEST_F(CredentialManagerDispatcherTest,
617 CredentialManagerOnRequestCredentialWithCrossOriginPasswordStore) {
618 store_->AddLogin(cross_origin_form_);
619
620 std::vector<GURL> federations;
621 EXPECT_CALL(*client_, PromptUserToSavePasswordPtr(
622 _, CredentialSourceType::CREDENTIAL_SOURCE_API))
623 .Times(testing::Exactly(0));
624 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
625 .Times(testing::Exactly(0));
626 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
627
628 dispatcher()->OnRequestCredential(kRequestId, false, true, federations);
629
630 RunAllPendingTasks();
631
632 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
633 const IPC::Message* message =
634 process()->sink().GetFirstMessageMatching(kMsgID);
635 EXPECT_TRUE(message);
636 CredentialManagerMsg_SendCredential::Param param;
637 CredentialManagerMsg_SendCredential::Read(message, &param);
638 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, std::get<1>(param).type);
639 process()->sink().ClearMessages();
640 }
641
642 TEST_F(CredentialManagerDispatcherTest,
643 CredentialManagerOnRequestCredentialWithFullPasswordStore) {
644 client_->set_zero_click_enabled(false);
645 store_->AddLogin(form_);
646
647 std::vector<GURL> federations;
648 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
649 .Times(testing::Exactly(1));
650 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
651
652 dispatcher()->OnRequestCredential(kRequestId, false, true, federations);
653
654 RunAllPendingTasks();
655
656 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
657 const IPC::Message* message =
658 process()->sink().GetFirstMessageMatching(kMsgID);
659 EXPECT_TRUE(message);
660 }
661
662 TEST_F(
663 CredentialManagerDispatcherTest,
664 CredentialManagerOnRequestCredentialWithZeroClickOnlyEmptyPasswordStore) {
665 std::vector<GURL> federations;
666 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
667 .Times(testing::Exactly(0));
668 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
669
670 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
671
672 RunAllPendingTasks();
673
674 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
675 const IPC::Message* message =
676 process()->sink().GetFirstMessageMatching(kMsgID);
677 EXPECT_TRUE(message);
678 CredentialManagerMsg_SendCredential::Param send_param;
679 CredentialManagerMsg_SendCredential::Read(message, &send_param);
680 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY,
681 std::get<1>(send_param).type);
682 }
683
684 TEST_F(CredentialManagerDispatcherTest,
685 CredentialManagerOnRequestCredentialWithZeroClickOnlyFullPasswordStore) {
686 store_->AddLogin(form_);
687 client_->set_first_run_seen(true);
688
689 std::vector<GURL> federations;
690
691 EXPECT_CALL(*client_, NotifyUserCouldBeAutoSignedInPtr(_)).Times(0);
692 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
693
694 ExpectZeroClickSignInSuccess(CredentialType::CREDENTIAL_TYPE_PASSWORD);
695 }
696
697 TEST_F(CredentialManagerDispatcherTest,
698 CredentialManagerOnRequestCredentialWithoutPasswords) {
699 store_->AddLogin(form_);
700 client_->set_first_run_seen(true);
701
702 std::vector<GURL> federations;
703
704 EXPECT_CALL(*client_, NotifyUserCouldBeAutoSignedInPtr(_)).Times(0);
705 dispatcher()->OnRequestCredential(kRequestId, true, false, federations);
706
707 ExpectZeroClickSignInFailure();
708 }
709
710 TEST_F(CredentialManagerDispatcherTest,
711 CredentialManagerOnRequestCredentialFederatedMatch) {
712 form_.federation_origin = url::Origin(GURL("https://example.com/"));
713 store_->AddLogin(form_);
714 client_->set_first_run_seen(true);
715
716 std::vector<GURL> federations;
717 federations.push_back(GURL("https://example.com/"));
718
719 EXPECT_CALL(*client_, NotifyUserCouldBeAutoSignedInPtr(_)).Times(0);
720 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
721
722 ExpectZeroClickSignInSuccess(CredentialType::CREDENTIAL_TYPE_FEDERATED);
723 }
724
725 TEST_F(CredentialManagerDispatcherTest,
726 CredentialManagerOnRequestCredentialFederatedNoMatch) {
727 form_.federation_origin = url::Origin(GURL("https://example.com/"));
728 store_->AddLogin(form_);
729 client_->set_first_run_seen(true);
730
731 std::vector<GURL> federations;
732 federations.push_back(GURL("https://not-example.com/"));
733
734 EXPECT_CALL(*client_, NotifyUserCouldBeAutoSignedInPtr(_)).Times(0);
735 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
736
737 ExpectZeroClickSignInFailure();
738 }
739
740 TEST_F(CredentialManagerDispatcherTest,
741 CredentialManagerOnRequestCredentialAffiliatedPasswordMatch) {
742 store_->AddLogin(affiliated_form1_);
743 client_->set_first_run_seen(true);
744 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
745 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
746
747 std::vector<GURL> federations;
748 std::vector<std::string> affiliated_realms;
749 affiliated_realms.push_back(kTestAndroidRealm1);
750 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
751 ->ExpectCallToGetAffiliatedAndroidRealms(
752 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
753
754 // We pass in 'true' for the 'include_passwords' argument to ensure that
755 // password-type credentials are included as potential matches.
756 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
757
758 ExpectZeroClickSignInSuccess(CredentialType::CREDENTIAL_TYPE_PASSWORD);
759 }
760
761 TEST_F(CredentialManagerDispatcherTest,
762 CredentialManagerOnRequestCredentialAffiliatedPasswordNoMatch) {
763 store_->AddLogin(affiliated_form1_);
764 client_->set_first_run_seen(true);
765 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
766 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
767
768 std::vector<GURL> federations;
769 std::vector<std::string> affiliated_realms;
770 affiliated_realms.push_back(kTestAndroidRealm1);
771 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
772 ->ExpectCallToGetAffiliatedAndroidRealms(
773 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
774
775 // We pass in 'false' for the 'include_passwords' argument to ensure that
776 // password-type credentials are excluded as potential matches.
777 dispatcher()->OnRequestCredential(kRequestId, true, false, federations);
778
779 ExpectZeroClickSignInFailure();
780 }
781
782 TEST_F(CredentialManagerDispatcherTest,
783 CredentialManagerOnRequestCredentialAffiliatedFederatedMatch) {
784 affiliated_form1_.federation_origin =
785 url::Origin(GURL("https://example.com/"));
786 store_->AddLogin(affiliated_form1_);
787 client_->set_first_run_seen(true);
788 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
789 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
790
791 std::vector<GURL> federations;
792 federations.push_back(GURL("https://example.com/"));
793
794 std::vector<std::string> affiliated_realms;
795 affiliated_realms.push_back(kTestAndroidRealm1);
796 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
797 ->ExpectCallToGetAffiliatedAndroidRealms(
798 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
799
800 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
801
802 ExpectZeroClickSignInSuccess(CredentialType::CREDENTIAL_TYPE_FEDERATED);
803 }
804
805 TEST_F(CredentialManagerDispatcherTest,
806 CredentialManagerOnRequestCredentialAffiliatedFederatedNoMatch) {
807 affiliated_form1_.federation_origin =
808 url::Origin(GURL("https://example.com/"));
809 store_->AddLogin(affiliated_form1_);
810 client_->set_first_run_seen(true);
811 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
812 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
813
814 std::vector<GURL> federations;
815 federations.push_back(GURL("https://not-example.com/"));
816
817 std::vector<std::string> affiliated_realms;
818 affiliated_realms.push_back(kTestAndroidRealm1);
819 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
820 ->ExpectCallToGetAffiliatedAndroidRealms(
821 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
822
823 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
824
825 ExpectZeroClickSignInFailure();
826 }
827
828 TEST_F(CredentialManagerDispatcherTest, RequestCredentialWithoutFirstRun) {
829 client_->set_first_run_seen(false);
830
831 store_->AddLogin(form_);
832
833 std::vector<GURL> federations;
834 EXPECT_CALL(*client_,
835 NotifyUserCouldBeAutoSignedInPtr(testing::Pointee(form_)))
836 .Times(1);
837 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
838
839 ExpectZeroClickSignInFailure();
840 }
841
842 TEST_F(CredentialManagerDispatcherTest, RequestCredentialWithFirstRunAndSkip) {
843 client_->set_first_run_seen(true);
844
845 form_.skip_zero_click = true;
846 store_->AddLogin(form_);
847
848 std::vector<GURL> federations;
849 EXPECT_CALL(*client_,
850 NotifyUserCouldBeAutoSignedInPtr(testing::Pointee(form_)))
851 .Times(1);
852 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
853
854 ExpectZeroClickSignInFailure();
855 }
856
857 TEST_F(CredentialManagerDispatcherTest, RequestCredentialWithTLSErrors) {
858 // If we encounter TLS errors, we won't return credentials.
859 EXPECT_CALL(*client_, DidLastPageLoadEncounterSSLErrors())
860 .WillRepeatedly(testing::Return(true));
861
862 store_->AddLogin(form_);
863
864 std::vector<GURL> federations;
865 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
866
867 ExpectZeroClickSignInFailure();
868 }
869
870 TEST_F(CredentialManagerDispatcherTest,
871 CredentialManagerOnRequestCredentialWithZeroClickOnlyTwoPasswordStore) {
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 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY,
893 std::get<1>(send_param).type);
894 }
895
896 TEST_F(CredentialManagerDispatcherTest,
897 OnRequestCredentialWithZeroClickOnlyAndSkipZeroClickPasswordStore) {
898 form_.skip_zero_click = true;
899 store_->AddLogin(form_);
900 store_->AddLogin(origin_path_form_);
901
902 std::vector<GURL> federations;
903 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
904 .Times(testing::Exactly(0));
905 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
906
907 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
908
909 RunAllPendingTasks();
910
911 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
912 const IPC::Message* message =
913 process()->sink().GetFirstMessageMatching(kMsgID);
914 EXPECT_TRUE(message);
915 CredentialManagerMsg_SendCredential::Param send_param;
916 CredentialManagerMsg_SendCredential::Read(message, &send_param);
917
918 // With two items in the password store, we shouldn't get credentials back,
919 // even though only one item has |skip_zero_click| set |false|.
920 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY,
921 std::get<1>(send_param).type);
922 }
923
924 TEST_F(CredentialManagerDispatcherTest,
925 OnRequestCredentialWithZeroClickOnlyCrossOriginPasswordStore) {
926 store_->AddLogin(cross_origin_form_);
927
928 form_.skip_zero_click = true;
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, true, true, federations);
937
938 RunAllPendingTasks();
939
940 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
941 const IPC::Message* message =
942 process()->sink().GetFirstMessageMatching(kMsgID);
943 EXPECT_TRUE(message);
944 CredentialManagerMsg_SendCredential::Param send_param;
945 CredentialManagerMsg_SendCredential::Read(message, &send_param);
946
947 // We only have cross-origin zero-click credentials; they should not be
948 // returned.
949 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY,
950 std::get<1>(send_param).type);
951 }
952
953 TEST_F(CredentialManagerDispatcherTest,
954 CredentialManagerOnRequestCredentialWhileRequestPending) {
955 client_->set_zero_click_enabled(false);
956 store_->AddLogin(form_);
957
958 std::vector<GURL> federations;
959 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
960 .Times(testing::Exactly(0));
961 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
962
963 dispatcher()->OnRequestCredential(kRequestId, false, true, federations);
964 dispatcher()->OnRequestCredential(kRequestId + 1, false, true, federations);
965
966 // Check that the second request triggered a rejection.
967 uint32_t kMsgID = CredentialManagerMsg_RejectCredentialRequest::ID;
968 const IPC::Message* message =
969 process()->sink().GetFirstMessageMatching(kMsgID);
970 EXPECT_TRUE(message);
971
972 CredentialManagerMsg_RejectCredentialRequest::Param reject_param;
973 CredentialManagerMsg_RejectCredentialRequest::Read(message, &reject_param);
974 EXPECT_EQ(blink::WebCredentialManagerPendingRequestError,
975 std::get<1>(reject_param));
976 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
977 .Times(testing::Exactly(1));
978 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
979
980 process()->sink().ClearMessages();
981
982 // Execute the PasswordStore asynchronousness.
983 RunAllPendingTasks();
984
985 // Check that the first request resolves.
986 kMsgID = CredentialManagerMsg_SendCredential::ID;
987 message = process()->sink().GetFirstMessageMatching(kMsgID);
988 EXPECT_TRUE(message);
989 CredentialManagerMsg_SendCredential::Param send_param;
990 CredentialManagerMsg_SendCredential::Read(message, &send_param);
991 EXPECT_NE(CredentialType::CREDENTIAL_TYPE_EMPTY,
992 std::get<1>(send_param).type);
993 process()->sink().ClearMessages();
994 }
995
996 TEST_F(CredentialManagerDispatcherTest, ResetSkipZeroClickAfterPrompt) {
997 // Turn on the global zero-click flag, and add two credentials in separate
998 // origins, both set to skip zero-click.
999 client_->set_zero_click_enabled(true);
1000 form_.skip_zero_click = true;
1001 store_->AddLogin(form_);
1002 cross_origin_form_.skip_zero_click = true;
1003 store_->AddLogin(cross_origin_form_);
1004
1005 // Execute the PasswordStore asynchronousness to ensure everything is
1006 // written before proceeding.
1007 RunAllPendingTasks();
1008
1009 // Sanity check.
1010 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
1011 EXPECT_EQ(2U, passwords.size());
1012 EXPECT_EQ(1U, passwords[form_.signon_realm].size());
1013 EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
1014 EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click);
1015 EXPECT_TRUE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
1016
1017 // Trigger a request which should return the credential found in |form_|, and
1018 // wait for it to process.
1019 std::vector<GURL> federations;
1020 // Check that the form in the database has been updated. `OnRequestCredential`
1021 // generates a call to prompt the user to choose a credential.
1022 // MockPasswordManagerClient mocks a user choice, and when users choose a
1023 // credential (and have the global zero-click flag enabled), we make sure that
1024 // they'll be logged in again next time.
1025 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
1026 .Times(testing::Exactly(1));
1027 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
1028
1029 dispatcher()->OnRequestCredential(kRequestId, false, true, federations);
1030 RunAllPendingTasks();
1031
1032 passwords = store_->stored_passwords();
1033 EXPECT_EQ(2U, passwords.size());
1034 EXPECT_EQ(1U, passwords[form_.signon_realm].size());
1035 EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
1036 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
1037 EXPECT_TRUE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
1038 }
1039
1040 TEST_F(CredentialManagerDispatcherTest,
1041 NoResetSkipZeroClickAfterPromptInIncognito) {
1042 EXPECT_CALL(*client_, IsOffTheRecord()).WillRepeatedly(testing::Return(true));
1043 // Turn on the global zero-click flag which should be overriden by Incognito.
1044 client_->set_zero_click_enabled(true);
1045 form_.skip_zero_click = true;
1046 store_->AddLogin(form_);
1047 RunAllPendingTasks();
1048
1049 // Sanity check.
1050 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
1051 ASSERT_EQ(1U, passwords.size());
1052 ASSERT_EQ(1U, passwords[form_.signon_realm].size());
1053 EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click);
1054
1055 // Trigger a request which should return the credential found in |form_|, and
1056 // wait for it to process.
1057 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
1058 .Times(testing::Exactly(1));
1059 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
1060
1061 dispatcher()->OnRequestCredential(kRequestId, false, true,
1062 std::vector<GURL>());
1063 RunAllPendingTasks();
1064
1065 // The form shouldn't become a zero-click one.
1066 passwords = store_->stored_passwords();
1067 ASSERT_EQ(1U, passwords.size());
1068 ASSERT_EQ(1U, passwords[form_.signon_realm].size());
1069 EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click);
1070 }
1071
1072 TEST_F(CredentialManagerDispatcherTest, IncognitoZeroClickRequestCredential) {
1073 EXPECT_CALL(*client_, IsOffTheRecord()).WillRepeatedly(testing::Return(true));
1074 store_->AddLogin(form_);
1075
1076 std::vector<GURL> federations;
1077 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
1078 .Times(testing::Exactly(0));
1079 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
1080
1081 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
1082
1083 RunAllPendingTasks();
1084
1085 const uint32_t kMsgID = CredentialManagerMsg_SendCredential::ID;
1086 const IPC::Message* message =
1087 process()->sink().GetFirstMessageMatching(kMsgID);
1088 ASSERT_TRUE(message);
1089 CredentialManagerMsg_SendCredential::Param param;
1090 CredentialManagerMsg_SendCredential::Read(message, &param);
1091 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, std::get<1>(param).type);
1092 }
1093
1094 TEST_F(CredentialManagerDispatcherTest,
1095 ZeroClickWithAffiliatedFormInPasswordStore) {
1096 // Insert the affiliated form into the store, and mock out the association
1097 // with the current origin. As it's the only form matching the origin, it
1098 // ought to be returned automagically.
1099 store_->AddLogin(affiliated_form1_);
1100
1101 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
1102 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
1103
1104 std::vector<GURL> federations;
1105 std::vector<std::string> affiliated_realms;
1106 affiliated_realms.push_back(kTestAndroidRealm1);
1107 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
1108 ->ExpectCallToGetAffiliatedAndroidRealms(
1109 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
1110
1111 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
1112
1113 ExpectZeroClickSignInSuccess(CredentialType::CREDENTIAL_TYPE_PASSWORD);
1114 }
1115
1116 TEST_F(CredentialManagerDispatcherTest,
1117 ZeroClickWithTwoAffiliatedFormsInPasswordStore) {
1118 // Insert two affiliated forms into the store, and mock out the association
1119 // with the current origin. Multiple forms === no zero-click sign in.
1120 store_->AddLogin(affiliated_form1_);
1121 store_->AddLogin(affiliated_form2_);
1122
1123 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
1124 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
1125
1126 std::vector<GURL> federations;
1127 std::vector<std::string> affiliated_realms;
1128 affiliated_realms.push_back(kTestAndroidRealm1);
1129 affiliated_realms.push_back(kTestAndroidRealm2);
1130 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
1131 ->ExpectCallToGetAffiliatedAndroidRealms(
1132 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
1133
1134 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
1135
1136 ExpectZeroClickSignInFailure();
1137 }
1138
1139 TEST_F(CredentialManagerDispatcherTest,
1140 ZeroClickWithUnaffiliatedFormsInPasswordStore) {
1141 // Insert the affiliated form into the store, but don't mock out the
1142 // association with the current origin. No association === no zero-click sign
1143 // in.
1144 store_->AddLogin(affiliated_form1_);
1145
1146 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
1147 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
1148
1149 std::vector<GURL> federations;
1150 std::vector<std::string> affiliated_realms;
1151 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
1152 ->ExpectCallToGetAffiliatedAndroidRealms(
1153 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
1154
1155 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
1156
1157 ExpectZeroClickSignInFailure();
1158 }
1159
1160 TEST_F(CredentialManagerDispatcherTest,
1161 ZeroClickWithFormAndUnaffiliatedFormsInPasswordStore) {
1162 // Insert the affiliated form into the store, along with a real form for the
1163 // origin, and don't mock out the association with the current origin. No
1164 // association + existing form === zero-click sign in.
1165 store_->AddLogin(form_);
1166 store_->AddLogin(affiliated_form1_);
1167
1168 auto mock_helper = base::WrapUnique(new MockAffiliatedMatchHelper);
1169 store_->SetAffiliatedMatchHelper(std::move(mock_helper));
1170
1171 std::vector<GURL> federations;
1172 std::vector<std::string> affiliated_realms;
1173 static_cast<MockAffiliatedMatchHelper*>(store_->affiliated_match_helper())
1174 ->ExpectCallToGetAffiliatedAndroidRealms(
1175 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
1176
1177 dispatcher()->OnRequestCredential(kRequestId, true, true, federations);
1178
1179 ExpectZeroClickSignInSuccess(CredentialType::CREDENTIAL_TYPE_PASSWORD);
1180 }
1181
1182 TEST_F(CredentialManagerDispatcherTest, GetSynthesizedFormForOrigin) {
1183 autofill::PasswordForm synthesized =
1184 dispatcher_->GetSynthesizedFormForOrigin();
1185 EXPECT_EQ(kTestWebOrigin, synthesized.origin.spec());
1186 EXPECT_EQ(kTestWebOrigin, synthesized.signon_realm);
1187 EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML, synthesized.scheme);
1188 EXPECT_TRUE(synthesized.ssl_valid);
1189 }
1190
1191 } // namespace password_manager
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698