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

Unified 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: Address CR comment Created 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | chrome/test/data/password/crossite_iframe_content.html » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/password_manager/password_manager_browsertest.cc
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc
index f759c2bb152c07a38ecf65c780b279a65185689a..df03e439cbc1262806c1c905e08f27843b698052 100644
--- a/chrome/browser/password_manager/password_manager_browsertest.cc
+++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -48,6 +48,7 @@
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "net/base/filename_util.h"
+#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
@@ -345,10 +346,18 @@ class PasswordManagerBrowserTest : public InProcessBrowserTest {
// event loop is spun to allow all other possible events to take place.
void WaitForElementValue(const std::string& element_id,
const std::string& expected_value);
+ // Same as above except the element |element_id| is in iframe |iframe_id|
+ void WaitForElementValue(const std::string& iframe_id,
+ const std::string& element_id,
+ const std::string& expected_value);
// Checks that the current "value" attribute of the HTML element with
// |element_id| is equal to |expected_value|.
void CheckElementValue(const std::string& element_id,
const std::string& expected_value);
+ // Same as above except the element |element_id| is in iframe |iframe_id|
+ void CheckElementValue(const std::string& iframe_id,
+ const std::string& element_id,
+ const std::string& expected_value);
// TODO(dvadym): Remove this once history.pushState() handling is not behind
// a flag.
@@ -366,6 +375,15 @@ class PasswordManagerBrowserTest : public InProcessBrowserTest {
void PasswordManagerBrowserTest::WaitForElementValue(
const std::string& element_id,
const std::string& expected_value) {
+ PasswordManagerBrowserTest::WaitForElementValue("null",
+ element_id,
+ expected_value);
+}
+
+void PasswordManagerBrowserTest::WaitForElementValue(
+ const std::string& iframe_id,
+ const std::string& element_id,
+ const std::string& expected_value) {
enum ReturnCodes { // Possible results of the JavaScript code.
RETURN_CODE_OK,
RETURN_CODE_NO_ELEMENT,
@@ -374,9 +392,16 @@ void PasswordManagerBrowserTest::WaitForElementValue(
};
const std::string value_check_function = base::StringPrintf(
"function valueCheck() {"
- " var element = document.getElementById('%s');"
+ " if (%s)"
+ " var element = document.getElementById("
+ " '%s').contentDocument.getElementById('%s');"
+ " else "
+ " var element = document.getElementById('%s');"
" return element && element.value == '%s';"
"}",
+ iframe_id.c_str(),
+ iframe_id.c_str(),
+ element_id.c_str(),
element_id.c_str(),
expected_value.c_str());
const std::string script =
@@ -386,7 +411,11 @@ void PasswordManagerBrowserTest::WaitForElementValue(
" /* Spin the event loop with setTimeout. */"
" setTimeout(window.domAutomationController.send(%d), 0);"
"} else {"
- " var element = document.getElementById('%s');"
+ " if (%s)"
+ " var element = document.getElementById("
+ " '%s').contentDocument.getElementById('%s');"
+ " else "
+ " var element = document.getElementById('%s');"
" if (!element)"
" window.domAutomationController.send(%d);"
" element.onchange = function() {"
@@ -399,6 +428,9 @@ void PasswordManagerBrowserTest::WaitForElementValue(
" };"
"}",
RETURN_CODE_OK,
+ iframe_id.c_str(),
+ iframe_id.c_str(),
+ element_id.c_str(),
element_id.c_str(),
RETURN_CODE_NO_ELEMENT,
RETURN_CODE_OK,
@@ -414,9 +446,25 @@ void PasswordManagerBrowserTest::WaitForElementValue(
void PasswordManagerBrowserTest::CheckElementValue(
const std::string& element_id,
const std::string& expected_value) {
+ PasswordManagerBrowserTest::CheckElementValue("null",
+ element_id,
+ expected_value);
+}
+
+void PasswordManagerBrowserTest::CheckElementValue(
+ const std::string& iframe_id,
+ const std::string& element_id,
+ const std::string& expected_value) {
const std::string value_check_script = base::StringPrintf(
- "var element = document.getElementById('%s');"
+ "if (%s)"
+ " var element = document.getElementById("
+ " '%s').contentDocument.getElementById('%s');"
+ "else "
+ " var element = document.getElementById('%s');"
"window.domAutomationController.send(element && element.value == '%s');",
+ iframe_id.c_str(),
+ iframe_id.c_str(),
+ element_id.c_str(),
element_id.c_str(),
expected_value.c_str());
bool return_value = false;
@@ -1913,3 +1961,122 @@ IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, BaseTagWithNoActionTest) {
// Wait until that interaction causes the password value to be revealed.
WaitForElementValue("password_field", "mypassword");
}
+
+// Check that a password form in an iframe of different origin will not be
+// filled in until a user interact with the form.
+IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, CrossSiteIframeNotFillTest) {
+ // Setup the mock host resolver
+ host_resolver()->AddRule("*", "127.0.0.1");
+
+ // Here we need to dynamically create the iframe because the port
+ // embedded_test_server ran on was dynamically allocated, so the iframe's src
+ // attribute can only be determined at run time.
+ NavigateToFile("/password/password_form_in_crosssite_iframe.html");
+ NavigationObserver ifrm_observer(WebContents());
+ ifrm_observer.SetPathToWaitFor("/password/crossite_iframe_content.html");
+
+ std::string submit = base::StringPrintf(
Garrett Casto 2015/05/28 18:08:18 Sorry, if this was clear, but the JS function name
xunlu 2015/05/28 22:28:16 Done.
+ "create_iframe("
+ "'http://randomsite.net:%d/password/crossite_iframe_content.html');",
+ embedded_test_server()->port());
+
+ ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
+ ifrm_observer.Wait();
+
+ NavigationObserver init_observer(WebContents());
+ init_observer.SetPathToWaitFor("/password/done.html");
+ scoped_ptr<PromptObserver> prompt_observer(
+ PromptObserver::Create(WebContents()));
+ // Store a password for autofill later
Garrett Casto 2015/05/28 18:08:18 Nit: This isn't a rule, but we generally value con
xunlu 2015/05/28 22:28:15 Done.
+ std::string init_form = "sendMessage('fill_and_submit');";
+ ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), init_form));
+ init_observer.Wait();
+ EXPECT_TRUE(prompt_observer->IsShowingPrompt());
+ prompt_observer->Accept();
+
+ // Visit the form again
+ NavigationObserver reload_observer(WebContents());
+ NavigateToFile("/password/password_form_in_crosssite_iframe.html");
+ reload_observer.Wait();
+
+ NavigationObserver ifrm_observer_2(WebContents());
+ ifrm_observer_2.SetPathToWaitFor("/password/crossite_iframe_content.html");
+ ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
+ ifrm_observer_2.Wait();
+
Garrett Casto 2015/05/28 18:08:18 So we talked about how it's probably okay here not
xunlu 2015/05/28 22:28:16 Done.
+ // Verfiy username is not autofilled
Garrett Casto 2015/05/28 18:08:18 "Verify"
xunlu 2015/05/28 22:28:16 Done.
+ std::string empty_username;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+ RenderViewHost(),
+ "sendMessage('get_username');",
+ &empty_username));
+ ASSERT_EQ("", empty_username);
+
+
+ // Verfiy password is not autofilled
Garrett Casto 2015/05/28 18:08:18 "Verify"
xunlu 2015/05/28 22:28:16 Done.
+ std::string empty_password;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+ RenderViewHost(),
+ "sendMessage('get_password');",
+ &empty_password));
+ ASSERT_EQ("", empty_password);
+}
+
+// Check that a password form in an iframe of same origin will not be
+// filled in until user interact with the iframe.
+IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
+ SameOriginIframeAutoFillTest) {
+ // Visit the sign-up form to store a password for autofill later
+ NavigateToFile("/password/password_form_in_same_origin_iframe.html");
+ NavigationObserver observer(WebContents());
+ observer.SetPathToWaitFor("/password/done.html");
+ scoped_ptr<PromptObserver> prompt_observer(
+ PromptObserver::Create(WebContents()));
+
+ std::string submit =
+ "var ifrmDoc = document.getElementById('iframe').contentDocument;"
+ "ifrmDoc.getElementById('username_field').value = 'temp';"
+ "ifrmDoc.getElementById('password_field').value = 'pa55w0rd';"
+ "ifrmDoc.getElementById('input_submit_button').click();";
+ ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
+ observer.Wait();
+ EXPECT_TRUE(prompt_observer->IsShowingPrompt());
+ prompt_observer->Accept();
+
+ // Visit the form again
+ NavigationObserver reload_observer(WebContents());
+ NavigateToFile("/password/password_form_in_same_origin_iframe.html");
+ reload_observer.Wait();
+
+ // Verfiy username is autofilled
Garrett Casto 2015/05/28 18:08:18 "Verify"
xunlu 2015/05/28 22:28:16 Done.
+ CheckElementValue("iframe", "username_field", "temp");
+
+ // Verfiy password is not autofilled
Garrett Casto 2015/05/28 18:08:18 "Verify"
xunlu 2015/05/28 22:28:16 Done.
+ CheckElementValue("iframe", "password_field", "");
+
+ // Simulate the user interaction in the iframe which should trigger autofill.
+ ASSERT_TRUE(content::ExecuteScript(
+ RenderViewHost(),
+ "var iframeRect = document.getElementById("
+ "'iframe').getBoundingClientRect();"));
+ int top;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
+ RenderViewHost(),
+ "window.domAutomationController.send(iframeRect.top);",
+ &top));
+ int left;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
+ RenderViewHost(),
+ "window.domAutomationController.send(iframeRect.left);",
+ &left));
+
+ content::SimulateMouseClickAt(
+ WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(left + 1,
+ top + 1));
+ // Verify password has been autofilled
+ WaitForElementValue("iframe", "password_field", "pa55w0rd");
+
+ // Verfiy username has been autofilled
Garrett Casto 2015/05/28 18:08:18 "Verify"
xunlu 2015/05/28 22:28:15 Done.
+ CheckElementValue("iframe", "username_field", "temp");
+
+}
« no previous file with comments | « no previous file | chrome/test/data/password/crossite_iframe_content.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698