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 |