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/path_service.h" | 10 #include "base/path_service.h" |
(...skipping 30 matching lines...) Expand all Loading... |
41 #include "content/public/browser/navigation_controller.h" | 41 #include "content/public/browser/navigation_controller.h" |
42 #include "content/public/browser/notification_service.h" | 42 #include "content/public/browser/notification_service.h" |
43 #include "content/public/browser/render_frame_host.h" | 43 #include "content/public/browser/render_frame_host.h" |
44 #include "content/public/browser/render_view_host.h" | 44 #include "content/public/browser/render_view_host.h" |
45 #include "content/public/browser/web_contents.h" | 45 #include "content/public/browser/web_contents.h" |
46 #include "content/public/browser/web_contents_observer.h" | 46 #include "content/public/browser/web_contents_observer.h" |
47 #include "content/public/common/content_switches.h" | 47 #include "content/public/common/content_switches.h" |
48 #include "content/public/test/browser_test_utils.h" | 48 #include "content/public/test/browser_test_utils.h" |
49 #include "content/public/test/test_utils.h" | 49 #include "content/public/test/test_utils.h" |
50 #include "net/base/filename_util.h" | 50 #include "net/base/filename_util.h" |
| 51 #include "net/dns/mock_host_resolver.h" |
51 #include "net/test/embedded_test_server/embedded_test_server.h" | 52 #include "net/test/embedded_test_server/embedded_test_server.h" |
52 #include "net/test/embedded_test_server/http_request.h" | 53 #include "net/test/embedded_test_server/http_request.h" |
53 #include "net/test/embedded_test_server/http_response.h" | 54 #include "net/test/embedded_test_server/http_response.h" |
54 #include "net/test/spawned_test_server/spawned_test_server.h" | 55 #include "net/test/spawned_test_server/spawned_test_server.h" |
55 #include "net/url_request/test_url_fetcher_factory.h" | 56 #include "net/url_request/test_url_fetcher_factory.h" |
56 #include "testing/gmock/include/gmock/gmock.h" | 57 #include "testing/gmock/include/gmock/gmock.h" |
57 #include "third_party/WebKit/public/web/WebInputEvent.h" | 58 #include "third_party/WebKit/public/web/WebInputEvent.h" |
58 #include "ui/events/keycodes/keyboard_codes.h" | 59 #include "ui/events/keycodes/keyboard_codes.h" |
59 #include "ui/gfx/geometry/point.h" | 60 #include "ui/gfx/geometry/point.h" |
60 | 61 |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 observer.Wait(); | 339 observer.Wait(); |
339 } | 340 } |
340 | 341 |
341 // Waits until the "value" attribute of the HTML element with |element_id| is | 342 // Waits until the "value" attribute of the HTML element with |element_id| is |
342 // equal to |expected_value|. If the current value is not as expected, this | 343 // equal to |expected_value|. If the current value is not as expected, this |
343 // waits until the "change" event is fired for the element. This also | 344 // waits until the "change" event is fired for the element. This also |
344 // guarantees that once the real value matches the expected, the JavaScript | 345 // guarantees that once the real value matches the expected, the JavaScript |
345 // event loop is spun to allow all other possible events to take place. | 346 // event loop is spun to allow all other possible events to take place. |
346 void WaitForElementValue(const std::string& element_id, | 347 void WaitForElementValue(const std::string& element_id, |
347 const std::string& expected_value); | 348 const std::string& expected_value); |
| 349 // Same as above except the element |element_id| is in iframe |iframe_id| |
| 350 void WaitForElementValue(const std::string& iframe_id, |
| 351 const std::string& element_id, |
| 352 const std::string& expected_value); |
348 // Checks that the current "value" attribute of the HTML element with | 353 // Checks that the current "value" attribute of the HTML element with |
349 // |element_id| is equal to |expected_value|. | 354 // |element_id| is equal to |expected_value|. |
350 void CheckElementValue(const std::string& element_id, | 355 void CheckElementValue(const std::string& element_id, |
351 const std::string& expected_value); | 356 const std::string& expected_value); |
| 357 // Same as above except the element |element_id| is in iframe |iframe_id| |
| 358 void CheckElementValue(const std::string& iframe_id, |
| 359 const std::string& element_id, |
| 360 const std::string& expected_value); |
352 | 361 |
353 // TODO(dvadym): Remove this once history.pushState() handling is not behind | 362 // TODO(dvadym): Remove this once history.pushState() handling is not behind |
354 // a flag. | 363 // a flag. |
355 // Calling this will activate handling of pushState()-initiated form submits. | 364 // Calling this will activate handling of pushState()-initiated form submits. |
356 // This feature is currently behind a renderer flag. Just setting the flag in | 365 // This feature is currently behind a renderer flag. Just setting the flag in |
357 // the browser will not change it for the already running renderer at tab 0. | 366 // the browser will not change it for the already running renderer at tab 0. |
358 // Therefore this method first sets the flag and then opens a new tab at | 367 // Therefore this method first sets the flag and then opens a new tab at |
359 // position 0. This new tab gets the flag copied from the browser process. | 368 // position 0. This new tab gets the flag copied from the browser process. |
360 void ActivateHistoryPushState(); | 369 void ActivateHistoryPushState(); |
361 | 370 |
362 private: | 371 private: |
363 DISALLOW_COPY_AND_ASSIGN(PasswordManagerBrowserTest); | 372 DISALLOW_COPY_AND_ASSIGN(PasswordManagerBrowserTest); |
364 }; | 373 }; |
365 | 374 |
366 void PasswordManagerBrowserTest::WaitForElementValue( | 375 void PasswordManagerBrowserTest::WaitForElementValue( |
367 const std::string& element_id, | 376 const std::string& element_id, |
368 const std::string& expected_value) { | 377 const std::string& expected_value) { |
| 378 PasswordManagerBrowserTest::WaitForElementValue("null", |
| 379 element_id, |
| 380 expected_value); |
| 381 } |
| 382 |
| 383 void PasswordManagerBrowserTest::WaitForElementValue( |
| 384 const std::string& iframe_id, |
| 385 const std::string& element_id, |
| 386 const std::string& expected_value) { |
369 enum ReturnCodes { // Possible results of the JavaScript code. | 387 enum ReturnCodes { // Possible results of the JavaScript code. |
370 RETURN_CODE_OK, | 388 RETURN_CODE_OK, |
371 RETURN_CODE_NO_ELEMENT, | 389 RETURN_CODE_NO_ELEMENT, |
372 RETURN_CODE_WRONG_VALUE, | 390 RETURN_CODE_WRONG_VALUE, |
373 RETURN_CODE_INVALID, | 391 RETURN_CODE_INVALID, |
374 }; | 392 }; |
375 const std::string value_check_function = base::StringPrintf( | 393 const std::string value_check_function = base::StringPrintf( |
376 "function valueCheck() {" | 394 "function valueCheck() {" |
377 " var element = document.getElementById('%s');" | 395 " if (%s)" |
| 396 " var element = document.getElementById(" |
| 397 " '%s').contentDocument.getElementById('%s');" |
| 398 " else " |
| 399 " var element = document.getElementById('%s');" |
378 " return element && element.value == '%s';" | 400 " return element && element.value == '%s';" |
379 "}", | 401 "}", |
| 402 iframe_id.c_str(), |
| 403 iframe_id.c_str(), |
| 404 element_id.c_str(), |
380 element_id.c_str(), | 405 element_id.c_str(), |
381 expected_value.c_str()); | 406 expected_value.c_str()); |
382 const std::string script = | 407 const std::string script = |
383 value_check_function + | 408 value_check_function + |
384 base::StringPrintf( | 409 base::StringPrintf( |
385 "if (valueCheck()) {" | 410 "if (valueCheck()) {" |
386 " /* Spin the event loop with setTimeout. */" | 411 " /* Spin the event loop with setTimeout. */" |
387 " setTimeout(window.domAutomationController.send(%d), 0);" | 412 " setTimeout(window.domAutomationController.send(%d), 0);" |
388 "} else {" | 413 "} else {" |
389 " var element = document.getElementById('%s');" | 414 " if (%s)" |
| 415 " var element = document.getElementById(" |
| 416 " '%s').contentDocument.getElementById('%s');" |
| 417 " else " |
| 418 " var element = document.getElementById('%s');" |
390 " if (!element)" | 419 " if (!element)" |
391 " window.domAutomationController.send(%d);" | 420 " window.domAutomationController.send(%d);" |
392 " element.onchange = function() {" | 421 " element.onchange = function() {" |
393 " if (valueCheck()) {" | 422 " if (valueCheck()) {" |
394 " /* Spin the event loop with setTimeout. */" | 423 " /* Spin the event loop with setTimeout. */" |
395 " setTimeout(window.domAutomationController.send(%d), 0);" | 424 " setTimeout(window.domAutomationController.send(%d), 0);" |
396 " } else {" | 425 " } else {" |
397 " window.domAutomationController.send(%d);" | 426 " window.domAutomationController.send(%d);" |
398 " }" | 427 " }" |
399 " };" | 428 " };" |
400 "}", | 429 "}", |
401 RETURN_CODE_OK, | 430 RETURN_CODE_OK, |
| 431 iframe_id.c_str(), |
| 432 iframe_id.c_str(), |
| 433 element_id.c_str(), |
402 element_id.c_str(), | 434 element_id.c_str(), |
403 RETURN_CODE_NO_ELEMENT, | 435 RETURN_CODE_NO_ELEMENT, |
404 RETURN_CODE_OK, | 436 RETURN_CODE_OK, |
405 RETURN_CODE_WRONG_VALUE); | 437 RETURN_CODE_WRONG_VALUE); |
406 int return_value = RETURN_CODE_INVALID; | 438 int return_value = RETURN_CODE_INVALID; |
407 ASSERT_TRUE(content::ExecuteScriptAndExtractInt( | 439 ASSERT_TRUE(content::ExecuteScriptAndExtractInt( |
408 RenderViewHost(), script, &return_value)); | 440 RenderViewHost(), script, &return_value)); |
409 EXPECT_EQ(RETURN_CODE_OK, return_value) | 441 EXPECT_EQ(RETURN_CODE_OK, return_value) |
410 << "element_id = " << element_id | 442 << "element_id = " << element_id |
411 << ", expected_value = " << expected_value; | 443 << ", expected_value = " << expected_value; |
412 } | 444 } |
413 | 445 |
414 void PasswordManagerBrowserTest::CheckElementValue( | 446 void PasswordManagerBrowserTest::CheckElementValue( |
415 const std::string& element_id, | 447 const std::string& element_id, |
416 const std::string& expected_value) { | 448 const std::string& expected_value) { |
| 449 PasswordManagerBrowserTest::CheckElementValue("null", |
| 450 element_id, |
| 451 expected_value); |
| 452 } |
| 453 |
| 454 void PasswordManagerBrowserTest::CheckElementValue( |
| 455 const std::string& iframe_id, |
| 456 const std::string& element_id, |
| 457 const std::string& expected_value) { |
417 const std::string value_check_script = base::StringPrintf( | 458 const std::string value_check_script = base::StringPrintf( |
418 "var element = document.getElementById('%s');" | 459 "if (%s)" |
| 460 " var element = document.getElementById(" |
| 461 " '%s').contentDocument.getElementById('%s');" |
| 462 "else " |
| 463 " var element = document.getElementById('%s');" |
419 "window.domAutomationController.send(element && element.value == '%s');", | 464 "window.domAutomationController.send(element && element.value == '%s');", |
| 465 iframe_id.c_str(), |
| 466 iframe_id.c_str(), |
| 467 element_id.c_str(), |
420 element_id.c_str(), | 468 element_id.c_str(), |
421 expected_value.c_str()); | 469 expected_value.c_str()); |
422 bool return_value = false; | 470 bool return_value = false; |
423 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( | 471 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( |
424 RenderViewHost(), value_check_script, &return_value)); | 472 RenderViewHost(), value_check_script, &return_value)); |
425 EXPECT_TRUE(return_value) << "element_id = " << element_id | 473 EXPECT_TRUE(return_value) << "element_id = " << element_id |
426 << ", expected_value = " << expected_value; | 474 << ", expected_value = " << expected_value; |
427 } | 475 } |
428 | 476 |
429 void PasswordManagerBrowserTest::ActivateHistoryPushState() { | 477 void PasswordManagerBrowserTest::ActivateHistoryPushState() { |
(...skipping 1476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1906 NavigateToFile("/password/password_xhr_submit.html"); | 1954 NavigateToFile("/password/password_xhr_submit.html"); |
1907 | 1955 |
1908 // Let the user interact with the page, so that DOM gets modification events, | 1956 // Let the user interact with the page, so that DOM gets modification events, |
1909 // needed for autofilling fields. | 1957 // needed for autofilling fields. |
1910 content::SimulateMouseClickAt( | 1958 content::SimulateMouseClickAt( |
1911 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(1, 1)); | 1959 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(1, 1)); |
1912 | 1960 |
1913 // Wait until that interaction causes the password value to be revealed. | 1961 // Wait until that interaction causes the password value to be revealed. |
1914 WaitForElementValue("password_field", "mypassword"); | 1962 WaitForElementValue("password_field", "mypassword"); |
1915 } | 1963 } |
| 1964 |
| 1965 // Check that a password form in an iframe of different origin will not be |
| 1966 // filled in until a user interact with the form. |
| 1967 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, CrossSiteIframeNotFillTest) { |
| 1968 // Setup the mock host resolver |
| 1969 host_resolver()->AddRule("*", "127.0.0.1"); |
| 1970 |
| 1971 // Here we need to dynamically create the iframe because the port |
| 1972 // embedded_test_server ran on was dynamically allocated, so the iframe's src |
| 1973 // attribute can only be determined at run time. |
| 1974 NavigateToFile("/password/password_form_in_crosssite_iframe.html"); |
| 1975 NavigationObserver ifrm_observer(WebContents()); |
| 1976 ifrm_observer.SetPathToWaitFor("/password/crossite_iframe_content.html"); |
| 1977 std::string create_iframe = base::StringPrintf( |
| 1978 "create_iframe(" |
| 1979 "'http://randomsite.net:%d/password/crossite_iframe_content.html');", |
| 1980 embedded_test_server()->port()); |
| 1981 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_iframe)); |
| 1982 ifrm_observer.Wait(); |
| 1983 |
| 1984 // Store a password for autofill later |
| 1985 NavigationObserver init_observer(WebContents()); |
| 1986 init_observer.SetPathToWaitFor("/password/done.html"); |
| 1987 scoped_ptr<PromptObserver> prompt_observer( |
| 1988 PromptObserver::Create(WebContents())); |
| 1989 std::string init_form = "sendMessage('fill_and_submit');"; |
| 1990 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), init_form)); |
| 1991 init_observer.Wait(); |
| 1992 EXPECT_TRUE(prompt_observer->IsShowingPrompt()); |
| 1993 prompt_observer->Accept(); |
| 1994 |
| 1995 // Visit the form again |
| 1996 NavigationObserver reload_observer(WebContents()); |
| 1997 NavigateToFile("/password/password_form_in_crosssite_iframe.html"); |
| 1998 reload_observer.Wait(); |
| 1999 |
| 2000 NavigationObserver ifrm_observer_2(WebContents()); |
| 2001 ifrm_observer_2.SetPathToWaitFor("/password/crossite_iframe_content.html"); |
| 2002 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_iframe)); |
| 2003 ifrm_observer_2.Wait(); |
| 2004 |
| 2005 // Verify username is not autofilled |
| 2006 std::string empty_username; |
| 2007 ASSERT_TRUE(content::ExecuteScriptAndExtractString( |
| 2008 RenderViewHost(), |
| 2009 "sendMessage('get_username');", |
| 2010 &empty_username)); |
| 2011 ASSERT_EQ("", empty_username); |
| 2012 // Verify password is not autofilled |
| 2013 std::string empty_password; |
| 2014 ASSERT_TRUE(content::ExecuteScriptAndExtractString( |
| 2015 RenderViewHost(), |
| 2016 "sendMessage('get_password');", |
| 2017 &empty_password)); |
| 2018 ASSERT_EQ("", empty_password); |
| 2019 |
| 2020 // Simulate the user interaction in the iframe and verify autofill is not |
| 2021 // triggered. Note this check is only best-effort because we don't know how |
| 2022 // long to wait before we are certain that no autofill will be triggered. |
| 2023 // Theoretically unexpected autofill can happen after this check. |
| 2024 ASSERT_TRUE(content::ExecuteScript( |
| 2025 RenderViewHost(), |
| 2026 "var iframeRect = document.getElementById(" |
| 2027 "'iframe').getBoundingClientRect();")); |
| 2028 int top; |
| 2029 ASSERT_TRUE(content::ExecuteScriptAndExtractInt( |
| 2030 RenderViewHost(), |
| 2031 "window.domAutomationController.send(iframeRect.top);", |
| 2032 &top)); |
| 2033 int left; |
| 2034 ASSERT_TRUE(content::ExecuteScriptAndExtractInt( |
| 2035 RenderViewHost(), |
| 2036 "window.domAutomationController.send(iframeRect.left);", |
| 2037 &left)); |
| 2038 |
| 2039 content::SimulateMouseClickAt( |
| 2040 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(left + 1, |
| 2041 top + 1)); |
| 2042 // Verify username is not autofilled |
| 2043 ASSERT_TRUE(content::ExecuteScriptAndExtractString( |
| 2044 RenderViewHost(), |
| 2045 "sendMessage('get_username');", |
| 2046 &empty_username)); |
| 2047 ASSERT_EQ("", empty_username); |
| 2048 // Verify password is not autofilled |
| 2049 ASSERT_TRUE(content::ExecuteScriptAndExtractString( |
| 2050 RenderViewHost(), |
| 2051 "sendMessage('get_password');", |
| 2052 &empty_password)); |
| 2053 ASSERT_EQ("", empty_password); |
| 2054 } |
| 2055 |
| 2056 // Check that a password form in an iframe of same origin will not be |
| 2057 // filled in until user interact with the iframe. |
| 2058 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, |
| 2059 SameOriginIframeAutoFillTest) { |
| 2060 // Visit the sign-up form to store a password for autofill later |
| 2061 NavigateToFile("/password/password_form_in_same_origin_iframe.html"); |
| 2062 NavigationObserver observer(WebContents()); |
| 2063 observer.SetPathToWaitFor("/password/done.html"); |
| 2064 scoped_ptr<PromptObserver> prompt_observer( |
| 2065 PromptObserver::Create(WebContents())); |
| 2066 |
| 2067 std::string submit = |
| 2068 "var ifrmDoc = document.getElementById('iframe').contentDocument;" |
| 2069 "ifrmDoc.getElementById('username_field').value = 'temp';" |
| 2070 "ifrmDoc.getElementById('password_field').value = 'pa55w0rd';" |
| 2071 "ifrmDoc.getElementById('input_submit_button').click();"; |
| 2072 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit)); |
| 2073 observer.Wait(); |
| 2074 EXPECT_TRUE(prompt_observer->IsShowingPrompt()); |
| 2075 prompt_observer->Accept(); |
| 2076 |
| 2077 // Visit the form again |
| 2078 NavigationObserver reload_observer(WebContents()); |
| 2079 NavigateToFile("/password/password_form_in_same_origin_iframe.html"); |
| 2080 reload_observer.Wait(); |
| 2081 |
| 2082 // Verify username is autofilled |
| 2083 CheckElementValue("iframe", "username_field", "temp"); |
| 2084 |
| 2085 // Verify password is not autofilled |
| 2086 CheckElementValue("iframe", "password_field", ""); |
| 2087 |
| 2088 // Simulate the user interaction in the iframe which should trigger autofill. |
| 2089 ASSERT_TRUE(content::ExecuteScript( |
| 2090 RenderViewHost(), |
| 2091 "var iframeRect = document.getElementById(" |
| 2092 "'iframe').getBoundingClientRect();")); |
| 2093 int top; |
| 2094 ASSERT_TRUE(content::ExecuteScriptAndExtractInt( |
| 2095 RenderViewHost(), |
| 2096 "window.domAutomationController.send(iframeRect.top);", |
| 2097 &top)); |
| 2098 int left; |
| 2099 ASSERT_TRUE(content::ExecuteScriptAndExtractInt( |
| 2100 RenderViewHost(), |
| 2101 "window.domAutomationController.send(iframeRect.left);", |
| 2102 &left)); |
| 2103 |
| 2104 content::SimulateMouseClickAt( |
| 2105 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(left + 1, |
| 2106 top + 1)); |
| 2107 // Verify password has been autofilled |
| 2108 WaitForElementValue("iframe", "password_field", "pa55w0rd"); |
| 2109 |
| 2110 // Verify username has been autofilled |
| 2111 CheckElementValue("iframe", "username_field", "temp"); |
| 2112 |
| 2113 } |
OLD | NEW |