| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 <vector> | 5 #include <vector> |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
| 9 #include "chrome/browser/chrome_content_browser_client.h" | 9 #include "chrome/browser/chrome_content_browser_client.h" |
| 10 #include "chrome/browser/ui/browser.h" | 10 #include "chrome/browser/ui/browser.h" |
| 11 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 11 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 12 #include "chrome/test/base/in_process_browser_test.h" | 12 #include "chrome/test/base/in_process_browser_test.h" |
| 13 #include "chrome/test/base/interactive_test_utils.h" | 13 #include "chrome/test/base/interactive_test_utils.h" |
| 14 #include "chrome/test/base/ui_test_utils.h" | 14 #include "chrome/test/base/ui_test_utils.h" |
| 15 #include "content/public/browser/browser_message_filter.h" | 15 #include "content/public/browser/browser_message_filter.h" |
| 16 #include "content/public/browser/content_browser_client.h" | 16 #include "content/public/browser/content_browser_client.h" |
| 17 #include "content/public/browser/render_frame_host.h" | 17 #include "content/public/browser/render_frame_host.h" |
| 18 #include "content/public/browser/render_process_host.h" | 18 #include "content/public/browser/render_process_host.h" |
| 19 #include "content/public/browser/render_widget_host_view.h" | 19 #include "content/public/browser/render_widget_host_view.h" |
| 20 #include "content/public/browser/web_contents.h" | 20 #include "content/public/browser/web_contents.h" |
| 21 #include "content/public/common/content_client.h" | 21 #include "content/public/common/content_client.h" |
| 22 #include "content/public/common/form_field_data.h" |
| 22 #include "content/public/test/browser_test_utils.h" | 23 #include "content/public/test/browser_test_utils.h" |
| 23 #include "content/public/test/content_browser_test_utils.h" | 24 #include "content/public/test/content_browser_test_utils.h" |
| 24 #include "content/public/test/test_utils.h" | 25 #include "content/public/test/test_utils.h" |
| 25 #include "content/public/test/text_input_test_utils.h" | 26 #include "content/public/test/text_input_test_utils.h" |
| 26 #include "net/dns/mock_host_resolver.h" | 27 #include "net/dns/mock_host_resolver.h" |
| 27 #include "net/test/embedded_test_server/embedded_test_server.h" | 28 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 28 #include "ui/base/ime/composition_underline.h" | 29 #include "ui/base/ime/composition_underline.h" |
| 29 #include "ui/base/ime/text_edit_commands.h" | 30 #include "ui/base/ime/text_edit_commands.h" |
| 30 #include "ui/base/ime/text_input_client.h" | 31 #include "ui/base/ime/text_input_client.h" |
| 31 #include "ui/base/ime/text_input_mode.h" | 32 #include "ui/base/ime/text_input_mode.h" |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 OnSuccess(); | 270 OnSuccess(); |
| 270 } | 271 } |
| 271 } | 272 } |
| 272 | 273 |
| 273 const content::RenderWidgetHostView* const expected_view_; | 274 const content::RenderWidgetHostView* const expected_view_; |
| 274 const size_t expected_length_; | 275 const size_t expected_length_; |
| 275 | 276 |
| 276 DISALLOW_COPY_AND_ASSIGN(ViewTextSelectionObserver); | 277 DISALLOW_COPY_AND_ASSIGN(ViewTextSelectionObserver); |
| 277 }; | 278 }; |
| 278 | 279 |
| 280 // This class is used to verify the result of form field data requests. |
| 281 class FormFieldDataVerifier { |
| 282 public: |
| 283 FormFieldDataVerifier(const std::string& text, const std::string& placeholder) |
| 284 : text_(text), placeholder_(placeholder), success_(false) {} |
| 285 |
| 286 void Verify(const content::FormFieldData& field) { |
| 287 ASSERT_EQ(field.text, text_); |
| 288 ASSERT_EQ(field.placeholder, placeholder_); |
| 289 OnSuccess(); |
| 290 } |
| 291 |
| 292 // Wait for success_ to be true. |
| 293 void Wait() { |
| 294 if (success_) |
| 295 return; |
| 296 message_loop_runner_ = new content::MessageLoopRunner(); |
| 297 message_loop_runner_->Run(); |
| 298 } |
| 299 |
| 300 private: |
| 301 void OnSuccess() { |
| 302 success_ = true; |
| 303 if (message_loop_runner_) |
| 304 message_loop_runner_->Quit(); |
| 305 } |
| 306 |
| 307 std::string text_; |
| 308 std::string placeholder_; |
| 309 |
| 310 bool success_; |
| 311 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; |
| 312 |
| 313 DISALLOW_COPY_AND_ASSIGN(FormFieldDataVerifier); |
| 314 }; |
| 315 |
| 279 // This class monitors all the changes in TextInputState and keeps a record of | 316 // This class monitors all the changes in TextInputState and keeps a record of |
| 280 // the active views. There is no waiting and the recording process is | 317 // the active views. There is no waiting and the recording process is |
| 281 // continuous. | 318 // continuous. |
| 282 class RecordActiveViewsObserver { | 319 class RecordActiveViewsObserver { |
| 283 public: | 320 public: |
| 284 explicit RecordActiveViewsObserver(content::WebContents* web_contents) | 321 explicit RecordActiveViewsObserver(content::WebContents* web_contents) |
| 285 : tester_(new content::TextInputManagerTester(web_contents)) { | 322 : tester_(new content::TextInputManagerTester(web_contents)) { |
| 286 tester_->SetUpdateTextInputStateCalledCallback(base::Bind( | 323 tester_->SetUpdateTextInputStateCalledCallback(base::Bind( |
| 287 &RecordActiveViewsObserver::RecordActiveView, base::Unretained(this))); | 324 &RecordActiveViewsObserver::RecordActiveView, base::Unretained(this))); |
| 288 } | 325 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 "var input = document.createElement('input');" | 381 "var input = document.createElement('input');" |
| 345 "input.setAttribute('type', '%s');" | 382 "input.setAttribute('type', '%s');" |
| 346 "input.setAttribute('value', '%s');" | 383 "input.setAttribute('value', '%s');" |
| 347 "document.body.%s;", | 384 "document.body.%s;", |
| 348 type.c_str(), value.c_str(), | 385 type.c_str(), value.c_str(), |
| 349 append_as_first_child ? "insertBefore(input, document.body.firstChild)" | 386 append_as_first_child ? "insertBefore(input, document.body.firstChild)" |
| 350 : "appendChild(input)"); | 387 : "appendChild(input)"); |
| 351 EXPECT_TRUE(ExecuteScript(rfh, script)); | 388 EXPECT_TRUE(ExecuteScript(rfh, script)); |
| 352 } | 389 } |
| 353 | 390 |
| 391 // static |
| 392 // Appends an <input> field with various attribues to a given frame by |
| 393 // executing javascript code. |
| 394 static void AppendInputFieldToFrame(content::RenderFrameHost* rfh, |
| 395 const std::string& type, |
| 396 const std::string& id, |
| 397 const std::string& value, |
| 398 const std::string& placeholder) { |
| 399 std::string script = base::StringPrintf( |
| 400 "var input = document.createElement('input');" |
| 401 "input.setAttribute('type', '%s');" |
| 402 "input.setAttribute('id', '%s');" |
| 403 "input.setAttribute('value', '%s');" |
| 404 "input.setAttribute('placeholder', '%s');" |
| 405 "document.body.appendChild(input);", |
| 406 type.c_str(), id.c_str(), value.c_str(), placeholder.c_str()); |
| 407 EXPECT_TRUE(ExecuteScript(rfh, script)); |
| 408 } |
| 409 |
| 410 // static |
| 411 // Focus a form field by its Id. |
| 412 static void FocusFormField(content::RenderFrameHost* rfh, |
| 413 const std::string& id) { |
| 414 std::string script = base::StringPrintf( |
| 415 "document.getElementById('%s').focus();", id.c_str()); |
| 416 |
| 417 EXPECT_TRUE(ExecuteScript(rfh, script)); |
| 418 } |
| 419 |
| 354 // Uses 'cross_site_iframe_factory.html'. The main frame's domain is | 420 // Uses 'cross_site_iframe_factory.html'. The main frame's domain is |
| 355 // 'a.com'. | 421 // 'a.com'. |
| 356 void CreateIframePage(const std::string& structure) { | 422 void CreateIframePage(const std::string& structure) { |
| 357 std::string path = base::StringPrintf("/cross_site_iframe_factory.html?%s", | 423 std::string path = base::StringPrintf("/cross_site_iframe_factory.html?%s", |
| 358 structure.c_str()); | 424 structure.c_str()); |
| 359 GURL main_url(embedded_test_server()->GetURL("a.com", path)); | 425 GURL main_url(embedded_test_server()->GetURL("a.com", path)); |
| 360 ui_test_utils::NavigateToURL(browser(), main_url); | 426 ui_test_utils::NavigateToURL(browser(), main_url); |
| 361 } | 427 } |
| 362 | 428 |
| 363 // Iteratively uses ChildFrameAt(frame, i) to get the i-th child frame | 429 // Iteratively uses ChildFrameAt(frame, i) to get the i-th child frame |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 695 for (size_t i = 0; i < views.size(); ++i) { | 761 for (size_t i = 0; i < views.size(); ++i) { |
| 696 // First focus the <input>. | 762 // First focus the <input>. |
| 697 send_tab_and_wait_for_value(values[i]); | 763 send_tab_and_wait_for_value(values[i]); |
| 698 | 764 |
| 699 // Send a sequence of |count| 'E' keys and wait until the view receives a | 765 // Send a sequence of |count| 'E' keys and wait until the view receives a |
| 700 // selection change update for a text of the corresponding size, |count|. | 766 // selection change update for a text of the corresponding size, |count|. |
| 701 send_keys_select_all_wait_for_selection_change(views[i], count++); | 767 send_keys_select_all_wait_for_selection_change(views[i], count++); |
| 702 } | 768 } |
| 703 } | 769 } |
| 704 | 770 |
| 771 // This test creates a page with multiple child frames and adds two <input> |
| 772 // elements to each frame. Then, sequentially, each <input> is focused through |
| 773 // javascript. For each frame, its text and placeholder attributes are queried |
| 774 // through RenderFrameHost and verified against expected values. |
| 775 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest, |
| 776 RequestFocusedFormFieldDataForMultipleIFrames) { |
| 777 CreateIframePage("a(b, c)"); |
| 778 std::vector<content::RenderFrameHost*> frames{GetFrame(IndexVector{}), |
| 779 GetFrame(IndexVector{0}), |
| 780 GetFrame(IndexVector{1})}; |
| 781 |
| 782 std::vector<std::string> values{"main_1", "main_2", "node_b_1", |
| 783 "node_b_2", "node_c_1", "node_c_2"}; |
| 784 std::vector<std::string> placeholders{ |
| 785 "placeholder_main_1", "placeholder_main_2", "placeholder_node_b_1", |
| 786 "placeholder_node_b_2", "placeholder_node_c_1", "placeholder_node_c_2"}; |
| 787 |
| 788 for (size_t i = 0; i < values.size(); ++i) { |
| 789 AppendInputFieldToFrame(frames[i / 2], "text", values[i], values[i], |
| 790 placeholders[i]); |
| 791 } |
| 792 |
| 793 for (size_t i = 0; i < values.size(); ++i) { |
| 794 content::RenderFrameHost* frame = frames[i / 2]; |
| 795 FocusFormField(frame, values[i]); |
| 796 FormFieldDataVerifier verifier(values[i], placeholders[i]); |
| 797 content::FormFieldDataCallback callback = |
| 798 base::Bind(&FormFieldDataVerifier::Verify, base::Unretained(&verifier)); |
| 799 frame->RequestFocusedFormFieldData(callback); |
| 800 verifier.Wait(); |
| 801 } |
| 802 } |
| 803 |
| 705 // The following test verifies that when the active widget changes value, it is | 804 // The following test verifies that when the active widget changes value, it is |
| 706 // always from nullptr to non-null or vice versa. | 805 // always from nullptr to non-null or vice versa. |
| 707 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest, | 806 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest, |
| 708 ResetTextInputStateOnActiveWidgetChange) { | 807 ResetTextInputStateOnActiveWidgetChange) { |
| 709 CreateIframePage("a(b,c(a,b),d)"); | 808 CreateIframePage("a(b,c(a,b),d)"); |
| 710 std::vector<content::RenderFrameHost*> frames{ | 809 std::vector<content::RenderFrameHost*> frames{ |
| 711 GetFrame(IndexVector{}), GetFrame(IndexVector{0}), | 810 GetFrame(IndexVector{}), GetFrame(IndexVector{0}), |
| 712 GetFrame(IndexVector{1}), GetFrame(IndexVector{1, 0}), | 811 GetFrame(IndexVector{1}), GetFrame(IndexVector{1, 0}), |
| 713 GetFrame(IndexVector{1, 1}), GetFrame(IndexVector{2})}; | 812 GetFrame(IndexVector{1, 1}), GetFrame(IndexVector{2})}; |
| 714 std::vector<content::RenderWidgetHostView*> views; | 813 std::vector<content::RenderWidgetHostView*> views; |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1123 // Test ends here. The rest is cleanup. | 1222 // Test ends here. The rest is cleanup. |
| 1124 | 1223 |
| 1125 // Closing this WebContents while we still hold on to our TestBrowserClient. | 1224 // Closing this WebContents while we still hold on to our TestBrowserClient. |
| 1126 EXPECT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt( | 1225 EXPECT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt( |
| 1127 1, TabStripModel::CLOSE_USER_GESTURE)); | 1226 1, TabStripModel::CLOSE_USER_GESTURE)); |
| 1128 | 1227 |
| 1129 // For the cleanup of the original WebContents in tab index 0. | 1228 // For the cleanup of the original WebContents in tab index 0. |
| 1130 content::SetBrowserClientForTesting(old_browser_client); | 1229 content::SetBrowserClientForTesting(old_browser_client); |
| 1131 } | 1230 } |
| 1132 #endif | 1231 #endif |
| OLD | NEW |