GetLoginsRequest: Use ScopedVector to express ownership of forms
[chromium-blink-merge.git] / components / password_manager / content / browser / credential_manager_dispatcher_unittest.cc
bloba6512024d8122cbd783b22ed986cf3d009a6525b
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 "components/password_manager/content/browser/credential_manager_password_form_manager.h"
15 #include "components/password_manager/content/common/credential_manager_messages.h"
16 #include "components/password_manager/content/common/credential_manager_types.h"
17 #include "components/password_manager/core/browser/stub_password_manager_client.h"
18 #include "components/password_manager/core/browser/stub_password_manager_driver.h"
19 #include "components/password_manager/core/browser/test_password_store.h"
20 #include "components/password_manager/core/common/password_manager_pref_names.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/test/mock_render_process_host.h"
23 #include "content/public/test/test_renderer_host.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 using content::BrowserContext;
28 using content::WebContents;
30 namespace {
32 // Chosen by fair dice roll. Guaranteed to be random.
33 const int kRequestId = 4;
35 class TestPasswordManagerClient
36 : public password_manager::StubPasswordManagerClient {
37 public:
38 TestPasswordManagerClient(password_manager::PasswordStore* store)
39 : did_prompt_user_to_save_(false),
40 did_prompt_user_to_choose_(false),
41 is_off_the_record_(false),
42 store_(store) {
43 prefs_.registry()->RegisterBooleanPref(
44 password_manager::prefs::kPasswordManagerAutoSignin, true);
46 ~TestPasswordManagerClient() override {}
48 password_manager::PasswordStore* GetPasswordStore() override {
49 return store_;
52 PrefService* GetPrefs() override { return &prefs_; }
54 bool PromptUserToSavePassword(
55 scoped_ptr<password_manager::PasswordFormManager> manager) override {
56 did_prompt_user_to_save_ = true;
57 manager_.reset(manager.release());
58 return true;
61 bool PromptUserToChooseCredentials(
62 ScopedVector<autofill::PasswordForm> local_forms,
63 ScopedVector<autofill::PasswordForm> federated_forms,
64 base::Callback<void(const password_manager::CredentialInfo&)> callback)
65 override {
66 EXPECT_FALSE(local_forms.empty() && federated_forms.empty());
67 did_prompt_user_to_choose_ = true;
68 password_manager::CredentialInfo info(
69 local_forms.empty() ? *federated_forms[0] : *local_forms[0],
70 local_forms.empty()
71 ? password_manager::CredentialType::CREDENTIAL_TYPE_FEDERATED
72 : password_manager::CredentialType::CREDENTIAL_TYPE_LOCAL);
73 base::MessageLoop::current()->PostTask(FROM_HERE,
74 base::Bind(callback, info));
75 return true;
78 bool IsOffTheRecord() override { return is_off_the_record_; }
80 bool did_prompt_user_to_save() const { return did_prompt_user_to_save_; }
81 bool did_prompt_user_to_choose() const { return did_prompt_user_to_choose_; }
83 password_manager::PasswordFormManager* pending_manager() const {
84 return manager_.get();
87 void set_off_the_record(bool off_the_record) {
88 is_off_the_record_ = off_the_record;
91 void set_zero_click_enabled(bool zero_click_enabled) {
92 prefs_.SetBoolean(password_manager::prefs::kPasswordManagerAutoSignin,
93 zero_click_enabled);
96 private:
97 TestingPrefServiceSimple prefs_;
98 bool did_prompt_user_to_save_;
99 bool did_prompt_user_to_choose_;
100 bool is_off_the_record_;
101 password_manager::PasswordStore* store_;
102 scoped_ptr<password_manager::PasswordFormManager> manager_;
105 class TestCredentialManagerDispatcher
106 : public password_manager::CredentialManagerDispatcher {
107 public:
108 TestCredentialManagerDispatcher(
109 content::WebContents* web_contents,
110 password_manager::PasswordManagerClient* client,
111 password_manager::PasswordManagerDriver* driver);
113 private:
114 base::WeakPtr<password_manager::PasswordManagerDriver> GetDriver() override;
116 base::WeakPtr<password_manager::PasswordManagerDriver> driver_;
119 TestCredentialManagerDispatcher::TestCredentialManagerDispatcher(
120 content::WebContents* web_contents,
121 password_manager::PasswordManagerClient* client,
122 password_manager::PasswordManagerDriver* driver)
123 : CredentialManagerDispatcher(web_contents, client),
124 driver_(driver->AsWeakPtr()) {
127 base::WeakPtr<password_manager::PasswordManagerDriver>
128 TestCredentialManagerDispatcher::GetDriver() {
129 return driver_;
132 void RunAllPendingTasks() {
133 base::RunLoop run_loop;
134 base::MessageLoop::current()->PostTask(
135 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
136 run_loop.Run();
139 } // namespace
141 namespace password_manager {
143 class CredentialManagerDispatcherTest
144 : public content::RenderViewHostTestHarness {
145 public:
146 CredentialManagerDispatcherTest() {}
148 void SetUp() override {
149 content::RenderViewHostTestHarness::SetUp();
150 store_ = new TestPasswordStore;
151 client_.reset(new TestPasswordManagerClient(store_.get()));
152 dispatcher_.reset(new TestCredentialManagerDispatcher(
153 web_contents(), client_.get(), &stub_driver_));
155 NavigateAndCommit(GURL("https://example.com/test.html"));
157 form_.username_value = base::ASCIIToUTF16("Username");
158 form_.display_name = base::ASCIIToUTF16("Display Name");
159 form_.password_value = base::ASCIIToUTF16("Password");
160 form_.origin = web_contents()->GetLastCommittedURL().GetOrigin();
161 form_.signon_realm = form_.origin.spec();
162 form_.scheme = autofill::PasswordForm::SCHEME_HTML;
163 form_.skip_zero_click = false;
165 form2_.username_value = base::ASCIIToUTF16("Username 2");
166 form2_.display_name = base::ASCIIToUTF16("Display Name 2");
167 form2_.password_value = base::ASCIIToUTF16("Password 2");
168 form2_.origin = web_contents()->GetLastCommittedURL().GetOrigin();
169 form2_.signon_realm = form2_.origin.spec();
170 form2_.scheme = autofill::PasswordForm::SCHEME_HTML;
171 form2_.skip_zero_click = false;
173 cross_origin_form_.username_value = base::ASCIIToUTF16("Username");
174 cross_origin_form_.display_name = base::ASCIIToUTF16("Display Name");
175 cross_origin_form_.password_value = base::ASCIIToUTF16("Password");
176 cross_origin_form_.origin = GURL("https://example.net/");
177 cross_origin_form_.signon_realm = cross_origin_form_.origin.spec();
178 cross_origin_form_.scheme = autofill::PasswordForm::SCHEME_HTML;
179 cross_origin_form_.skip_zero_click = false;
181 store_->Clear();
182 EXPECT_TRUE(store_->IsEmpty());
185 void TearDown() override {
186 store_->Shutdown();
187 content::RenderViewHostTestHarness::TearDown();
190 CredentialManagerDispatcher* dispatcher() { return dispatcher_.get(); }
192 protected:
193 autofill::PasswordForm form_;
194 autofill::PasswordForm form2_;
195 autofill::PasswordForm cross_origin_form_;
196 scoped_refptr<TestPasswordStore> store_;
197 scoped_ptr<TestPasswordManagerClient> client_;
198 StubPasswordManagerDriver stub_driver_;
199 scoped_ptr<CredentialManagerDispatcher> dispatcher_;
202 TEST_F(CredentialManagerDispatcherTest, CredentialManagerOnNotifyFailedSignIn) {
203 CredentialInfo info;
204 info.type = CredentialType::CREDENTIAL_TYPE_LOCAL;
205 dispatcher()->OnNotifyFailedSignIn(kRequestId, info);
207 const uint32 kMsgID = CredentialManagerMsg_AcknowledgeFailedSignIn::ID;
208 const IPC::Message* message =
209 process()->sink().GetFirstMessageMatching(kMsgID);
210 EXPECT_TRUE(message);
211 process()->sink().ClearMessages();
214 TEST_F(CredentialManagerDispatcherTest, CredentialManagerOnNotifySignedIn) {
215 CredentialInfo info(form_,
216 password_manager::CredentialType::CREDENTIAL_TYPE_LOCAL);
217 dispatcher()->OnNotifySignedIn(kRequestId, info);
219 const uint32 kMsgID = CredentialManagerMsg_AcknowledgeSignedIn::ID;
220 const IPC::Message* message =
221 process()->sink().GetFirstMessageMatching(kMsgID);
222 EXPECT_TRUE(message);
223 process()->sink().ClearMessages();
225 // Allow the PasswordFormManager to talk to the password store, determine
226 // that the form is new, and set it as pending.
227 RunAllPendingTasks();
229 EXPECT_TRUE(client_->did_prompt_user_to_save());
230 EXPECT_TRUE(client_->pending_manager()->HasCompletedMatching());
232 autofill::PasswordForm new_form =
233 client_->pending_manager()->pending_credentials();
234 EXPECT_EQ(form_.username_value, new_form.username_value);
235 EXPECT_EQ(form_.display_name, new_form.display_name);
236 EXPECT_EQ(form_.password_value, new_form.password_value);
237 EXPECT_EQ(form_.origin, new_form.origin);
238 EXPECT_EQ(form_.signon_realm, new_form.signon_realm);
239 EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML, new_form.scheme);
242 TEST_F(CredentialManagerDispatcherTest, CredentialManagerIncognitoSignedIn) {
243 CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_LOCAL);
244 client_->set_off_the_record(true);
245 dispatcher()->OnNotifySignedIn(kRequestId, info);
247 const uint32 kMsgID = CredentialManagerMsg_AcknowledgeSignedIn::ID;
248 const IPC::Message* message =
249 process()->sink().GetFirstMessageMatching(kMsgID);
250 EXPECT_TRUE(message);
251 process()->sink().ClearMessages();
253 RunAllPendingTasks();
255 EXPECT_FALSE(client_->did_prompt_user_to_save());
256 EXPECT_FALSE(client_->pending_manager());
259 TEST_F(CredentialManagerDispatcherTest, CredentialManagerOnNotifySignedOut) {
260 store_->AddLogin(form_);
261 store_->AddLogin(cross_origin_form_);
262 RunAllPendingTasks();
264 TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
265 EXPECT_EQ(2U, passwords.size());
266 EXPECT_EQ(1U, passwords[form_.signon_realm].size());
267 EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
268 EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
269 EXPECT_FALSE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
271 dispatcher()->OnNotifySignedOut(kRequestId);
272 RunAllPendingTasks();
274 const uint32 kMsgID = CredentialManagerMsg_AcknowledgeSignedOut::ID;
275 const IPC::Message* message =
276 process()->sink().GetFirstMessageMatching(kMsgID);
277 EXPECT_TRUE(message);
278 process()->sink().ClearMessages();
280 passwords = store_->stored_passwords();
281 EXPECT_EQ(2U, passwords.size());
282 EXPECT_EQ(1U, passwords[form_.signon_realm].size());
283 EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
284 EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click);
285 EXPECT_FALSE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
288 TEST_F(CredentialManagerDispatcherTest,
289 CredentialManagerOnRequestCredentialWithEmptyPasswordStore) {
290 std::vector<GURL> federations;
291 dispatcher()->OnRequestCredential(kRequestId, false, federations);
293 RunAllPendingTasks();
295 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
296 const IPC::Message* message =
297 process()->sink().GetFirstMessageMatching(kMsgID);
298 EXPECT_TRUE(message);
299 CredentialManagerMsg_SendCredential::Param param;
300 CredentialManagerMsg_SendCredential::Read(message, &param);
301 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, get<1>(param).type);
302 process()->sink().ClearMessages();
303 EXPECT_FALSE(client_->did_prompt_user_to_choose());
306 TEST_F(CredentialManagerDispatcherTest,
307 CredentialManagerOnRequestCredentialWithCrossOriginPasswordStore) {
308 store_->AddLogin(cross_origin_form_);
310 std::vector<GURL> federations;
311 dispatcher()->OnRequestCredential(kRequestId, false, federations);
313 RunAllPendingTasks();
315 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
316 const IPC::Message* message =
317 process()->sink().GetFirstMessageMatching(kMsgID);
318 EXPECT_TRUE(message);
319 CredentialManagerMsg_SendCredential::Param param;
320 CredentialManagerMsg_SendCredential::Read(message, &param);
321 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, get<1>(param).type);
322 process()->sink().ClearMessages();
323 EXPECT_FALSE(client_->did_prompt_user_to_choose());
326 TEST_F(CredentialManagerDispatcherTest,
327 CredentialManagerOnRequestCredentialWithFullPasswordStore) {
328 client_->set_zero_click_enabled(false);
329 store_->AddLogin(form_);
331 std::vector<GURL> federations;
332 dispatcher()->OnRequestCredential(kRequestId, false, federations);
334 RunAllPendingTasks();
336 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
337 const IPC::Message* message =
338 process()->sink().GetFirstMessageMatching(kMsgID);
339 EXPECT_TRUE(message);
340 EXPECT_TRUE(client_->did_prompt_user_to_choose());
343 TEST_F(
344 CredentialManagerDispatcherTest,
345 CredentialManagerOnRequestCredentialWithZeroClickOnlyEmptyPasswordStore) {
346 std::vector<GURL> federations;
347 dispatcher()->OnRequestCredential(kRequestId, true, federations);
349 RunAllPendingTasks();
351 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
352 const IPC::Message* message =
353 process()->sink().GetFirstMessageMatching(kMsgID);
354 EXPECT_TRUE(message);
355 EXPECT_FALSE(client_->did_prompt_user_to_choose());
356 CredentialManagerMsg_SendCredential::Param send_param;
357 CredentialManagerMsg_SendCredential::Read(message, &send_param);
358 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, get<1>(send_param).type);
361 TEST_F(CredentialManagerDispatcherTest,
362 CredentialManagerOnRequestCredentialWithZeroClickOnlyFullPasswordStore) {
363 store_->AddLogin(form_);
365 std::vector<GURL> federations;
366 dispatcher()->OnRequestCredential(kRequestId, true, federations);
368 RunAllPendingTasks();
370 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
371 const IPC::Message* message =
372 process()->sink().GetFirstMessageMatching(kMsgID);
373 EXPECT_TRUE(message);
374 EXPECT_FALSE(client_->did_prompt_user_to_choose());
375 CredentialManagerMsg_SendCredential::Param send_param;
376 CredentialManagerMsg_SendCredential::Read(message, &send_param);
377 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_LOCAL, get<1>(send_param).type);
380 TEST_F(CredentialManagerDispatcherTest,
381 CredentialManagerOnRequestCredentialWithZeroClickOnlyTwoPasswordStore) {
382 store_->AddLogin(form_);
383 store_->AddLogin(form2_);
385 std::vector<GURL> federations;
386 dispatcher()->OnRequestCredential(kRequestId, true, federations);
388 RunAllPendingTasks();
390 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
391 const IPC::Message* message =
392 process()->sink().GetFirstMessageMatching(kMsgID);
393 EXPECT_TRUE(message);
394 EXPECT_FALSE(client_->did_prompt_user_to_choose());
395 CredentialManagerMsg_SendCredential::Param send_param;
396 CredentialManagerMsg_SendCredential::Read(message, &send_param);
398 // With two items in the password store, we shouldn't get credentials back.
399 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, get<1>(send_param).type);
402 TEST_F(CredentialManagerDispatcherTest,
403 OnRequestCredentialWithZeroClickOnlyOnePasswordStore) {
404 form_.skip_zero_click = true;
405 store_->AddLogin(form_);
406 store_->AddLogin(form2_);
408 std::vector<GURL> federations;
409 dispatcher()->OnRequestCredential(kRequestId, true, federations);
411 RunAllPendingTasks();
413 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
414 const IPC::Message* message =
415 process()->sink().GetFirstMessageMatching(kMsgID);
416 EXPECT_TRUE(message);
417 EXPECT_FALSE(client_->did_prompt_user_to_choose());
418 CredentialManagerMsg_SendCredential::Param send_param;
419 CredentialManagerMsg_SendCredential::Read(message, &send_param);
421 // We should get |form2_| back, as |form_| is marked as skipping zero-click.
422 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_LOCAL, get<1>(send_param).type);
423 EXPECT_EQ(form2_.username_value, get<1>(send_param).id);
424 EXPECT_EQ(form2_.display_name, get<1>(send_param).name);
425 EXPECT_EQ(form2_.password_value, get<1>(send_param).password);
428 TEST_F(CredentialManagerDispatcherTest,
429 OnRequestCredentialWithZeroClickOnlyCrossOriginPasswordStore) {
430 store_->AddLogin(cross_origin_form_);
432 form_.skip_zero_click = true;
433 store_->AddLogin(form_);
435 std::vector<GURL> federations;
436 dispatcher()->OnRequestCredential(kRequestId, true, federations);
438 RunAllPendingTasks();
440 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
441 const IPC::Message* message =
442 process()->sink().GetFirstMessageMatching(kMsgID);
443 EXPECT_TRUE(message);
444 EXPECT_FALSE(client_->did_prompt_user_to_choose());
445 CredentialManagerMsg_SendCredential::Param send_param;
446 CredentialManagerMsg_SendCredential::Read(message, &send_param);
448 // We only have cross-origin zero-click credentials; they should not be
449 // returned.
450 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, get<1>(send_param).type);
453 TEST_F(CredentialManagerDispatcherTest,
454 CredentialManagerOnRequestCredentialWhileRequestPending) {
455 client_->set_zero_click_enabled(false);
456 store_->AddLogin(form_);
458 std::vector<GURL> federations;
459 dispatcher()->OnRequestCredential(kRequestId, false, federations);
460 dispatcher()->OnRequestCredential(kRequestId, false, federations);
462 // Check that the second request triggered a rejection.
463 uint32 kMsgID = CredentialManagerMsg_RejectCredentialRequest::ID;
464 const IPC::Message* message =
465 process()->sink().GetFirstMessageMatching(kMsgID);
466 EXPECT_TRUE(message);
467 CredentialManagerMsg_RejectCredentialRequest::Param reject_param;
468 CredentialManagerMsg_RejectCredentialRequest::Read(message, &reject_param);
469 EXPECT_EQ(blink::WebCredentialManagerError::ErrorTypePendingRequest,
470 get<1>(reject_param));
471 EXPECT_FALSE(client_->did_prompt_user_to_choose());
473 process()->sink().ClearMessages();
475 // Execute the PasswordStore asynchronousness.
476 RunAllPendingTasks();
478 // Check that the first request resolves.
479 kMsgID = CredentialManagerMsg_SendCredential::ID;
480 message = process()->sink().GetFirstMessageMatching(kMsgID);
481 EXPECT_TRUE(message);
482 CredentialManagerMsg_SendCredential::Param send_param;
483 CredentialManagerMsg_SendCredential::Read(message, &send_param);
484 EXPECT_NE(CredentialType::CREDENTIAL_TYPE_EMPTY, get<1>(send_param).type);
485 process()->sink().ClearMessages();
486 EXPECT_TRUE(client_->did_prompt_user_to_choose());
489 TEST_F(CredentialManagerDispatcherTest, IncognitoRequestCredential) {
490 client_->set_off_the_record(true);
491 store_->AddLogin(form_);
493 std::vector<GURL> federations;
494 dispatcher()->OnRequestCredential(kRequestId, true, federations);
496 RunAllPendingTasks();
498 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
499 const IPC::Message* message =
500 process()->sink().GetFirstMessageMatching(kMsgID);
501 ASSERT_TRUE(message);
502 CredentialManagerMsg_SendCredential::Param param;
503 CredentialManagerMsg_SendCredential::Read(message, &param);
504 EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, get<1>(param).type);
505 EXPECT_FALSE(client_->did_prompt_user_to_choose());
508 } // namespace password_manager