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

Side by Side Diff: chrome/renderer/autofill/password_autofill_agent_browsertest.cc

Issue 2865233003: Use an MutationObserver to check when a password form disappears after XHR (Closed)
Patch Set: updates Created 3 years, 7 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
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 "components/autofill/content/renderer/password_autofill_agent.h" 5 #include "components/autofill/content/renderer/password_autofill_agent.h"
6 6
7 #include "base/macros.h" 7 #include "base/macros.h"
8 #include "base/run_loop.h" 8 #include "base/run_loop.h"
9 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h" 10 #include "base/strings/string_util.h"
(...skipping 1660 matching lines...) Expand 10 before | Expand all | Expand 10 after
1671 ExpectFieldPropertiesMasks(PasswordFormSubmitted, expected_properties_masks); 1671 ExpectFieldPropertiesMasks(PasswordFormSubmitted, expected_properties_masks);
1672 } 1672 }
1673 1673
1674 TEST_F(PasswordAutofillAgentTest, RememberFieldPropertiesOnInPageNavigation) { 1674 TEST_F(PasswordAutofillAgentTest, RememberFieldPropertiesOnInPageNavigation) {
1675 LoadHTML(kNoFormHTML); 1675 LoadHTML(kNoFormHTML);
1676 UpdateUsernameAndPasswordElements(); 1676 UpdateUsernameAndPasswordElements();
1677 1677
1678 SimulateUsernameChange("Bob"); 1678 SimulateUsernameChange("Bob");
1679 SimulatePasswordChange("mypassword"); 1679 SimulatePasswordChange("mypassword");
1680 1680
1681 username_element_.SetAttribute("style", "display:none;"); 1681 std::string hide_elements =
1682 password_element_.SetAttribute("style", "display:none;"); 1682 "var password = document.getElementById('password');"
1683 "password.style = 'display:none';"
1684 "var username = document.getElementById('username');"
1685 "username.style = 'display:none';";
1686 ExecuteJavaScriptForTests(hide_elements.c_str());
1683 1687
1684 password_autofill_agent_->AJAXSucceeded(); 1688 password_autofill_agent_->AJAXSucceeded();
1685 1689
1686 std::map<base::string16, FieldPropertiesMask> expected_properties_masks; 1690 std::map<base::string16, FieldPropertiesMask> expected_properties_masks;
1687 expected_properties_masks[ASCIIToUTF16("username")] = 1691 expected_properties_masks[ASCIIToUTF16("username")] =
1688 FieldPropertiesFlags::USER_TYPED; 1692 FieldPropertiesFlags::USER_TYPED;
1689 expected_properties_masks[ASCIIToUTF16("password")] = 1693 expected_properties_masks[ASCIIToUTF16("password")] =
1690 FieldPropertiesFlags::USER_TYPED | FieldPropertiesFlags::HAD_FOCUS; 1694 FieldPropertiesFlags::USER_TYPED | FieldPropertiesFlags::HAD_FOCUS;
1691 1695
1692 ExpectFieldPropertiesMasks(PasswordFormInPageNavigation, 1696 ExpectFieldPropertiesMasks(PasswordFormInPageNavigation,
1693 expected_properties_masks); 1697 expected_properties_masks);
1694 } 1698 }
1695 1699
1700 TEST_F(PasswordAutofillAgentTest, RememberFieldPropertiesOnInPageNavigation_2) {
1701 LoadHTML(kNoFormHTML);
1702 UpdateUsernameAndPasswordElements();
1703
1704 SimulateUsernameChange("Bob");
1705 SimulatePasswordChange("mypassword");
1706
1707 password_autofill_agent_->AJAXSucceeded();
1708
1709 std::string hide_elements =
1710 "var password = document.getElementById('password');"
1711 "password.style = 'display:none';"
1712 "var username = document.getElementById('username');"
1713 "username.style = 'display:none';";
1714 ExecuteJavaScriptForTests(hide_elements.c_str());
1715
1716 base::RunLoop().RunUntilIdle();
1717
1718 std::map<base::string16, FieldPropertiesMask> expected_properties_masks;
1719 expected_properties_masks[ASCIIToUTF16("username")] =
1720 FieldPropertiesFlags::USER_TYPED;
1721 expected_properties_masks[ASCIIToUTF16("password")] =
1722 FieldPropertiesFlags::USER_TYPED | FieldPropertiesFlags::HAD_FOCUS;
1723
1724 ExpectFieldPropertiesMasks(PasswordFormInPageNavigation,
1725 expected_properties_masks);
1726 }
1727
1696 // The username/password is autofilled by password manager then just before 1728 // The username/password is autofilled by password manager then just before
1697 // sending the form off, a script changes them. This test checks that 1729 // sending the form off, a script changes them. This test checks that
1698 // PasswordAutofillAgent can still get the username and the password autofilled. 1730 // PasswordAutofillAgent can still get the username and the password autofilled.
1699 TEST_F(PasswordAutofillAgentTest, 1731 TEST_F(PasswordAutofillAgentTest,
1700 RememberLastAutofilledUsernameAndPasswordOnSubmit_ScriptChanged) { 1732 RememberLastAutofilledUsernameAndPasswordOnSubmit_ScriptChanged) {
1701 SimulateOnFillPasswordForm(fill_data_); 1733 SimulateOnFillPasswordForm(fill_data_);
1702 1734
1703 // Simulate that the username and the password value was changed by the 1735 // Simulate that the username and the password value was changed by the
1704 // site's JavaScript before submit. 1736 // site's JavaScript before submit.
1705 username_element_.SetValue(WebString("new username")); 1737 username_element_.SetValue(WebString("new username"));
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after
2241 CheckTextFieldsState("", true, kAlicePassword, true); 2273 CheckTextFieldsState("", true, kAlicePassword, true);
2242 } 2274 }
2243 2275
2244 TEST_F(PasswordAutofillAgentTest, NoForm_PromptForAJAXSubmitWithoutNavigation) { 2276 TEST_F(PasswordAutofillAgentTest, NoForm_PromptForAJAXSubmitWithoutNavigation) {
2245 LoadHTML(kNoFormHTML); 2277 LoadHTML(kNoFormHTML);
2246 UpdateUsernameAndPasswordElements(); 2278 UpdateUsernameAndPasswordElements();
2247 2279
2248 SimulateUsernameChange("Bob"); 2280 SimulateUsernameChange("Bob");
2249 SimulatePasswordChange("mypassword"); 2281 SimulatePasswordChange("mypassword");
2250 2282
2251 username_element_.SetAttribute("style", "display:none;"); 2283 std::string hide_elements =
2252 password_element_.SetAttribute("style", "display:none;"); 2284 "var password = document.getElementById('password');"
2285 "password.style = 'display:none';"
2286 "var username = document.getElementById('username');"
2287 "username.style = 'display:none';";
2288 ExecuteJavaScriptForTests(hide_elements.c_str());
2253 2289
2254 password_autofill_agent_->AJAXSucceeded(); 2290 password_autofill_agent_->AJAXSucceeded();
2255 2291
2256 ExpectInPageNavigationWithUsernameAndPasswords( 2292 ExpectInPageNavigationWithUsernameAndPasswords(
2257 "Bob", "mypassword", "", 2293 "Bob", "mypassword", "",
2258 PasswordForm::SubmissionIndicatorEvent::XHR_SUCCEEDED); 2294 PasswordForm::SubmissionIndicatorEvent::XHR_SUCCEEDED);
2259 } 2295 }
2260 2296
2261 TEST_F(PasswordAutofillAgentTest, 2297 TEST_F(PasswordAutofillAgentTest,
2298 NoForm_PromptForAJAXSubmitWithoutNavigation_2) {
2299 LoadHTML(kNoFormHTML);
2300 UpdateUsernameAndPasswordElements();
2301
2302 SimulateUsernameChange("Bob");
2303 SimulatePasswordChange("mypassword");
2304
2305 password_autofill_agent_->AJAXSucceeded();
2306
2307 std::string hide_elements =
2308 "var password = document.getElementById('password');"
2309 "password.style = 'display:none';"
2310 "var username = document.getElementById('username');"
2311 "username.style = 'display:none';";
2312 ExecuteJavaScriptForTests(hide_elements.c_str());
2313
2314 base::RunLoop().RunUntilIdle();
2315
2316 ExpectInPageNavigationWithUsernameAndPasswords(
2317 "Bob", "mypassword", "",
2318 PasswordForm::SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR);
2319 }
2320
2321 TEST_F(PasswordAutofillAgentTest,
2262 NoForm_NoPromptForAJAXSubmitWithoutNavigationAndElementsVisible) { 2322 NoForm_NoPromptForAJAXSubmitWithoutNavigationAndElementsVisible) {
2263 LoadHTML(kNoFormHTML); 2323 LoadHTML(kNoFormHTML);
2264 UpdateUsernameAndPasswordElements(); 2324 UpdateUsernameAndPasswordElements();
2265 2325
2266 SimulateUsernameChange("Bob"); 2326 SimulateUsernameChange("Bob");
2267 SimulatePasswordChange("mypassword"); 2327 SimulatePasswordChange("mypassword");
2268 2328
2269 password_autofill_agent_->AJAXSucceeded(); 2329 password_autofill_agent_->AJAXSucceeded();
2270 2330
2271 base::RunLoop().RunUntilIdle(); 2331 base::RunLoop().RunUntilIdle();
(...skipping 12 matching lines...) Expand all
2284 2344
2285 UpdateUsernameAndPasswordElements(); 2345 UpdateUsernameAndPasswordElements();
2286 WebElement captcha_element = GetMainFrame()->GetDocument().GetElementById( 2346 WebElement captcha_element = GetMainFrame()->GetDocument().GetElementById(
2287 WebString::FromUTF8("captcha")); 2347 WebString::FromUTF8("captcha"));
2288 ASSERT_FALSE(captcha_element.IsNull()); 2348 ASSERT_FALSE(captcha_element.IsNull());
2289 2349
2290 SimulateUsernameChange("Bob"); 2350 SimulateUsernameChange("Bob");
2291 SimulatePasswordChange("mypassword"); 2351 SimulatePasswordChange("mypassword");
2292 2352
2293 // Simulate captcha element show up right before AJAX completed. 2353 // Simulate captcha element show up right before AJAX completed.
2294 captcha_element.SetAttribute("style", "display:inline;"); 2354 std::string show_captcha =
2355 "var captcha = document.getElementById('captcha');"
2356 "captcha.style = 'display:inline';";
2357 ExecuteJavaScriptForTests(show_captcha.c_str());
2295 password_autofill_agent_->AJAXSucceeded(); 2358 password_autofill_agent_->AJAXSucceeded();
2296 2359
2297 base::RunLoop().RunUntilIdle(); 2360 base::RunLoop().RunUntilIdle();
2298 EXPECT_FALSE(fake_driver_.called_inpage_navigation()); 2361 EXPECT_FALSE(fake_driver_.called_inpage_navigation());
2299 EXPECT_FALSE(fake_driver_.called_password_form_submitted()); 2362 EXPECT_FALSE(fake_driver_.called_password_form_submitted());
2300 } 2363 }
2301 2364
2365 TEST_F(PasswordAutofillAgentTest,
2366 NoForm_NoPromptForAJAXSubmitWithoutNavigationAndNewElementAppeared_2) {
2367 const char kNoFormHTMLWithHiddenField[] =
2368 "<INPUT type='text' id='username'/>"
2369 "<INPUT type='password' id='password'/>"
2370 "<INPUT type='text' id='captcha' style='display:none'/>";
2371 LoadHTML(kNoFormHTMLWithHiddenField);
2372
2373 UpdateUsernameAndPasswordElements();
2374 WebElement captcha_element = GetMainFrame()->GetDocument().GetElementById(
2375 WebString::FromUTF8("captcha"));
2376 ASSERT_FALSE(captcha_element.IsNull());
2377
2378 SimulateUsernameChange("Bob");
2379 SimulatePasswordChange("mypassword");
2380
2381 password_autofill_agent_->AJAXSucceeded();
2382
2383 // Simulate captcha element show up right after AJAX completed.
2384 std::string show_captcha =
2385 "var captcha = document.getElementById('captcha');"
2386 "captcha.style = 'display:inline';";
2387 ExecuteJavaScriptForTests(show_captcha.c_str());
2388 base::RunLoop().RunUntilIdle();
2389
2390 EXPECT_FALSE(fake_driver_.called_inpage_navigation());
2391 EXPECT_FALSE(fake_driver_.called_password_form_submitted());
2392 }
2393
2302 // Tests that no save promt is shown when a form with empty action URL is 2394 // Tests that no save promt is shown when a form with empty action URL is
2303 // changed and AJAX completed but the form is still visible. 2395 // changed and AJAX completed but the form is still visible.
2304 TEST_F(PasswordAutofillAgentTest, 2396 TEST_F(PasswordAutofillAgentTest,
2305 NoAction_NoPromptForAJAXSubmitWithoutNavigationAndNewElementAppeared) { 2397 NoAction_NoPromptForAJAXSubmitWithoutNavigationAndNewElementAppeared) {
2306 // Form without an action URL. 2398 // Form without an action URL.
2307 const char kHTMLWithHiddenField[] = 2399 const char kHTMLWithHiddenField[] =
2308 "<FORM name='LoginTestForm'>" 2400 "<FORM name='LoginTestForm'>"
2309 " <INPUT type='text' id='username'/>" 2401 " <INPUT type='text' id='username'/>"
2310 " <INPUT type='password' id='password'/>" 2402 " <INPUT type='password' id='password'/>"
2311 " <INPUT type='text' id='captcha' style='display:none'/>" 2403 " <INPUT type='text' id='captcha' style='display:none'/>"
(...skipping 12 matching lines...) Expand all
2324 2416
2325 // Simulate captcha element show up right before AJAX completed. 2417 // Simulate captcha element show up right before AJAX completed.
2326 captcha_element.SetAttribute("style", "display:inline;"); 2418 captcha_element.SetAttribute("style", "display:inline;");
2327 password_autofill_agent_->AJAXSucceeded(); 2419 password_autofill_agent_->AJAXSucceeded();
2328 2420
2329 base::RunLoop().RunUntilIdle(); 2421 base::RunLoop().RunUntilIdle();
2330 EXPECT_FALSE(fake_driver_.called_inpage_navigation()); 2422 EXPECT_FALSE(fake_driver_.called_inpage_navigation());
2331 EXPECT_FALSE(fake_driver_.called_password_form_submitted()); 2423 EXPECT_FALSE(fake_driver_.called_password_form_submitted());
2332 } 2424 }
2333 2425
2426 TEST_F(PasswordAutofillAgentTest,
2427 NoAction_NoPromptForAJAXSubmitWithoutNavigationAndNewElementAppeared_2) {
2428 // Form without an action URL.
2429 const char kHTMLWithHiddenField[] =
2430 "<FORM name='LoginTestForm'>"
2431 " <INPUT type='text' id='username'/>"
2432 " <INPUT type='password' id='password'/>"
2433 " <INPUT type='text' id='captcha' style='display:none'/>"
2434 " <INPUT type='submit' value='Login'/>"
2435 "</FORM>";
2436 // Set the valid URL so the form action URL can be generated properly.
2437 LoadHTMLWithUrlOverride(kHTMLWithHiddenField, "https://www.example.com");
2438
2439 UpdateUsernameAndPasswordElements();
2440 WebElement captcha_element = GetMainFrame()->GetDocument().GetElementById(
2441 WebString::FromUTF8("captcha"));
2442 ASSERT_FALSE(captcha_element.IsNull());
2443
2444 SimulateUsernameChange("Bob");
2445 SimulatePasswordChange("mypassword");
2446
2447 password_autofill_agent_->AJAXSucceeded();
2448
2449 // Simulate captcha element show up right after AJAX completed.
2450 captcha_element.SetAttribute("style", "display:inline;");
2451
2452 base::RunLoop().RunUntilIdle();
2453 EXPECT_FALSE(fake_driver_.called_inpage_navigation());
2454 EXPECT_FALSE(fake_driver_.called_password_form_submitted());
2455 }
2456
2334 // Tests that credential suggestions are autofilled on a password (and change 2457 // Tests that credential suggestions are autofilled on a password (and change
2335 // password) forms having either ambiguous or empty name. 2458 // password) forms having either ambiguous or empty name.
2336 TEST_F(PasswordAutofillAgentTest, 2459 TEST_F(PasswordAutofillAgentTest,
2337 SuggestionsOnFormContainingAmbiguousOrEmptyNames) { 2460 SuggestionsOnFormContainingAmbiguousOrEmptyNames) {
2338 const char kEmpty[] = ""; 2461 const char kEmpty[] = "";
2339 const char kDummyUsernameField[] = "anonymous_username"; 2462 const char kDummyUsernameField[] = "anonymous_username";
2340 const char kDummyPasswordField[] = "anonymous_password"; 2463 const char kDummyPasswordField[] = "anonymous_password";
2341 const char kFormContainsEmptyNamesHTML[] = 2464 const char kFormContainsEmptyNamesHTML[] =
2342 "<FORM name='WithoutNameIdForm' action='http://www.bidule.com' >" 2465 "<FORM name='WithoutNameIdForm' action='http://www.bidule.com' >"
2343 " <INPUT type='text' placeholder='username'/>" 2466 " <INPUT type='text' placeholder='username'/>"
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
2534 TEST_F(PasswordAutofillAgentTest, 2657 TEST_F(PasswordAutofillAgentTest,
2535 UsernameChangedAfterPasswordInput_InPageNavigation) { 2658 UsernameChangedAfterPasswordInput_InPageNavigation) {
2536 LoadHTML(kNoFormHTML); 2659 LoadHTML(kNoFormHTML);
2537 UpdateUsernameAndPasswordElements(); 2660 UpdateUsernameAndPasswordElements();
2538 2661
2539 SimulateUsernameChange("Bob"); 2662 SimulateUsernameChange("Bob");
2540 SimulatePasswordChange("mypassword"); 2663 SimulatePasswordChange("mypassword");
2541 SimulateUsernameChange("Alice"); 2664 SimulateUsernameChange("Alice");
2542 2665
2543 // Hide form elements to simulate successful login. 2666 // Hide form elements to simulate successful login.
2544 username_element_.SetAttribute("style", "display:none;"); 2667 std::string hide_elements =
2545 password_element_.SetAttribute("style", "display:none;"); 2668 "var password = document.getElementById('password');"
2669 "password.style = 'display:none';"
2670 "var username = document.getElementById('username');"
2671 "username.style = 'display:none';";
2672 ExecuteJavaScriptForTests(hide_elements.c_str());
2546 2673
2547 password_autofill_agent_->AJAXSucceeded(); 2674 password_autofill_agent_->AJAXSucceeded();
2548 2675
2549 ExpectInPageNavigationWithUsernameAndPasswords( 2676 ExpectInPageNavigationWithUsernameAndPasswords(
2550 "Alice", "mypassword", "", 2677 "Alice", "mypassword", "",
2551 PasswordForm::SubmissionIndicatorEvent::XHR_SUCCEEDED); 2678 PasswordForm::SubmissionIndicatorEvent::XHR_SUCCEEDED);
2552 } 2679 }
2553 2680
2554 TEST_F(PasswordAutofillAgentTest, 2681 TEST_F(PasswordAutofillAgentTest,
2682 UsernameChangedAfterPasswordInput_InPageNavigation_2) {
2683 LoadHTML(kNoFormHTML);
2684 UpdateUsernameAndPasswordElements();
2685
2686 SimulateUsernameChange("Bob");
2687 SimulatePasswordChange("mypassword");
2688 SimulateUsernameChange("Alice");
2689
2690 password_autofill_agent_->AJAXSucceeded();
2691
2692 // Hide form elements to simulate successful login.
2693 std::string hide_elements =
2694 "var password = document.getElementById('password');"
2695 "password.style = 'display:none';"
2696 "var username = document.getElementById('username');"
2697 "username.style = 'display:none';";
2698 ExecuteJavaScriptForTests(hide_elements.c_str());
2699 base::RunLoop().RunUntilIdle();
2700
2701 ExpectInPageNavigationWithUsernameAndPasswords(
2702 "Alice", "mypassword", "",
2703 PasswordForm::SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR);
2704 }
2705
2706 TEST_F(PasswordAutofillAgentTest,
2555 UsernameChangedAfterPasswordInput_FormSubmitted) { 2707 UsernameChangedAfterPasswordInput_FormSubmitted) {
2556 SimulateUsernameChange("Bob"); 2708 SimulateUsernameChange("Bob");
2557 SimulatePasswordChange("mypassword"); 2709 SimulatePasswordChange("mypassword");
2558 SimulateUsernameChange("Alice"); 2710 SimulateUsernameChange("Alice");
2559 2711
2560 static_cast<content::RenderFrameObserver*>(password_autofill_agent_) 2712 static_cast<content::RenderFrameObserver*>(password_autofill_agent_)
2561 ->WillSendSubmitEvent(username_element_.Form()); 2713 ->WillSendSubmitEvent(username_element_.Form());
2562 static_cast<content::RenderFrameObserver*>(password_autofill_agent_) 2714 static_cast<content::RenderFrameObserver*>(password_autofill_agent_)
2563 ->WillSubmitForm(username_element_.Form()); 2715 ->WillSubmitForm(username_element_.Form());
2564 2716
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
2737 2889
2738 // Navigate to another page and click on username field, 2890 // Navigate to another page and click on username field,
2739 // CheckSafeBrowsingReputation() should be triggered again. 2891 // CheckSafeBrowsingReputation() should be triggered again.
2740 LoadHTML(kFormHTML); 2892 LoadHTML(kFormHTML);
2741 SimulateElementClick(kUsernameName); 2893 SimulateElementClick(kUsernameName);
2742 base::RunLoop().RunUntilIdle(); 2894 base::RunLoop().RunUntilIdle();
2743 EXPECT_EQ(2, fake_driver_.called_check_safe_browsing_reputation_cnt()); 2895 EXPECT_EQ(2, fake_driver_.called_check_safe_browsing_reputation_cnt());
2744 } 2896 }
2745 #endif 2897 #endif
2746 } // namespace autofill 2898 } // namespace autofill
OLDNEW
« no previous file with comments | « no previous file | components/autofill/content/DEPS » ('j') | third_party/WebKit/public/web/modules/password_manager/OWNERS » ('J')

Powered by Google App Engine
This is Rietveld 408576698