Roll src/third_party/WebKit c63b89c:29324ab (svn 202546:202547)
[chromium-blink-merge.git] / components / password_manager / content / browser / credential_manager_dispatcher_unittest.cc
blobb96b5d71e89a8ab39358935f1d5f4f785c8c09c9
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/password_manager/content/browser/credential_manager_dispatcher.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/prefs/pref_registry_simple.h"
10 #include "base/prefs/testing_pref_service.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "components/password_manager/content/common/credential_manager_messages.h"
16 #include "components/password_manager/core/browser/credential_manager_password_form_manager.h"
17 #include "components/password_manager/core/browser/mock_affiliated_match_helper.h"
18 #include "components/password_manager/core/browser/stub_password_manager_client.h"
19 #include "components/password_manager/core/browser/stub_password_manager_driver.h"
20 #include "components/password_manager/core/browser/test_password_store.h"
21 #include "components/password_manager/core/common/credential_manager_types.h"
22 #include "components/password_manager/core/common/password_manager_pref_names.h"
23 #include "content/public/browser/web_contents.h"
24 #include "content/public/test/mock_render_process_host.h"
25 #include "content/public/test/test_renderer_host.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
29 using content::BrowserContext;
30 using content::WebContents;
32 using testing::_;
34 namespace {
36 // Chosen by fair dice roll. Guaranteed to be random.
37 const int kRequestId = 4;
39 const char kTestWebOrigin[] = "https://example.com/";
40 const char kTestAndroidRealm1[] = "android://hash@com.example.one.android/";
41 const char kTestAndroidRealm2[] = "android://hash@com.example.two.android/";
43 class MockPasswordManagerClient
44 : public password_manager::StubPasswordManagerClient {
45 public:
46 MOCK_CONST_METHOD0(IsSavingAndFillingEnabledForCurrentPage, bool());
47 MOCK_CONST_METHOD0(IsOffTheRecord, bool());
48 MOCK_CONST_METHOD0(DidLastPageLoadEncounterSSLErrors, bool());
49 MOCK_METHOD1(NotifyUserAutoSigninPtr,
50 bool(const std::vector<autofill::PasswordForm*>& local_forms));
51 MOCK_METHOD2(PromptUserToSavePasswordPtr,
52 void(password_manager::PasswordFormManager*,
53 password_manager::CredentialSourceType type));
54 MOCK_METHOD4(PromptUserToChooseCredentialsPtr,
55 bool(const std::vector<autofill::PasswordForm*>& local_forms,
56 const std::vector<autofill::PasswordForm*>& federated_forms,
57 const GURL& origin,
58 base::Callback<void(
59 const password_manager::CredentialInfo&)> callback));
61 MockPasswordManagerClient(password_manager::PasswordStore* store)
62 : store_(store) {
63 prefs_.registry()->RegisterBooleanPref(
64 password_manager::prefs::kPasswordManagerAutoSignin, true);
66 ~MockPasswordManagerClient() override {}
68 bool PromptUserToSaveOrUpdatePassword(
69 scoped_ptr<password_manager::PasswordFormManager> manager,
70 password_manager::CredentialSourceType type,
71 bool update_password) override {
72 manager_.swap(manager);
73 PromptUserToSavePasswordPtr(manager_.get(), type);
74 return true;
77 password_manager::PasswordStore* GetPasswordStore() const override {
78 return store_;
81 PrefService* GetPrefs() override { return &prefs_; }
83 bool PromptUserToChooseCredentials(
84 ScopedVector<autofill::PasswordForm> local_forms,
85 ScopedVector<autofill::PasswordForm> federated_forms,
86 const GURL& origin,
87 base::Callback<void(const password_manager::CredentialInfo&)> callback) {
88 EXPECT_FALSE(local_forms.empty() && federated_forms.empty());
89 password_manager::CredentialInfo info(
90 local_forms.empty() ? *federated_forms[0] : *local_forms[0],
91 local_forms.empty()
92 ? password_manager::CredentialType::CREDENTIAL_TYPE_FEDERATED
93 : password_manager::CredentialType::CREDENTIAL_TYPE_PASSWORD);
94 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
95 base::Bind(callback, info));
96 PromptUserToChooseCredentialsPtr(local_forms.get(), federated_forms.get(),
97 origin, callback);
98 return true;
101 void NotifyUserAutoSignin(
102 ScopedVector<autofill::PasswordForm> local_forms) override {
103 EXPECT_FALSE(local_forms.empty());
104 NotifyUserAutoSigninPtr(local_forms.get());
107 password_manager::PasswordFormManager* pending_manager() const {
108 return manager_.get();
111 void set_zero_click_enabled(bool zero_click_enabled) {
112 prefs_.SetBoolean(password_manager::prefs::kPasswordManagerAutoSignin,
113 zero_click_enabled);
116 private:
117 TestingPrefServiceSimple prefs_;
118 password_manager::PasswordStore* store_;
119 scoped_ptr<password_manager::PasswordFormManager> manager_;
121 DISALLOW_COPY_AND_ASSIGN(MockPasswordManagerClient);
124 class TestCredentialManagerDispatcher
125 : public password_manager::CredentialManagerDispatcher {
126 public:
127 TestCredentialManagerDispatcher(
128 content::WebContents* web_contents,
129 password_manager::PasswordManagerClient* client,
130 password_manager::PasswordManagerDriver* driver);
132 private:
133 base::WeakPtr<password_manager::PasswordManagerDriver> GetDriver() override;
135 base::WeakPtr<password_manager::PasswordManagerDriver> driver_;
138 TestCredentialManagerDispatcher::TestCredentialManagerDispatcher(
139 content::WebContents* web_contents,
140 password_manager::PasswordManagerClient* client,
141 password_manager::PasswordManagerDriver* driver)
142 : CredentialManagerDispatcher(web_contents, client),
143 driver_(driver->AsWeakPtr()) {
146 base::WeakPtr<password_manager::PasswordManagerDriver>
147 TestCredentialManagerDispatcher::GetDriver() {
148 return driver_;
151 void RunAllPendingTasks() {
152 base::RunLoop run_loop;
153 base::MessageLoop::current()->PostTask(
154 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
155 run_loop.Run();
158 } // namespace
160 namespace password_manager {
162 class CredentialManagerDispatcherTest
163 : public content::RenderViewHostTestHarness {
164 public:
165 CredentialManagerDispatcherTest() {}
167 void SetUp() override {
168 content::RenderViewHostTestHarness::SetUp();
169 store_ = new TestPasswordStore;
170 client_.reset(new MockPasswordManagerClient(store_.get()));
171 dispatcher_.reset(new TestCredentialManagerDispatcher(
172 web_contents(), client_.get(), &stub_driver_));
173 ON_CALL(*client_, IsSavingAndFillingEnabledForCurrentPage())
174 .WillByDefault(testing::Return(true));
175 ON_CALL(*client_, IsOffTheRecord()).WillByDefault(testing::Return(false));
176 ON_CALL(*client_, DidLastPageLoadEncounterSSLErrors())
177 .WillByDefault(testing::Return(false));
179 NavigateAndCommit(GURL("https://example.com/test.html"));
181 form_.username_value = base::ASCIIToUTF16("Username");
182 form_.display_name = base::ASCIIToUTF16("Display Name");
183 form_.password_value = base::ASCIIToUTF16("Password");
184 form_.origin = web_contents()->GetLastCommittedURL().GetOrigin();
185 form_.signon_realm = form_.origin.spec();
186 form_.scheme = autofill::PasswordForm::SCHEME_HTML;
187 form_.skip_zero_click = false;
188 form_.ssl_valid = true;
190 affiliated_form1_.username_value = base::ASCIIToUTF16("Affiliated 1");
191 affiliated_form1_.display_name = base::ASCIIToUTF16("Display Name");
192 affiliated_form1_.password_value = base::ASCIIToUTF16("Password");
193 affiliated_form1_.origin = GURL();
194 affiliated_form1_.signon_realm = kTestAndroidRealm1;
195 affiliated_form1_.scheme = autofill::PasswordForm::SCHEME_HTML;
196 affiliated_form1_.skip_zero_click = false;
197 affiliated_form1_.ssl_valid = true;
199 affiliated_form2_.username_value = base::ASCIIToUTF16("Affiliated 2");
200 affiliated_form2_.display_name = base::ASCIIToUTF16("Display Name");
201 affiliated_form2_.password_value = base::ASCIIToUTF16("Password");
202 affiliated_form2_.origin = GURL();
203 affiliated_form2_.signon_realm = kTestAndroidRealm2;
204 affiliated_form2_.scheme = autofill::PasswordForm::SCHEME_HTML;
205 affiliated_form2_.skip_zero_click = false;
206 affiliated_form2_.ssl_valid = true;
208 origin_path_form_.username_value = base::ASCIIToUTF16("Username 2");
209 origin_path_form_.display_name = base::ASCIIToUTF16("Display Name 2");
210 origin_path_form_.password_value = base::ASCIIToUTF16("Password 2");
211 origin_path_form_.origin = GURL("https://example.com/path");
212 origin_path_form_.signon_realm = origin_path_form_.origin.spec();
213 origin_path_form_.scheme = autofill::PasswordForm::SCHEME_HTML;
214 origin_path_form_.skip_zero_click = false;
216 cross_origin_form_.username_value = base::ASCIIToUTF16("Username");
217 cross_origin_form_.display_name = base::ASCIIToUTF16("Display Name");
218 cross_origin_form_.password_value = base::ASCIIToUTF16("Password");
219 cross_origin_form_.origin = GURL("https://example.net/");
220 cross_origin_form_.signon_realm = cross_origin_form_.origin.spec();
221 cross_origin_form_.scheme = autofill::PasswordForm::SCHEME_HTML;
222 cross_origin_form_.skip_zero_click = false;
224 store_->Clear();
225 EXPECT_TRUE(store_->IsEmpty());
228 void TearDown() override {
229 store_->Shutdown();
230 content::RenderViewHostTestHarness::TearDown();
233 void ExpectZeroClickSignInFailure() {
234 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
235 .Times(testing::Exactly(0));
236 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_))
237 .Times(testing::Exactly(0));
239 RunAllPendingTasks();
241 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
242 const IPC::Message* message =
243 process()->sink().GetFirstMessageMatching(kMsgID);
244 ASSERT_TRUE(message);
245 CredentialManagerMsg_SendCredential::Param send_param;
246 CredentialManagerMsg_SendCredential::Read(message, &send_param);
248 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY,
249 base::get<1>(send_param).type);
252 void ExpectZeroClickSignInSuccess() {
253 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
254 .Times(testing::Exactly(0));
255 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_))
256 .Times(testing::Exactly(1));
258 RunAllPendingTasks();
260 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
261 const IPC::Message* message =
262 process()->sink().GetFirstMessageMatching(kMsgID);
263 ASSERT_TRUE(message);
264 CredentialManagerMsg_SendCredential::Param send_param;
265 CredentialManagerMsg_SendCredential::Read(message, &send_param);
267 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_PASSWORD,
268 base::get<1>(send_param).type);
271 CredentialManagerDispatcher* dispatcher() { return dispatcher_.get(); }
273 protected:
274 autofill::PasswordForm form_;
275 autofill::PasswordForm affiliated_form1_;
276 autofill::PasswordForm affiliated_form2_;
277 autofill::PasswordForm origin_path_form_;
278 autofill::PasswordForm cross_origin_form_;
279 scoped_refptr<TestPasswordStore> store_;
280 scoped_ptr<MockPasswordManagerClient> client_;
281 StubPasswordManagerDriver stub_driver_;
282 scoped_ptr<CredentialManagerDispatcher> dispatcher_;
285 TEST_F(CredentialManagerDispatcherTest, CredentialManagerOnStore) {
286 CredentialInfo info(
287 form_, password_manager::CredentialType::CREDENTIAL_TYPE_PASSWORD);
288 EXPECT_CALL(
289 *client_,
290 PromptUserToSavePasswordPtr(
291 _, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API))
292 .Times(testing::Exactly(1));
294 dispatcher()->OnStore(kRequestId, info);
296 const uint32 kMsgID = CredentialManagerMsg_AcknowledgeStore::ID;
297 const IPC::Message* message =
298 process()->sink().GetFirstMessageMatching(kMsgID);
299 EXPECT_TRUE(message);
300 process()->sink().ClearMessages();
302 // Allow the PasswordFormManager to talk to the password store, determine
303 // that the form is new, and set it as pending.
304 RunAllPendingTasks();
306 EXPECT_TRUE(client_->pending_manager()->HasCompletedMatching());
308 autofill::PasswordForm new_form =
309 client_->pending_manager()->pending_credentials();
310 EXPECT_EQ(form_.username_value, new_form.username_value);
311 EXPECT_EQ(form_.display_name, new_form.display_name);
312 EXPECT_EQ(form_.password_value, new_form.password_value);
313 EXPECT_EQ(form_.origin, new_form.origin);
314 EXPECT_EQ(form_.signon_realm, new_form.signon_realm);
315 EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML, new_form.scheme);
318 TEST_F(CredentialManagerDispatcherTest,
319 CredentialManagerSignInWithSavingDisabledForCurrentPage) {
320 CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_PASSWORD);
321 EXPECT_CALL(*client_, IsSavingAndFillingEnabledForCurrentPage())
322 .WillRepeatedly(testing::Return(false));
323 EXPECT_CALL(
324 *client_,
325 PromptUserToSavePasswordPtr(
326 _, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API))
327 .Times(testing::Exactly(0));
329 dispatcher()->OnStore(kRequestId, info);
331 const uint32 kMsgID = CredentialManagerMsg_AcknowledgeStore::ID;
332 const IPC::Message* message =
333 process()->sink().GetFirstMessageMatching(kMsgID);
334 EXPECT_TRUE(message);
335 process()->sink().ClearMessages();
337 RunAllPendingTasks();
339 EXPECT_FALSE(client_->pending_manager());
342 TEST_F(CredentialManagerDispatcherTest,
343 CredentialManagerOnRequireUserMediation) {
344 store_->AddLogin(form_);
345 store_->AddLogin(cross_origin_form_);
346 RunAllPendingTasks();
348 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
349 EXPECT_EQ(2U, passwords.size());
350 EXPECT_EQ(1U, passwords[form_.signon_realm].size());
351 EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
352 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
353 EXPECT_FALSE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
355 dispatcher()->OnRequireUserMediation(kRequestId);
356 RunAllPendingTasks();
358 const uint32 kMsgID =
359 CredentialManagerMsg_AcknowledgeRequireUserMediation::ID;
360 const IPC::Message* message =
361 process()->sink().GetFirstMessageMatching(kMsgID);
362 EXPECT_TRUE(message);
363 process()->sink().ClearMessages();
365 passwords = store_->stored_passwords();
366 EXPECT_EQ(2U, passwords.size());
367 EXPECT_EQ(1U, passwords[form_.signon_realm].size());
368 EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
369 EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click);
370 EXPECT_FALSE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
373 TEST_F(CredentialManagerDispatcherTest,
374 CredentialManagerOnRequestCredentialWithEmptyPasswordStore) {
375 std::vector<GURL> federations;
376 EXPECT_CALL(
377 *client_,
378 PromptUserToSavePasswordPtr(
379 _, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API))
380 .Times(testing::Exactly(0));
381 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
382 .Times(testing::Exactly(0));
383 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
385 dispatcher()->OnRequestCredential(kRequestId, false, federations);
387 RunAllPendingTasks();
389 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
390 const IPC::Message* message =
391 process()->sink().GetFirstMessageMatching(kMsgID);
392 EXPECT_TRUE(message);
393 CredentialManagerMsg_SendCredential::Param param;
394 CredentialManagerMsg_SendCredential::Read(message, &param);
395 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, base::get<1>(param).type);
396 process()->sink().ClearMessages();
399 TEST_F(CredentialManagerDispatcherTest,
400 CredentialManagerOnRequestCredentialWithCrossOriginPasswordStore) {
401 store_->AddLogin(cross_origin_form_);
403 std::vector<GURL> federations;
404 EXPECT_CALL(
405 *client_,
406 PromptUserToSavePasswordPtr(
407 _, password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API))
408 .Times(testing::Exactly(0));
409 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
410 .Times(testing::Exactly(0));
411 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
413 dispatcher()->OnRequestCredential(kRequestId, false, federations);
415 RunAllPendingTasks();
417 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
418 const IPC::Message* message =
419 process()->sink().GetFirstMessageMatching(kMsgID);
420 EXPECT_TRUE(message);
421 CredentialManagerMsg_SendCredential::Param param;
422 CredentialManagerMsg_SendCredential::Read(message, &param);
423 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, base::get<1>(param).type);
424 process()->sink().ClearMessages();
427 TEST_F(CredentialManagerDispatcherTest,
428 CredentialManagerOnRequestCredentialWithFullPasswordStore) {
429 client_->set_zero_click_enabled(false);
430 store_->AddLogin(form_);
432 std::vector<GURL> federations;
433 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
434 .Times(testing::Exactly(1));
435 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
437 dispatcher()->OnRequestCredential(kRequestId, false, federations);
439 RunAllPendingTasks();
441 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
442 const IPC::Message* message =
443 process()->sink().GetFirstMessageMatching(kMsgID);
444 EXPECT_TRUE(message);
447 TEST_F(
448 CredentialManagerDispatcherTest,
449 CredentialManagerOnRequestCredentialWithZeroClickOnlyEmptyPasswordStore) {
450 std::vector<GURL> federations;
451 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
452 .Times(testing::Exactly(0));
453 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
455 dispatcher()->OnRequestCredential(kRequestId, true, federations);
457 RunAllPendingTasks();
459 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
460 const IPC::Message* message =
461 process()->sink().GetFirstMessageMatching(kMsgID);
462 EXPECT_TRUE(message);
463 CredentialManagerMsg_SendCredential::Param send_param;
464 CredentialManagerMsg_SendCredential::Read(message, &send_param);
465 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY,
466 base::get<1>(send_param).type);
469 TEST_F(CredentialManagerDispatcherTest,
470 CredentialManagerOnRequestCredentialWithZeroClickOnlyFullPasswordStore) {
471 store_->AddLogin(form_);
473 std::vector<GURL> federations;
474 dispatcher()->OnRequestCredential(kRequestId, true, federations);
476 ExpectZeroClickSignInSuccess();
479 TEST_F(CredentialManagerDispatcherTest, RequestCredentialWithTLSErrors) {
480 // If we encounter TLS errors, we won't return credentials.
481 EXPECT_CALL(*client_, DidLastPageLoadEncounterSSLErrors())
482 .WillRepeatedly(testing::Return(true));
484 store_->AddLogin(form_);
486 std::vector<GURL> federations;
487 dispatcher()->OnRequestCredential(kRequestId, true, federations);
489 ExpectZeroClickSignInFailure();
492 TEST_F(CredentialManagerDispatcherTest,
493 CredentialManagerOnRequestCredentialWithZeroClickOnlyTwoPasswordStore) {
494 store_->AddLogin(form_);
495 store_->AddLogin(origin_path_form_);
497 std::vector<GURL> federations;
498 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
499 .Times(testing::Exactly(0));
500 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
502 dispatcher()->OnRequestCredential(kRequestId, true, federations);
504 RunAllPendingTasks();
506 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
507 const IPC::Message* message =
508 process()->sink().GetFirstMessageMatching(kMsgID);
509 EXPECT_TRUE(message);
510 CredentialManagerMsg_SendCredential::Param send_param;
511 CredentialManagerMsg_SendCredential::Read(message, &send_param);
513 // With two items in the password store, we shouldn't get credentials back.
514 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY,
515 base::get<1>(send_param).type);
518 TEST_F(CredentialManagerDispatcherTest,
519 OnRequestCredentialWithZeroClickOnlyAndSkipZeroClickPasswordStore) {
520 form_.skip_zero_click = true;
521 store_->AddLogin(form_);
522 store_->AddLogin(origin_path_form_);
524 std::vector<GURL> federations;
525 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
526 .Times(testing::Exactly(0));
527 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
529 dispatcher()->OnRequestCredential(kRequestId, true, federations);
531 RunAllPendingTasks();
533 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
534 const IPC::Message* message =
535 process()->sink().GetFirstMessageMatching(kMsgID);
536 EXPECT_TRUE(message);
537 CredentialManagerMsg_SendCredential::Param send_param;
538 CredentialManagerMsg_SendCredential::Read(message, &send_param);
540 // With two items in the password store, we shouldn't get credentials back,
541 // even though only one item has |skip_zero_click| set |false|.
542 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY,
543 base::get<1>(send_param).type);
546 TEST_F(CredentialManagerDispatcherTest,
547 OnRequestCredentialWithZeroClickOnlyCrossOriginPasswordStore) {
548 store_->AddLogin(cross_origin_form_);
550 form_.skip_zero_click = true;
551 store_->AddLogin(form_);
553 std::vector<GURL> federations;
554 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
555 .Times(testing::Exactly(0));
556 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
558 dispatcher()->OnRequestCredential(kRequestId, true, federations);
560 RunAllPendingTasks();
562 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
563 const IPC::Message* message =
564 process()->sink().GetFirstMessageMatching(kMsgID);
565 EXPECT_TRUE(message);
566 CredentialManagerMsg_SendCredential::Param send_param;
567 CredentialManagerMsg_SendCredential::Read(message, &send_param);
569 // We only have cross-origin zero-click credentials; they should not be
570 // returned.
571 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY,
572 base::get<1>(send_param).type);
575 TEST_F(CredentialManagerDispatcherTest,
576 CredentialManagerOnRequestCredentialWhileRequestPending) {
577 client_->set_zero_click_enabled(false);
578 store_->AddLogin(form_);
580 std::vector<GURL> federations;
581 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
582 .Times(testing::Exactly(0));
583 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
585 dispatcher()->OnRequestCredential(kRequestId, false, federations);
586 dispatcher()->OnRequestCredential(kRequestId, false, federations);
588 // Check that the second request triggered a rejection.
589 uint32 kMsgID = CredentialManagerMsg_RejectCredentialRequest::ID;
590 const IPC::Message* message =
591 process()->sink().GetFirstMessageMatching(kMsgID);
592 EXPECT_TRUE(message);
594 CredentialManagerMsg_RejectCredentialRequest::Param reject_param;
595 CredentialManagerMsg_RejectCredentialRequest::Read(message, &reject_param);
596 EXPECT_EQ(blink::WebCredentialManagerError::ErrorTypePendingRequest,
597 base::get<1>(reject_param));
598 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
599 .Times(testing::Exactly(1));
600 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
602 process()->sink().ClearMessages();
604 // Execute the PasswordStore asynchronousness.
605 RunAllPendingTasks();
607 // Check that the first request resolves.
608 kMsgID = CredentialManagerMsg_SendCredential::ID;
609 message = process()->sink().GetFirstMessageMatching(kMsgID);
610 EXPECT_TRUE(message);
611 CredentialManagerMsg_SendCredential::Param send_param;
612 CredentialManagerMsg_SendCredential::Read(message, &send_param);
613 EXPECT_NE(CredentialType::CREDENTIAL_TYPE_EMPTY,
614 base::get<1>(send_param).type);
615 process()->sink().ClearMessages();
618 TEST_F(CredentialManagerDispatcherTest, ResetSkipZeroClickAfterPrompt) {
619 // Turn on the global zero-click flag, and add two credentials in separate
620 // origins, both set to skip zero-click.
621 client_->set_zero_click_enabled(true);
622 form_.skip_zero_click = true;
623 store_->AddLogin(form_);
624 cross_origin_form_.skip_zero_click = true;
625 store_->AddLogin(cross_origin_form_);
627 // Execute the PasswordStore asynchronousness to ensure everything is
628 // written before proceeding.
629 RunAllPendingTasks();
631 // Sanity check.
632 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
633 EXPECT_EQ(2U, passwords.size());
634 EXPECT_EQ(1U, passwords[form_.signon_realm].size());
635 EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
636 EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click);
637 EXPECT_TRUE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
639 // Trigger a request which should return the credential found in |form_|, and
640 // wait for it to process.
641 std::vector<GURL> federations;
642 // Check that the form in the database has been updated. `OnRequestCredential`
643 // generates a call to prompt the user to choose a credential.
644 // MockPasswordManagerClient mocks a user choice, and when users choose a
645 // credential (and have the global zero-click flag enabled), we make sure that
646 // they'll be logged in again next time.
647 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
648 .Times(testing::Exactly(1));
649 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
651 dispatcher()->OnRequestCredential(kRequestId, false, federations);
652 RunAllPendingTasks();
654 passwords = store_->stored_passwords();
655 EXPECT_EQ(2U, passwords.size());
656 EXPECT_EQ(1U, passwords[form_.signon_realm].size());
657 EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
658 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
659 EXPECT_TRUE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
662 TEST_F(CredentialManagerDispatcherTest, IncognitoZeroClickRequestCredential) {
663 EXPECT_CALL(*client_, IsOffTheRecord()).WillRepeatedly(testing::Return(true));
664 store_->AddLogin(form_);
666 std::vector<GURL> federations;
667 EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _, _))
668 .Times(testing::Exactly(0));
669 EXPECT_CALL(*client_, NotifyUserAutoSigninPtr(_)).Times(testing::Exactly(0));
671 dispatcher()->OnRequestCredential(kRequestId, true, federations);
673 RunAllPendingTasks();
675 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
676 const IPC::Message* message =
677 process()->sink().GetFirstMessageMatching(kMsgID);
678 ASSERT_TRUE(message);
679 CredentialManagerMsg_SendCredential::Param param;
680 CredentialManagerMsg_SendCredential::Read(message, &param);
681 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, base::get<1>(param).type);
684 TEST_F(CredentialManagerDispatcherTest,
685 ZeroClickWithAffiliatedFormInPasswordStore) {
686 // Insert the affiliated form into the store, and mock out the association
687 // with the current origin. As it's the only form matching the origin, it
688 // ought to be returned automagically.
689 store_->AddLogin(affiliated_form1_);
691 MockAffiliatedMatchHelper* mock_helper = new MockAffiliatedMatchHelper;
692 store_->SetAffiliatedMatchHelper(make_scoped_ptr(mock_helper));
694 std::vector<GURL> federations;
695 std::vector<std::string> affiliated_realms;
696 affiliated_realms.push_back(kTestAndroidRealm1);
697 mock_helper->ExpectCallToGetAffiliatedAndroidRealms(
698 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
700 dispatcher()->OnRequestCredential(kRequestId, true, federations);
702 ExpectZeroClickSignInSuccess();
705 TEST_F(CredentialManagerDispatcherTest,
706 ZeroClickWithTwoAffiliatedFormsInPasswordStore) {
707 // Insert two affiliated forms into the store, and mock out the association
708 // with the current origin. Multiple forms === no zero-click sign in.
709 store_->AddLogin(affiliated_form1_);
710 store_->AddLogin(affiliated_form2_);
712 MockAffiliatedMatchHelper* mock_helper = new MockAffiliatedMatchHelper;
713 store_->SetAffiliatedMatchHelper(make_scoped_ptr(mock_helper));
715 std::vector<GURL> federations;
716 std::vector<std::string> affiliated_realms;
717 affiliated_realms.push_back(kTestAndroidRealm1);
718 affiliated_realms.push_back(kTestAndroidRealm2);
719 mock_helper->ExpectCallToGetAffiliatedAndroidRealms(
720 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
722 dispatcher()->OnRequestCredential(kRequestId, true, federations);
724 ExpectZeroClickSignInFailure();
727 TEST_F(CredentialManagerDispatcherTest,
728 ZeroClickWithUnaffiliatedFormsInPasswordStore) {
729 // Insert the affiliated form into the store, but don't mock out the
730 // association with the current origin. No association === no zero-click sign
731 // in.
732 store_->AddLogin(affiliated_form1_);
734 MockAffiliatedMatchHelper* mock_helper = new MockAffiliatedMatchHelper;
735 store_->SetAffiliatedMatchHelper(make_scoped_ptr(mock_helper));
737 std::vector<GURL> federations;
738 std::vector<std::string> affiliated_realms;
739 mock_helper->ExpectCallToGetAffiliatedAndroidRealms(
740 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
742 dispatcher()->OnRequestCredential(kRequestId, true, federations);
744 ExpectZeroClickSignInFailure();
747 TEST_F(CredentialManagerDispatcherTest,
748 ZeroClickWithFormAndUnaffiliatedFormsInPasswordStore) {
749 // Insert the affiliated form into the store, along with a real form for the
750 // origin, and don't mock out the association with the current origin. No
751 // association + existing form === zero-click sign in.
752 store_->AddLogin(form_);
753 store_->AddLogin(affiliated_form1_);
755 MockAffiliatedMatchHelper* mock_helper = new MockAffiliatedMatchHelper;
756 store_->SetAffiliatedMatchHelper(make_scoped_ptr(mock_helper));
758 std::vector<GURL> federations;
759 std::vector<std::string> affiliated_realms;
760 mock_helper->ExpectCallToGetAffiliatedAndroidRealms(
761 dispatcher_->GetSynthesizedFormForOrigin(), affiliated_realms);
763 dispatcher()->OnRequestCredential(kRequestId, true, federations);
765 ExpectZeroClickSignInSuccess();
768 TEST_F(CredentialManagerDispatcherTest, GetSynthesizedFormForOrigin) {
769 autofill::PasswordForm synthesized =
770 dispatcher_->GetSynthesizedFormForOrigin();
771 EXPECT_EQ(kTestWebOrigin, synthesized.origin.spec());
772 EXPECT_EQ(kTestWebOrigin, synthesized.signon_realm);
773 EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML, synthesized.scheme);
774 EXPECT_TRUE(synthesized.ssl_valid);
777 } // namespace password_manager