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

Side by Side Diff: chrome/browser/password_manager/password_manager_browsertest.cc

Issue 1159513002: Allow autofill in iframe inside page of same origin (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove PasswordAutofillAgentTest.IframeNoFillTest Created 5 years, 6 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
« no previous file with comments | « no previous file | chrome/renderer/autofill/password_autofill_agent_browsertest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | chrome/renderer/autofill/password_autofill_agent_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698