| Index: chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
|
| diff --git a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
|
| index bb73b4fe9207709e5c618f3918288c9d45948e4e..16e72bf11b4f123970c4be0bcdb0ebea3bca37c2 100644
|
| --- a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
|
| +++ b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
|
| @@ -19,6 +19,7 @@
|
| #include "content/public/browser/render_widget_host_view.h"
|
| #include "content/public/browser/web_contents.h"
|
| #include "content/public/common/content_client.h"
|
| +#include "content/public/common/form_field_data.h"
|
| #include "content/public/test/browser_test_utils.h"
|
| #include "content/public/test/content_browser_test_utils.h"
|
| #include "content/public/test/test_utils.h"
|
| @@ -274,6 +275,42 @@
|
| const size_t expected_length_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(ViewTextSelectionObserver);
|
| +};
|
| +
|
| +// This class is used to verify the result of form field data requests.
|
| +class FormFieldDataVerifier {
|
| + public:
|
| + FormFieldDataVerifier(const std::string& text, const std::string& placeholder)
|
| + : text_(text), placeholder_(placeholder), success_(false) {}
|
| +
|
| + void Verify(const content::FormFieldData& field) {
|
| + ASSERT_EQ(field.text, text_);
|
| + ASSERT_EQ(field.placeholder, placeholder_);
|
| + OnSuccess();
|
| + }
|
| +
|
| + // Wait for success_ to be true.
|
| + void Wait() {
|
| + if (success_)
|
| + return;
|
| + message_loop_runner_ = new content::MessageLoopRunner();
|
| + message_loop_runner_->Run();
|
| + }
|
| +
|
| + private:
|
| + void OnSuccess() {
|
| + success_ = true;
|
| + if (message_loop_runner_)
|
| + message_loop_runner_->Quit();
|
| + }
|
| +
|
| + std::string text_;
|
| + std::string placeholder_;
|
| +
|
| + bool success_;
|
| + scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(FormFieldDataVerifier);
|
| };
|
|
|
| // This class monitors all the changes in TextInputState and keeps a record of
|
| @@ -351,6 +388,35 @@
|
| EXPECT_TRUE(ExecuteScript(rfh, script));
|
| }
|
|
|
| + // static
|
| + // Appends an <input> field with various attribues to a given frame by
|
| + // executing javascript code.
|
| + static void AppendInputFieldToFrame(content::RenderFrameHost* rfh,
|
| + const std::string& type,
|
| + const std::string& id,
|
| + const std::string& value,
|
| + const std::string& placeholder) {
|
| + std::string script = base::StringPrintf(
|
| + "var input = document.createElement('input');"
|
| + "input.setAttribute('type', '%s');"
|
| + "input.setAttribute('id', '%s');"
|
| + "input.setAttribute('value', '%s');"
|
| + "input.setAttribute('placeholder', '%s');"
|
| + "document.body.appendChild(input);",
|
| + type.c_str(), id.c_str(), value.c_str(), placeholder.c_str());
|
| + EXPECT_TRUE(ExecuteScript(rfh, script));
|
| + }
|
| +
|
| + // static
|
| + // Focus a form field by its Id.
|
| + static void FocusFormField(content::RenderFrameHost* rfh,
|
| + const std::string& id) {
|
| + std::string script = base::StringPrintf(
|
| + "document.getElementById('%s').focus();", id.c_str());
|
| +
|
| + EXPECT_TRUE(ExecuteScript(rfh, script));
|
| + }
|
| +
|
| // Uses 'cross_site_iframe_factory.html'. The main frame's domain is
|
| // 'a.com'.
|
| void CreateIframePage(const std::string& structure) {
|
| @@ -702,6 +768,39 @@
|
| }
|
| }
|
|
|
| +// This test creates a page with multiple child frames and adds two <input>
|
| +// elements to each frame. Then, sequentially, each <input> is focused through
|
| +// javascript. For each frame, its text and placeholder attributes are queried
|
| +// through RenderFrameHost and verified against expected values.
|
| +IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
|
| + RequestFocusedFormFieldDataForMultipleIFrames) {
|
| + CreateIframePage("a(b, c)");
|
| + std::vector<content::RenderFrameHost*> frames{GetFrame(IndexVector{}),
|
| + GetFrame(IndexVector{0}),
|
| + GetFrame(IndexVector{1})};
|
| +
|
| + std::vector<std::string> values{"main_1", "main_2", "node_b_1",
|
| + "node_b_2", "node_c_1", "node_c_2"};
|
| + std::vector<std::string> placeholders{
|
| + "placeholder_main_1", "placeholder_main_2", "placeholder_node_b_1",
|
| + "placeholder_node_b_2", "placeholder_node_c_1", "placeholder_node_c_2"};
|
| +
|
| + for (size_t i = 0; i < values.size(); ++i) {
|
| + AppendInputFieldToFrame(frames[i / 2], "text", values[i], values[i],
|
| + placeholders[i]);
|
| + }
|
| +
|
| + for (size_t i = 0; i < values.size(); ++i) {
|
| + content::RenderFrameHost* frame = frames[i / 2];
|
| + FocusFormField(frame, values[i]);
|
| + FormFieldDataVerifier verifier(values[i], placeholders[i]);
|
| + content::FormFieldDataCallback callback =
|
| + base::Bind(&FormFieldDataVerifier::Verify, base::Unretained(&verifier));
|
| + frame->RequestFocusedFormFieldData(callback);
|
| + verifier.Wait();
|
| + }
|
| +}
|
| +
|
| // The following test verifies that when the active widget changes value, it is
|
| // always from nullptr to non-null or vice versa.
|
| IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
|
|
|