| 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 12 matching lines...) Expand all Loading... |
| 23 #include "testing/gmock/include/gmock/gmock.h" | 23 #include "testing/gmock/include/gmock/gmock.h" |
| 24 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
| 25 | 25 |
| 26 using content::PasswordForm; | 26 using content::PasswordForm; |
| 27 using testing::_; | 27 using testing::_; |
| 28 using testing::DoAll; | 28 using testing::DoAll; |
| 29 using testing::Exactly; | 29 using testing::Exactly; |
| 30 using testing::Return; | 30 using testing::Return; |
| 31 using testing::WithArg; | 31 using testing::WithArg; |
| 32 | 32 |
| 33 namespace { |
| 34 |
| 33 class MockPasswordManagerDelegate : public PasswordManagerDelegate { | 35 class MockPasswordManagerDelegate : public PasswordManagerDelegate { |
| 34 public: | 36 public: |
| 35 MOCK_METHOD1(FillPasswordForm, void(const autofill::PasswordFormFillData&)); | 37 MOCK_METHOD1(FillPasswordForm, void(const autofill::PasswordFormFillData&)); |
| 36 MOCK_METHOD1(AddSavePasswordInfoBarIfPermitted, void(PasswordFormManager*)); | 38 MOCK_METHOD1(AddSavePasswordInfoBarIfPermitted, void(PasswordFormManager*)); |
| 37 MOCK_METHOD0(GetProfile, Profile*()); | 39 MOCK_METHOD0(GetProfile, Profile*()); |
| 38 MOCK_METHOD0(DidLastPageLoadEncounterSSLErrors, bool()); | 40 MOCK_METHOD0(DidLastPageLoadEncounterSSLErrors, bool()); |
| 39 }; | 41 }; |
| 40 | 42 |
| 41 ACTION_P(InvokeConsumer, forms) { | 43 ACTION_P(InvokeConsumer, forms) { |
| 42 arg0->OnGetPasswordStoreResults(forms); | 44 arg0->OnGetPasswordStoreResults(forms); |
| 43 } | 45 } |
| 44 | 46 |
| 45 ACTION_P(SaveToScopedPtr, scoped) { | 47 ACTION_P(SaveToScopedPtr, scoped) { |
| 46 scoped->reset(arg0); | 48 scoped->reset(arg0); |
| 47 } | 49 } |
| 48 | 50 |
| 51 class TestPasswordManager : public PasswordManager { |
| 52 public: |
| 53 TestPasswordManager(content::WebContents* contents, |
| 54 PasswordManagerDelegate* delegate) |
| 55 : PasswordManager(contents, delegate) {} |
| 56 virtual ~TestPasswordManager() {} |
| 57 |
| 58 virtual void OnPasswordFormSubmitted(const PasswordForm& form) OVERRIDE { |
| 59 PasswordManager::OnPasswordFormSubmitted(form); |
| 60 } |
| 61 |
| 62 static TestPasswordManager* CreateForWebContentsAndDelegate( |
| 63 content::WebContents* contents, |
| 64 PasswordManagerDelegate* delegate) { |
| 65 TestPasswordManager* tpm = new TestPasswordManager(contents, delegate); |
| 66 contents->SetUserData(UserDataKey(), tpm); |
| 67 return tpm; |
| 68 } |
| 69 |
| 70 private: |
| 71 DISALLOW_COPY_AND_ASSIGN(TestPasswordManager); |
| 72 }; |
| 73 |
| 74 } // namespace |
| 75 |
| 49 class PasswordManagerTest : public ChromeRenderViewHostTestHarness { | 76 class PasswordManagerTest : public ChromeRenderViewHostTestHarness { |
| 50 protected: | 77 protected: |
| 51 virtual void SetUp() { | 78 virtual void SetUp() { |
| 52 ChromeRenderViewHostTestHarness::SetUp(); | 79 ChromeRenderViewHostTestHarness::SetUp(); |
| 53 store_ = static_cast<MockPasswordStore*>( | 80 store_ = static_cast<MockPasswordStore*>( |
| 54 PasswordStoreFactory::GetInstance()->SetTestingFactoryAndUse( | 81 PasswordStoreFactory::GetInstance()->SetTestingFactoryAndUse( |
| 55 profile(), MockPasswordStore::Build).get()); | 82 profile(), MockPasswordStore::Build).get()); |
| 56 | 83 |
| 57 EXPECT_CALL(delegate_, GetProfile()).WillRepeatedly(Return(profile())); | 84 EXPECT_CALL(delegate_, GetProfile()).WillRepeatedly(Return(profile())); |
| 58 PasswordManager::CreateForWebContentsAndDelegate( | 85 manager_ = TestPasswordManager::CreateForWebContentsAndDelegate( |
| 59 web_contents(), &delegate_); | 86 web_contents(), &delegate_); |
| 60 EXPECT_CALL(delegate_, DidLastPageLoadEncounterSSLErrors()) | 87 EXPECT_CALL(delegate_, DidLastPageLoadEncounterSSLErrors()) |
| 61 .WillRepeatedly(Return(false)); | 88 .WillRepeatedly(Return(false)); |
| 62 } | 89 } |
| 63 | 90 |
| 64 virtual void TearDown() { | 91 virtual void TearDown() { |
| 65 store_ = NULL; | 92 store_ = NULL; |
| 66 ChromeRenderViewHostTestHarness::TearDown(); | 93 ChromeRenderViewHostTestHarness::TearDown(); |
| 67 } | 94 } |
| 68 | 95 |
| 69 PasswordForm MakeSimpleForm() { | 96 PasswordForm MakeSimpleForm() { |
| 70 PasswordForm form; | 97 PasswordForm form; |
| 71 form.origin = GURL("http://www.google.com/a/LoginAuth"); | 98 form.origin = GURL("http://www.google.com/a/LoginAuth"); |
| 72 form.action = GURL("http://www.google.com/a/Login"); | 99 form.action = GURL("http://www.google.com/a/Login"); |
| 73 form.username_element = ASCIIToUTF16("Email"); | 100 form.username_element = ASCIIToUTF16("Email"); |
| 74 form.password_element = ASCIIToUTF16("Passwd"); | 101 form.password_element = ASCIIToUTF16("Passwd"); |
| 75 form.username_value = ASCIIToUTF16("google"); | 102 form.username_value = ASCIIToUTF16("google"); |
| 76 form.password_value = ASCIIToUTF16("password"); | 103 form.password_value = ASCIIToUTF16("password"); |
| 77 // Default to true so we only need to add tests in autocomplete=off cases. | 104 // Default to true so we only need to add tests in autocomplete=off cases. |
| 78 form.password_autocomplete_set = true; | 105 form.password_autocomplete_set = true; |
| 79 form.submit_element = ASCIIToUTF16("signIn"); | 106 form.submit_element = ASCIIToUTF16("signIn"); |
| 80 form.signon_realm = "http://www.google.com"; | 107 form.signon_realm = "http://www.google.com"; |
| 81 return form; | 108 return form; |
| 82 } | 109 } |
| 83 | 110 |
| 84 PasswordManager* manager() { | 111 bool FormsAreEqual(const content::PasswordForm& lhs, |
| 85 return PasswordManager::FromWebContents(web_contents()); | 112 const content::PasswordForm& rhs) { |
| 113 if (lhs.origin != rhs.origin) |
| 114 return false; |
| 115 if (lhs.action != rhs.action) |
| 116 return false; |
| 117 if (lhs.username_element != rhs.username_element) |
| 118 return false; |
| 119 if (lhs.password_element != rhs.password_element) |
| 120 return false; |
| 121 if (lhs.username_value != rhs.username_value) |
| 122 return false; |
| 123 if (lhs.password_value != rhs.password_value) |
| 124 return false; |
| 125 if (lhs.password_autocomplete_set != rhs.password_autocomplete_set) |
| 126 return false; |
| 127 if (lhs.submit_element != rhs.submit_element) |
| 128 return false; |
| 129 if (lhs.signon_realm != rhs.signon_realm) |
| 130 return false; |
| 131 return true; |
| 132 } |
| 133 |
| 134 TestPasswordManager* manager() { |
| 135 return manager_; |
| 136 } |
| 137 |
| 138 void OnPasswordFormSubmitted(const content::PasswordForm& form) { |
| 139 manager()->OnPasswordFormSubmitted(form); |
| 140 } |
| 141 |
| 142 PasswordManager::PasswordSubmittedCallback SubmissionCallback() { |
| 143 return base::Bind(&PasswordManagerTest::FormSubmitted, |
| 144 base::Unretained(this)); |
| 145 } |
| 146 |
| 147 void FormSubmitted(const content::PasswordForm& form) { |
| 148 submitted_form_ = form; |
| 86 } | 149 } |
| 87 | 150 |
| 88 scoped_refptr<MockPasswordStore> store_; | 151 scoped_refptr<MockPasswordStore> store_; |
| 152 TestPasswordManager* manager_; |
| 89 MockPasswordManagerDelegate delegate_; // Owned by manager_. | 153 MockPasswordManagerDelegate delegate_; // Owned by manager_. |
| 154 PasswordForm submitted_form_; |
| 90 }; | 155 }; |
| 91 | 156 |
| 92 MATCHER_P(FormMatches, form, "") { | 157 MATCHER_P(FormMatches, form, "") { |
| 93 return form.signon_realm == arg.signon_realm && | 158 return form.signon_realm == arg.signon_realm && |
| 94 form.origin == arg.origin && | 159 form.origin == arg.origin && |
| 95 form.action == arg.action && | 160 form.action == arg.action && |
| 96 form.username_element == arg.username_element && | 161 form.username_element == arg.username_element && |
| 97 form.password_element == arg.password_element && | 162 form.password_element == arg.password_element && |
| 98 form.password_autocomplete_set == | 163 form.password_autocomplete_set == |
| 99 arg.password_autocomplete_set && | 164 arg.password_autocomplete_set && |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 std::vector<PasswordForm*> result; // Empty password store. | 266 std::vector<PasswordForm*> result; // Empty password store. |
| 202 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0)); | 267 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0)); |
| 203 EXPECT_CALL(*store_.get(), GetLogins(_, _)) | 268 EXPECT_CALL(*store_.get(), GetLogins(_, _)) |
| 204 .WillOnce(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1))); | 269 .WillOnce(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1))); |
| 205 std::vector<PasswordForm> observed; | 270 std::vector<PasswordForm> observed; |
| 206 PasswordForm form(MakeSimpleForm()); | 271 PasswordForm form(MakeSimpleForm()); |
| 207 observed.push_back(form); | 272 observed.push_back(form); |
| 208 manager()->OnPasswordFormsParsed(observed); // The initial load. | 273 manager()->OnPasswordFormsParsed(observed); // The initial load. |
| 209 manager()->OnPasswordFormsRendered(observed); // The initial layout. | 274 manager()->OnPasswordFormsRendered(observed); // The initial layout. |
| 210 | 275 |
| 211 PasswordForm empty_form(form); | 276 // No message from the renderer that a password was submitted. No |
| 212 empty_form.username_value = string16(); | 277 // expected calls. |
| 213 empty_form.password_value = string16(); | |
| 214 content::LoadCommittedDetails details; | |
| 215 content::FrameNavigateParams params; | |
| 216 params.password_form = empty_form; | |
| 217 manager()->DidNavigateAnyFrame(details, params); | |
| 218 | |
| 219 // No expected calls. | |
| 220 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_)).Times(0); | 278 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_)).Times(0); |
| 221 observed.clear(); | 279 observed.clear(); |
| 222 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. | 280 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. |
| 223 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. | 281 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. |
| 224 } | 282 } |
| 225 | 283 |
| 226 TEST_F(PasswordManagerTest, FormSubmitAfterNavigateSubframe) { | 284 TEST_F(PasswordManagerTest, FormSubmitAfterNavigateSubframe) { |
| 227 // Test that navigating a subframe does not prevent us from showing the save | 285 // Test that navigating a subframe does not prevent us from showing the save |
| 228 // password infobar. | 286 // password infobar. |
| 229 std::vector<PasswordForm*> result; // Empty password store. | 287 std::vector<PasswordForm*> result; // Empty password store. |
| 230 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0)); | 288 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0)); |
| 231 EXPECT_CALL(*store_.get(), GetLogins(_, _)) | 289 EXPECT_CALL(*store_.get(), GetLogins(_, _)) |
| 232 .WillOnce(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1))); | 290 .WillOnce(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1))); |
| 233 std::vector<PasswordForm> observed; | 291 std::vector<PasswordForm> observed; |
| 234 PasswordForm form(MakeSimpleForm()); | 292 PasswordForm form(MakeSimpleForm()); |
| 235 observed.push_back(form); | 293 observed.push_back(form); |
| 236 manager()->OnPasswordFormsParsed(observed); // The initial load. | 294 manager()->OnPasswordFormsParsed(observed); // The initial load. |
| 237 manager()->OnPasswordFormsRendered(observed); // The initial layout. | 295 manager()->OnPasswordFormsRendered(observed); // The initial layout. |
| 238 | 296 |
| 239 // Simulate navigating a sub-frame. | 297 // Simulate navigating a sub-frame. |
| 240 content::LoadCommittedDetails details; | 298 content::LoadCommittedDetails details; |
| 241 details.is_main_frame = false; | |
| 242 content::FrameNavigateParams params; | 299 content::FrameNavigateParams params; |
| 243 manager()->DidNavigateAnyFrame(details, params); | 300 manager()->DidNavigateAnyFrame(details, params); |
| 244 | 301 |
| 245 // Simulate navigating the real page. | 302 // Simulate submitting the password. |
| 246 details.is_main_frame = true; | 303 OnPasswordFormSubmitted(form); |
| 247 params.password_form = form; | |
| 248 manager()->DidNavigateAnyFrame(details, params); | |
| 249 | 304 |
| 250 // Now the password manager waits for the navigation to complete. | 305 // Now the password manager waits for the navigation to complete. |
| 251 scoped_ptr<PasswordFormManager> form_to_save; | 306 scoped_ptr<PasswordFormManager> form_to_save; |
| 252 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_)) | 307 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_)) |
| 253 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save))); | 308 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save))); |
| 254 | 309 |
| 255 observed.clear(); | 310 observed.clear(); |
| 256 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. | 311 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. |
| 257 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. | 312 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. |
| 258 | 313 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 282 std::vector<PasswordForm> observed; | 337 std::vector<PasswordForm> observed; |
| 283 observed.push_back(first_form); | 338 observed.push_back(first_form); |
| 284 manager()->OnPasswordFormsParsed(observed); | 339 manager()->OnPasswordFormsParsed(observed); |
| 285 observed.clear(); | 340 observed.clear(); |
| 286 manager()->OnPasswordFormsRendered(observed); | 341 manager()->OnPasswordFormsRendered(observed); |
| 287 | 342 |
| 288 // Now navigate to a second page. | 343 // Now navigate to a second page. |
| 289 content::LoadCommittedDetails details; | 344 content::LoadCommittedDetails details; |
| 290 details.is_main_frame = true; | 345 details.is_main_frame = true; |
| 291 content::FrameNavigateParams params; | 346 content::FrameNavigateParams params; |
| 292 manager()->DidNavigateAnyFrame(details, params); | 347 manager()->DidNavigateMainFrame(details, params); |
| 293 | 348 |
| 294 // This page contains a form with the same markup, but on a different | 349 // This page contains a form with the same markup, but on a different |
| 295 // URL. | 350 // URL. |
| 296 observed.push_back(second_form); | 351 observed.push_back(second_form); |
| 297 manager()->OnPasswordFormsParsed(observed); | 352 manager()->OnPasswordFormsParsed(observed); |
| 298 manager()->OnPasswordFormsRendered(observed); | 353 manager()->OnPasswordFormsRendered(observed); |
| 299 | 354 |
| 300 // Now submit this form | 355 // Now submit this form |
| 301 params.password_form = second_form; | 356 OnPasswordFormSubmitted(second_form); |
| 302 manager()->DidNavigateAnyFrame(details, params); | |
| 303 | 357 |
| 304 // Navigation after form submit. | 358 // Navigation after form submit. |
| 305 scoped_ptr<PasswordFormManager> form_to_save; | 359 scoped_ptr<PasswordFormManager> form_to_save; |
| 306 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_)) | 360 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_)) |
| 307 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save))); | 361 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save))); |
| 308 observed.clear(); | 362 observed.clear(); |
| 309 manager()->OnPasswordFormsParsed(observed); | 363 manager()->OnPasswordFormsParsed(observed); |
| 310 manager()->OnPasswordFormsRendered(observed); | 364 manager()->OnPasswordFormsRendered(observed); |
| 311 | 365 |
| 312 // Make sure that the saved form matches the second form, not the first. | 366 // Make sure that the saved form matches the second form, not the first. |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 // navigation occurs. | 522 // navigation occurs. |
| 469 EXPECT_CALL(delegate_, | 523 EXPECT_CALL(delegate_, |
| 470 AddSavePasswordInfoBarIfPermitted(_)).Times(Exactly(0)); | 524 AddSavePasswordInfoBarIfPermitted(_)).Times(Exactly(0)); |
| 471 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))); | 525 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))); |
| 472 | 526 |
| 473 // Now the password manager waits for the navigation to complete. | 527 // Now the password manager waits for the navigation to complete. |
| 474 observed.clear(); | 528 observed.clear(); |
| 475 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. | 529 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. |
| 476 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. | 530 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. |
| 477 } | 531 } |
| 532 |
| 533 TEST_F(PasswordManagerTest, SubmissionCallbackTest) { |
| 534 manager()->AddSubmissionCallback(SubmissionCallback()); |
| 535 PasswordForm form = MakeSimpleForm(); |
| 536 OnPasswordFormSubmitted(form); |
| 537 EXPECT_TRUE(FormsAreEqual(form, submitted_form_)); |
| 538 } |
| OLD | NEW |