| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 <string> | 5 #include <string> |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/metrics/histogram_samples.h" | 8 #include "base/metrics/histogram_samples.h" |
| 9 #include "base/metrics/statistics_recorder.h" | 9 #include "base/metrics/statistics_recorder.h" |
| 10 #include "base/strings/stringprintf.h" |
| 10 #include "chrome/browser/chrome_notification_types.h" | 11 #include "chrome/browser/chrome_notification_types.h" |
| 11 #include "chrome/browser/infobars/infobar_service.h" | 12 #include "chrome/browser/infobars/infobar_service.h" |
| 12 #include "chrome/browser/password_manager/password_store_factory.h" | 13 #include "chrome/browser/password_manager/password_store_factory.h" |
| 13 #include "chrome/browser/password_manager/test_password_store_service.h" | 14 #include "chrome/browser/password_manager/test_password_store_service.h" |
| 14 #include "chrome/browser/ui/browser.h" | 15 #include "chrome/browser/ui/browser.h" |
| 15 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 16 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 16 #include "chrome/common/chrome_version_info.h" | 17 #include "chrome/common/chrome_version_info.h" |
| 17 #include "chrome/test/base/in_process_browser_test.h" | 18 #include "chrome/test/base/in_process_browser_test.h" |
| 18 #include "chrome/test/base/test_switches.h" | 19 #include "chrome/test/base/test_switches.h" |
| 19 #include "chrome/test/base/ui_test_utils.h" | 20 #include "chrome/test/base/ui_test_utils.h" |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); | 167 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); |
| 167 | 168 |
| 168 ASSERT_FALSE(CommandLine::ForCurrentProcess()->HasSwitch( | 169 ASSERT_FALSE(CommandLine::ForCurrentProcess()->HasSwitch( |
| 169 password_manager::switches::kEnableAutomaticPasswordSaving)); | 170 password_manager::switches::kEnableAutomaticPasswordSaving)); |
| 170 NavigationObserver observer(WebContents()); | 171 NavigationObserver observer(WebContents()); |
| 171 GURL url = embedded_test_server()->GetURL(path); | 172 GURL url = embedded_test_server()->GetURL(path); |
| 172 ui_test_utils::NavigateToURL(browser(), url); | 173 ui_test_utils::NavigateToURL(browser(), url); |
| 173 observer.Wait(); | 174 observer.Wait(); |
| 174 } | 175 } |
| 175 | 176 |
| 176 // Executes |script| and uses the EXPECT macros to check the return value | 177 // Waits until the "value" attribute of the HTML element with |element_id| is |
| 177 // against |expected_return_value|. | 178 // equal to |expected_value|. If the current value is not as expected, this |
| 178 void CheckScriptReturnValue(std::string& script, bool expected_return_value); | 179 // waits until the "change" event is fired for the element. This also |
| 180 // guarantees that once the real value matches the expected, the JavaScript |
| 181 // event loop is spun to allow all other possible events to take place. |
| 182 void WaitForElementValue(const std::string& element_id, |
| 183 const std::string& expected_value); |
| 184 // Checks that the current "value" attribute of the HTML element with |
| 185 // |element_id| is equal to |expected_value|. |
| 186 void CheckElementValue(const std::string& element_id, |
| 187 const std::string& expected_value); |
| 179 | 188 |
| 180 private: | 189 private: |
| 181 DISALLOW_COPY_AND_ASSIGN(PasswordManagerBrowserTest); | 190 DISALLOW_COPY_AND_ASSIGN(PasswordManagerBrowserTest); |
| 182 }; | 191 }; |
| 183 | 192 |
| 184 void PasswordManagerBrowserTest::CheckScriptReturnValue( | 193 void PasswordManagerBrowserTest::WaitForElementValue( |
| 185 std::string& script, | 194 const std::string& element_id, |
| 186 bool expected_return_value) { | 195 const std::string& expected_value) { |
| 187 const std::string wrapped_script = | 196 enum ReturnCodes { // Possible results of the JavaScript code. |
| 188 std::string("window.domAutomationController.send(") + script + ");"; | 197 RETURN_CODE_OK, |
| 189 bool return_value = !expected_return_value; | 198 RETURN_CODE_NO_ELEMENT, |
| 199 RETURN_CODE_WRONG_VALUE, |
| 200 RETURN_CODE_INVALID, |
| 201 }; |
| 202 const std::string value_check_function = base::StringPrintf( |
| 203 "function valueCheck() {" |
| 204 " var element = document.getElementById('%s');" |
| 205 " return element && element.value == '%s';" |
| 206 "}", |
| 207 element_id.c_str(), |
| 208 expected_value.c_str()); |
| 209 const std::string script = |
| 210 value_check_function + |
| 211 base::StringPrintf( |
| 212 "if (valueCheck()) {" |
| 213 " /* Spin the event loop with setTimeout. */" |
| 214 " setTimeout(window.domAutomationController.send(%d), 0);" |
| 215 "} else {" |
| 216 " var element = document.getElementById('%s');" |
| 217 " if (!element)" |
| 218 " window.domAutomationController.send(%d);" |
| 219 " element.onchange = function() {" |
| 220 " if (valueCheck()) {" |
| 221 " /* Spin the event loop with setTimeout. */" |
| 222 " setTimeout(window.domAutomationController.send(%d), 0);" |
| 223 " } else {" |
| 224 " window.domAutomationController.send(%d);" |
| 225 " }" |
| 226 " };" |
| 227 "}", |
| 228 RETURN_CODE_OK, |
| 229 element_id.c_str(), |
| 230 RETURN_CODE_NO_ELEMENT, |
| 231 RETURN_CODE_OK, |
| 232 RETURN_CODE_WRONG_VALUE); |
| 233 int return_value = RETURN_CODE_INVALID; |
| 234 ASSERT_TRUE(content::ExecuteScriptAndExtractInt( |
| 235 RenderViewHost(), script, &return_value)); |
| 236 EXPECT_EQ(RETURN_CODE_OK, return_value) |
| 237 << "element_id = " << element_id |
| 238 << ", expected_value = " << expected_value; |
| 239 } |
| 240 |
| 241 void PasswordManagerBrowserTest::CheckElementValue( |
| 242 const std::string& element_id, |
| 243 const std::string& expected_value) { |
| 244 const std::string value_check_script = base::StringPrintf( |
| 245 "var element = document.getElementById('%s');" |
| 246 "window.domAutomationController.send(element && element.value == '%s');", |
| 247 element_id.c_str(), |
| 248 expected_value.c_str()); |
| 249 bool return_value = false; |
| 190 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( | 250 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( |
| 191 RenderViewHost(), wrapped_script, &return_value)); | 251 RenderViewHost(), value_check_script, &return_value)); |
| 192 EXPECT_EQ(expected_return_value, return_value) << "script = " << script; | 252 EXPECT_TRUE(return_value) << "element_id = " << element_id |
| 253 << ", expected_value = " << expected_value; |
| 193 } | 254 } |
| 194 | 255 |
| 195 // Actual tests --------------------------------------------------------------- | 256 // Actual tests --------------------------------------------------------------- |
| 196 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, | 257 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, |
| 197 PromptForNormalSubmit) { | 258 PromptForNormalSubmit) { |
| 198 NavigateToFile("/password/password_form.html"); | 259 NavigateToFile("/password/password_form.html"); |
| 199 | 260 |
| 200 // Fill a form and submit through a <input type="submit"> button. Nothing | 261 // Fill a form and submit through a <input type="submit"> button. Nothing |
| 201 // special. | 262 // special. |
| 202 NavigationObserver observer(WebContents()); | 263 NavigationObserver observer(WebContents()); |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 "document.getElementById('password_field').value = 'random';" | 647 "document.getElementById('password_field').value = 'random';" |
| 587 "document.getElementById('input_submit_button').click();" | 648 "document.getElementById('input_submit_button').click();" |
| 588 "window.location.href = 'done.html';"; | 649 "window.location.href = 'done.html';"; |
| 589 | 650 |
| 590 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), save_and_remove)); | 651 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), save_and_remove)); |
| 591 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), navigate_frame)); | 652 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), navigate_frame)); |
| 592 observer.Wait(); | 653 observer.Wait(); |
| 593 // The only thing we check here is that there is no use-after-free reported. | 654 // The only thing we check here is that there is no use-after-free reported. |
| 594 } | 655 } |
| 595 | 656 |
| 596 // Disabled on Windows due to flakiness: http://crbug.com/346297 | 657 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, PasswordValueAccessible) { |
| 597 #if defined(OS_WIN) | |
| 598 #define MAYBE_PasswordValueAccessible DISABLED_PasswordValueAccessible | |
| 599 #else | |
| 600 #define MAYBE_PasswordValueAccessible PasswordValueAccessible | |
| 601 #endif | |
| 602 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, | |
| 603 MAYBE_PasswordValueAccessible) { | |
| 604 NavigateToFile("/password/form_and_link.html"); | 658 NavigateToFile("/password/form_and_link.html"); |
| 605 | 659 |
| 606 // Click on a link to open a new tab, then switch back to the first one. | 660 // Click on a link to open a new tab, then switch back to the first one. |
| 607 EXPECT_EQ(1, browser()->tab_strip_model()->count()); | 661 EXPECT_EQ(1, browser()->tab_strip_model()->count()); |
| 608 std::string click = | 662 std::string click = |
| 609 "document.getElementById('testlink').click();"; | 663 "document.getElementById('testlink').click();"; |
| 610 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), click)); | 664 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), click)); |
| 611 EXPECT_EQ(2, browser()->tab_strip_model()->count()); | 665 EXPECT_EQ(2, browser()->tab_strip_model()->count()); |
| 612 browser()->tab_strip_model()->ActivateTabAt(0, false); | 666 browser()->tab_strip_model()->ActivateTabAt(0, false); |
| 613 | 667 |
| 614 // Fill in the credentials, and make sure they are saved. | 668 // Fill in the credentials, and make sure they are saved. |
| 615 NavigationObserver form_submit_observer(WebContents()); | 669 NavigationObserver form_submit_observer(WebContents()); |
| 616 std::string fill_and_submit = | 670 std::string fill_and_submit = |
| 617 "document.getElementById('username_field').value = 'temp';" | 671 "document.getElementById('username_field').value = 'temp';" |
| 618 "document.getElementById('password_field').value = 'random';" | 672 "document.getElementById('password_field').value = 'random';" |
| 619 "document.getElementById('input_submit_button').click();"; | 673 "document.getElementById('input_submit_button').click();"; |
| 620 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit)); | 674 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit)); |
| 621 form_submit_observer.Wait(); | 675 form_submit_observer.Wait(); |
| 622 EXPECT_TRUE(form_submit_observer.infobar_shown()); | 676 EXPECT_TRUE(form_submit_observer.infobar_shown()); |
| 623 | 677 |
| 624 // Reload the original page to have the saved credentials autofilled. | 678 // Reload the original page to have the saved credentials autofilled. |
| 625 NavigationObserver reload_observer(WebContents()); | 679 NavigationObserver reload_observer(WebContents()); |
| 626 NavigateToFile("/password/form_and_link.html"); | 680 NavigateToFile("/password/form_and_link.html"); |
| 627 reload_observer.Wait(); | 681 reload_observer.Wait(); |
| 628 | 682 |
| 629 // Check that while the username is immediately available, the password value | 683 // Wait until the username is filled, to make sure autofill kicked in. |
| 630 // needs a user interaction to show up. | 684 WaitForElementValue("username_field", "temp"); |
| 631 std::string check_username = | 685 // Now check that the password is not accessible yet. |
| 632 "document.getElementById('username_field').value == 'temp'"; | 686 CheckElementValue("password_field", ""); |
| 633 std::string check_password = | 687 // Let the user interact with the page. |
| 634 "document.getElementById('password_field').value == 'random'"; | 688 content::SimulateMouseClickAt( |
| 635 CheckScriptReturnValue(check_username, true); | 689 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(1, 1)); |
| 636 CheckScriptReturnValue(check_password, false); | 690 // Wait until that interaction causes the password value to be revealed. |
| 637 content::SimulateMouseClick( | 691 WaitForElementValue("password_field", "random"); |
| 638 WebContents(), 0, blink::WebMouseEvent::ButtonLeft); | 692 // And check that after the side-effects of the interaction took place, the |
| 639 CheckScriptReturnValue(check_username, true); | 693 // username value stays the same. |
| 640 CheckScriptReturnValue(check_password, true); | 694 CheckElementValue("username_field", "temp"); |
| 641 } | 695 } |
| 642 | 696 |
| 643 // The following test is limited to Aura, because | 697 // The following test is limited to Aura, because |
| 644 // RenderWidgetHostViewGuest::ProcessAckedTouchEvent is, and | 698 // RenderWidgetHostViewGuest::ProcessAckedTouchEvent is, and |
| 645 // ProcessAckedTouchEvent is what triggers the translation of touch events to | 699 // ProcessAckedTouchEvent is what triggers the translation of touch events to |
| 646 // gesture events. | 700 // gesture events. |
| 647 #if defined(USE_AURA) | 701 #if defined(USE_AURA) |
| 648 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, | 702 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, |
| 649 PasswordValueAccessibleOnSubmit) { | 703 PasswordValueAccessibleOnSubmit) { |
| 650 NavigateToFile("/password/form_and_link.html"); | 704 NavigateToFile("/password/form_and_link.html"); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill)); | 801 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill)); |
| 748 | 802 |
| 749 NavigationObserver observer(WebContents()); | 803 NavigationObserver observer(WebContents()); |
| 750 GURL url = embedded_test_server()->GetURL("/password/password_form.html"); | 804 GURL url = embedded_test_server()->GetURL("/password/password_form.html"); |
| 751 chrome::NavigateParams params(browser(), url, | 805 chrome::NavigateParams params(browser(), url, |
| 752 content::PAGE_TRANSITION_RELOAD); | 806 content::PAGE_TRANSITION_RELOAD); |
| 753 ui_test_utils::NavigateToURL(¶ms); | 807 ui_test_utils::NavigateToURL(¶ms); |
| 754 observer.Wait(); | 808 observer.Wait(); |
| 755 EXPECT_FALSE(observer.infobar_shown()); | 809 EXPECT_FALSE(observer.infobar_shown()); |
| 756 } | 810 } |
| OLD | NEW |