OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <vector> | 5 #include <vector> |
6 | 6 |
7 #include "base/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
10 #include "chrome/browser/password_manager/mock_password_store.h" | 10 #include "chrome/browser/password_manager/mock_password_store.h" |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 } | 94 } |
95 | 95 |
96 PasswordForm MakeSimpleForm() { | 96 PasswordForm MakeSimpleForm() { |
97 PasswordForm form; | 97 PasswordForm form; |
98 form.origin = GURL("http://www.google.com/a/LoginAuth"); | 98 form.origin = GURL("http://www.google.com/a/LoginAuth"); |
99 form.action = GURL("http://www.google.com/a/Login"); | 99 form.action = GURL("http://www.google.com/a/Login"); |
100 form.username_element = ASCIIToUTF16("Email"); | 100 form.username_element = ASCIIToUTF16("Email"); |
101 form.password_element = ASCIIToUTF16("Passwd"); | 101 form.password_element = ASCIIToUTF16("Passwd"); |
102 form.username_value = ASCIIToUTF16("google"); | 102 form.username_value = ASCIIToUTF16("google"); |
103 form.password_value = ASCIIToUTF16("password"); | 103 form.password_value = ASCIIToUTF16("password"); |
104 // Default to true so we only need to add tests in autocomplete=off cases. | |
105 form.password_autocomplete_set = true; | |
106 form.submit_element = ASCIIToUTF16("signIn"); | 104 form.submit_element = ASCIIToUTF16("signIn"); |
107 form.signon_realm = "http://www.google.com"; | 105 form.signon_realm = "http://www.google.com"; |
108 return form; | 106 return form; |
109 } | 107 } |
110 | 108 |
111 // Reproduction of the form present on twitter's login page. | 109 // Reproduction of the form present on twitter's login page. |
112 PasswordForm MakeTwitterLoginForm() { | 110 PasswordForm MakeTwitterLoginForm() { |
113 PasswordForm form; | 111 PasswordForm form; |
114 form.origin = GURL("https://twitter.com/"); | 112 form.origin = GURL("https://twitter.com/"); |
115 form.action = GURL("https://twitter.com/sessions"); | 113 form.action = GURL("https://twitter.com/sessions"); |
116 form.username_element = ASCIIToUTF16("Email"); | 114 form.username_element = ASCIIToUTF16("Email"); |
117 form.password_element = ASCIIToUTF16("Passwd"); | 115 form.password_element = ASCIIToUTF16("Passwd"); |
118 form.username_value = ASCIIToUTF16("twitter"); | 116 form.username_value = ASCIIToUTF16("twitter"); |
119 form.password_value = ASCIIToUTF16("password"); | 117 form.password_value = ASCIIToUTF16("password"); |
120 form.password_autocomplete_set = true; | |
121 form.submit_element = ASCIIToUTF16("signIn"); | 118 form.submit_element = ASCIIToUTF16("signIn"); |
122 form.signon_realm = "https://twitter.com"; | 119 form.signon_realm = "https://twitter.com"; |
123 return form; | 120 return form; |
124 } | 121 } |
125 | 122 |
126 // Reproduction of the form present on twitter's failed login page. | 123 // Reproduction of the form present on twitter's failed login page. |
127 PasswordForm MakeTwitterFailedLoginForm() { | 124 PasswordForm MakeTwitterFailedLoginForm() { |
128 PasswordForm form; | 125 PasswordForm form; |
129 form.origin = | 126 form.origin = |
130 GURL("https://twitter.com/login/error?redirect_after_login"); | 127 GURL("https://twitter.com/login/error?redirect_after_login"); |
131 form.action = GURL("https://twitter.com/sessions"); | 128 form.action = GURL("https://twitter.com/sessions"); |
132 form.username_element = ASCIIToUTF16("EmailField"); | 129 form.username_element = ASCIIToUTF16("EmailField"); |
133 form.password_element = ASCIIToUTF16("PasswdField"); | 130 form.password_element = ASCIIToUTF16("PasswdField"); |
134 form.username_value = ASCIIToUTF16("twitter"); | 131 form.username_value = ASCIIToUTF16("twitter"); |
135 form.password_value = ASCIIToUTF16("password"); | 132 form.password_value = ASCIIToUTF16("password"); |
136 form.password_autocomplete_set = true; | |
137 form.submit_element = ASCIIToUTF16("signIn"); | 133 form.submit_element = ASCIIToUTF16("signIn"); |
138 form.signon_realm = "https://twitter.com"; | 134 form.signon_realm = "https://twitter.com"; |
139 return form; | 135 return form; |
140 } | 136 } |
141 | 137 |
142 bool FormsAreEqual(const autofill::PasswordForm& lhs, | 138 bool FormsAreEqual(const autofill::PasswordForm& lhs, |
143 const autofill::PasswordForm& rhs) { | 139 const autofill::PasswordForm& rhs) { |
144 if (lhs.origin != rhs.origin) | 140 if (lhs.origin != rhs.origin) |
145 return false; | 141 return false; |
146 if (lhs.action != rhs.action) | 142 if (lhs.action != rhs.action) |
147 return false; | 143 return false; |
148 if (lhs.username_element != rhs.username_element) | 144 if (lhs.username_element != rhs.username_element) |
149 return false; | 145 return false; |
150 if (lhs.password_element != rhs.password_element) | 146 if (lhs.password_element != rhs.password_element) |
151 return false; | 147 return false; |
152 if (lhs.username_value != rhs.username_value) | 148 if (lhs.username_value != rhs.username_value) |
153 return false; | 149 return false; |
154 if (lhs.password_value != rhs.password_value) | 150 if (lhs.password_value != rhs.password_value) |
155 return false; | 151 return false; |
156 if (lhs.password_autocomplete_set != rhs.password_autocomplete_set) | |
157 return false; | |
158 if (lhs.submit_element != rhs.submit_element) | 152 if (lhs.submit_element != rhs.submit_element) |
159 return false; | 153 return false; |
160 if (lhs.signon_realm != rhs.signon_realm) | 154 if (lhs.signon_realm != rhs.signon_realm) |
161 return false; | 155 return false; |
162 return true; | 156 return true; |
163 } | 157 } |
164 | 158 |
165 TestPasswordManager* manager() { | 159 TestPasswordManager* manager() { |
166 return manager_; | 160 return manager_; |
167 } | 161 } |
(...skipping 16 matching lines...) Expand all Loading... |
184 MockPasswordManagerDelegate delegate_; // Owned by manager_. | 178 MockPasswordManagerDelegate delegate_; // Owned by manager_. |
185 PasswordForm submitted_form_; | 179 PasswordForm submitted_form_; |
186 }; | 180 }; |
187 | 181 |
188 MATCHER_P(FormMatches, form, "") { | 182 MATCHER_P(FormMatches, form, "") { |
189 return form.signon_realm == arg.signon_realm && | 183 return form.signon_realm == arg.signon_realm && |
190 form.origin == arg.origin && | 184 form.origin == arg.origin && |
191 form.action == arg.action && | 185 form.action == arg.action && |
192 form.username_element == arg.username_element && | 186 form.username_element == arg.username_element && |
193 form.password_element == arg.password_element && | 187 form.password_element == arg.password_element && |
194 form.password_autocomplete_set == | |
195 arg.password_autocomplete_set && | |
196 form.submit_element == arg.submit_element; | 188 form.submit_element == arg.submit_element; |
197 } | 189 } |
198 | 190 |
199 TEST_F(PasswordManagerTest, FormSubmitEmptyStore) { | 191 TEST_F(PasswordManagerTest, FormSubmitEmptyStore) { |
200 // Test that observing a newly submitted form shows the save password bar. | 192 // Test that observing a newly submitted form shows the save password bar. |
201 std::vector<PasswordForm*> result; // Empty password store. | 193 std::vector<PasswordForm*> result; // Empty password store. |
202 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0)); | 194 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0)); |
203 EXPECT_CALL(*store_.get(), GetLogins(_, _)) | 195 EXPECT_CALL(*store_.get(), GetLogins(_, _)) |
204 .WillOnce(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1))); | 196 .WillOnce(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1))); |
205 std::vector<PasswordForm> observed; | 197 std::vector<PasswordForm> observed; |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 Value::CreateBooleanValue(false)); | 487 Value::CreateBooleanValue(false)); |
496 EXPECT_CALL(delegate_, FillPasswordForm(_)); | 488 EXPECT_CALL(delegate_, FillPasswordForm(_)); |
497 EXPECT_CALL(*store_.get(), GetLogins(_, _)) | 489 EXPECT_CALL(*store_.get(), GetLogins(_, _)) |
498 .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1))); | 490 .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1))); |
499 std::vector<PasswordForm> observed; | 491 std::vector<PasswordForm> observed; |
500 PasswordForm form(MakeSimpleForm()); | 492 PasswordForm form(MakeSimpleForm()); |
501 observed.push_back(form); | 493 observed.push_back(form); |
502 manager()->OnPasswordFormsParsed(observed); | 494 manager()->OnPasswordFormsParsed(observed); |
503 } | 495 } |
504 | 496 |
505 TEST_F(PasswordManagerTest, FormNotSavedAutocompleteOff) { | |
506 // Test password form with non-generated password will not be saved if | |
507 // autocomplete=off. | |
508 std::vector<PasswordForm*> result; // Empty password store. | |
509 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0)); | |
510 EXPECT_CALL(*store_.get(), GetLogins(_, _)) | |
511 .WillOnce(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1))); | |
512 std::vector<PasswordForm> observed; | |
513 PasswordForm form(MakeSimpleForm()); | |
514 form.password_autocomplete_set = false; | |
515 observed.push_back(form); | |
516 manager()->OnPasswordFormsParsed(observed); // The initial load. | |
517 manager()->OnPasswordFormsRendered(observed); // The initial layout. | |
518 | |
519 // And the form submit contract is to call ProvisionallySavePassword. | |
520 manager()->ProvisionallySavePassword(form); | |
521 | |
522 // Password form should not be saved. | |
523 EXPECT_CALL(delegate_, | |
524 AddSavePasswordInfoBarIfPermitted(_)).Times(Exactly(0)); | |
525 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))).Times(Exactly(0)); | |
526 | |
527 // Now the password manager waits for the navigation to complete. | |
528 observed.clear(); | |
529 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. | |
530 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. | |
531 } | |
532 | |
533 TEST_F(PasswordManagerTest, GeneratedPasswordFormSavedAutocompleteOff) { | |
534 // Test password form with generated password will still be saved if | |
535 // autocomplete=off. | |
536 std::vector<PasswordForm*> result; // Empty password store. | |
537 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0)); | |
538 EXPECT_CALL(*store_.get(), GetLogins(_, _)) | |
539 .WillOnce(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1))); | |
540 std::vector<PasswordForm> observed; | |
541 PasswordForm form(MakeSimpleForm()); | |
542 form.password_autocomplete_set = false; | |
543 observed.push_back(form); | |
544 manager()->OnPasswordFormsParsed(observed); // The initial load. | |
545 manager()->OnPasswordFormsRendered(observed); // The initial layout. | |
546 | |
547 // Simulate the user generating the password and submitting the form. | |
548 manager()->SetFormHasGeneratedPassword(form); | |
549 manager()->ProvisionallySavePassword(form); | |
550 | |
551 // The user should not be presented with an infobar as they have already given | |
552 // consent by using the generated password. The form should be saved once | |
553 // navigation occurs. | |
554 EXPECT_CALL(delegate_, | |
555 AddSavePasswordInfoBarIfPermitted(_)).Times(Exactly(0)); | |
556 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))); | |
557 | |
558 // Now the password manager waits for the navigation to complete. | |
559 observed.clear(); | |
560 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. | |
561 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. | |
562 } | |
563 | |
564 TEST_F(PasswordManagerTest, SubmissionCallbackTest) { | 497 TEST_F(PasswordManagerTest, SubmissionCallbackTest) { |
565 manager()->AddSubmissionCallback(SubmissionCallback()); | 498 manager()->AddSubmissionCallback(SubmissionCallback()); |
566 PasswordForm form = MakeSimpleForm(); | 499 PasswordForm form = MakeSimpleForm(); |
567 OnPasswordFormSubmitted(form); | 500 OnPasswordFormSubmitted(form); |
568 EXPECT_TRUE(FormsAreEqual(form, submitted_form_)); | 501 EXPECT_TRUE(FormsAreEqual(form, submitted_form_)); |
569 } | 502 } |
570 | 503 |
571 TEST_F(PasswordManagerTest, PasswordFormReappearance) { | 504 TEST_F(PasswordManagerTest, PasswordFormReappearance) { |
572 // Test the heuristic to know if a password form reappears. | 505 // Test the heuristic to know if a password form reappears. |
573 // We assume that if we send our credentials and there | 506 // We assume that if we send our credentials and there |
(...skipping 12 matching lines...) Expand all Loading... |
586 manager()->ProvisionallySavePassword(login_form); | 519 manager()->ProvisionallySavePassword(login_form); |
587 | 520 |
588 PasswordForm failed_login_form(MakeTwitterFailedLoginForm()); | 521 PasswordForm failed_login_form(MakeTwitterFailedLoginForm()); |
589 observed.clear(); | 522 observed.clear(); |
590 observed.push_back(failed_login_form); | 523 observed.push_back(failed_login_form); |
591 // A PasswordForm appears, and is visible in the layout: | 524 // A PasswordForm appears, and is visible in the layout: |
592 // No expected calls to the PasswordStore... | 525 // No expected calls to the PasswordStore... |
593 manager()->OnPasswordFormsParsed(observed); | 526 manager()->OnPasswordFormsParsed(observed); |
594 manager()->OnPasswordFormsRendered(observed); | 527 manager()->OnPasswordFormsRendered(observed); |
595 } | 528 } |
OLD | NEW |