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 <stddef.h> | 5 #include <stddef.h> |
6 | 6 |
| 7 #include <limits> |
| 8 |
7 #include "base/location.h" | 9 #include "base/location.h" |
8 #include "base/macros.h" | 10 #include "base/macros.h" |
9 #include "base/single_thread_task_runner.h" | 11 #include "base/single_thread_task_runner.h" |
10 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
11 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
12 #include "base/test/scoped_feature_list.h" | 14 #include "base/test/scoped_feature_list.h" |
13 #include "base/test/test_timeouts.h" | 15 #include "base/test/test_timeouts.h" |
14 #include "base/threading/thread_task_runner_handle.h" | 16 #include "base/threading/thread_task_runner_handle.h" |
15 #include "build/build_config.h" | 17 #include "build/build_config.h" |
16 #include "chrome/app/chrome_command_ids.h" | 18 #include "chrome/app/chrome_command_ids.h" |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 } else { | 557 } else { |
556 scoped_feature_list_.InitAndDisableFeature( | 558 scoped_feature_list_.InitAndDisableFeature( |
557 features::kGuestViewCrossProcessFrames); | 559 features::kGuestViewCrossProcessFrames); |
558 } | 560 } |
559 } | 561 } |
560 | 562 |
561 private: | 563 private: |
562 base::test::ScopedFeatureList scoped_feature_list_; | 564 base::test::ScopedFeatureList scoped_feature_list_; |
563 }; | 565 }; |
564 | 566 |
| 567 class WebViewImeInteractiveTest : public WebViewInteractiveTest { |
| 568 protected: |
| 569 // This class observes all the composition range updates associated with the |
| 570 // TextInputManager of the provided WebContents. The WebContents should be an |
| 571 // outer most WebContents. |
| 572 class CompositionRangeUpdateObserver { |
| 573 public: |
| 574 explicit CompositionRangeUpdateObserver(content::WebContents* web_contents) |
| 575 : tester_(web_contents) { |
| 576 tester_.SetOnImeCompositionRangeChangedCallback( |
| 577 base::Bind(&CompositionRangeUpdateObserver::OnCompositionRangeUpdated, |
| 578 base::Unretained(this))); |
| 579 } |
| 580 ~CompositionRangeUpdateObserver() {} |
| 581 |
| 582 // Wait until a composition range update with a range length equal to |
| 583 // |length| is received. |
| 584 void WaitForCompositionRangeLength(uint32_t length) { |
| 585 if (last_composition_range_length_.has_value() && |
| 586 last_composition_range_length_.value() == length) |
| 587 return; |
| 588 expected_length_ = length; |
| 589 run_loop_.reset(new base::RunLoop()); |
| 590 run_loop_->Run(); |
| 591 } |
| 592 |
| 593 private: |
| 594 void OnCompositionRangeUpdated() { |
| 595 uint32_t length = std::numeric_limits<uint32_t>::max(); |
| 596 if (tester_.GetLastCompositionRangeLength(&length)) { |
| 597 last_composition_range_length_ = length; |
| 598 } |
| 599 if (last_composition_range_length_.value() == expected_length_) |
| 600 run_loop_->Quit(); |
| 601 } |
| 602 |
| 603 content::TextInputManagerTester tester_; |
| 604 std::unique_ptr<base::RunLoop> run_loop_; |
| 605 base::Optional<uint32_t> last_composition_range_length_; |
| 606 uint32_t expected_length_ = 0; |
| 607 |
| 608 DISALLOW_COPY_AND_ASSIGN(CompositionRangeUpdateObserver); |
| 609 }; |
| 610 }; |
| 611 |
565 class WebViewDragDropInteractiveTest : public WebViewInteractiveTest {}; | 612 class WebViewDragDropInteractiveTest : public WebViewInteractiveTest {}; |
566 class WebViewNewWindowInteractiveTest : public WebViewInteractiveTest {}; | 613 class WebViewNewWindowInteractiveTest : public WebViewInteractiveTest {}; |
567 class WebViewFocusInteractiveTest : public WebViewInteractiveTest {}; | 614 class WebViewFocusInteractiveTest : public WebViewInteractiveTest {}; |
568 class WebViewPointerLockInteractiveTest : public WebViewInteractiveTest {}; | 615 class WebViewPointerLockInteractiveTest : public WebViewInteractiveTest {}; |
569 class WebViewImeInteractiveTest : public WebViewInteractiveTest {}; | |
570 | 616 |
571 // The tests below aren't needed in --use-cross-process-frames-for-guests. | 617 // The tests below aren't needed in --use-cross-process-frames-for-guests. |
572 class WebViewContextMenuInteractiveTest : public WebViewInteractiveTestBase {}; | 618 class WebViewContextMenuInteractiveTest : public WebViewInteractiveTestBase {}; |
573 | 619 |
574 // The following class of tests do not work for OOPIF <webview>. | 620 // The following class of tests do not work for OOPIF <webview>. |
575 // TODO(ekaramad): Make this tests work with OOPIF and replace the test classes | 621 // TODO(ekaramad): Make this tests work with OOPIF and replace the test classes |
576 // with WebViewInteractiveTest (see crbug.com/582562). | 622 // with WebViewInteractiveTest (see crbug.com/582562). |
577 class WebViewPopupInteractiveTest : public WebViewInteractiveTestBase {}; | 623 class WebViewPopupInteractiveTest : public WebViewInteractiveTestBase {}; |
578 | 624 |
579 INSTANTIATE_TEST_CASE_P(WebViewInteractiveTests, | 625 INSTANTIATE_TEST_CASE_P(WebViewInteractiveTests, |
(...skipping 1066 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1646 | 1692 |
1647 // Click the <input> element inside the <webview>. In its focus handle, the | 1693 // Click the <input> element inside the <webview>. In its focus handle, the |
1648 // <input> inside the <webview> initializes its value to "A B X D". | 1694 // <input> inside the <webview> initializes its value to "A B X D". |
1649 ExtensionTestMessageListener focus_listener("WebViewImeTest.InputFocused", | 1695 ExtensionTestMessageListener focus_listener("WebViewImeTest.InputFocused", |
1650 false); | 1696 false); |
1651 content::WebContents* target_web_contents = | 1697 content::WebContents* target_web_contents = |
1652 GetParam() | 1698 GetParam() |
1653 ? guest_web_contents | 1699 ? guest_web_contents |
1654 : guest_view::GuestViewBase::FromWebContents(guest_web_contents) | 1700 : guest_view::GuestViewBase::FromWebContents(guest_web_contents) |
1655 ->embedder_web_contents(); | 1701 ->embedder_web_contents(); |
| 1702 |
| 1703 // The guest page has a large input box and (50, 50) lies inside the box. |
1656 content::SimulateMouseClickAt(target_web_contents, 0, | 1704 content::SimulateMouseClickAt(target_web_contents, 0, |
1657 blink::WebMouseEvent::Button::kLeft, | 1705 blink::WebMouseEvent::Button::kLeft, |
1658 gfx::Point(50, 50)); | 1706 gfx::Point(50, 50)); |
1659 focus_listener.WaitUntilSatisfied(); | 1707 focus_listener.WaitUntilSatisfied(); |
1660 | 1708 |
1661 // Verify the text inside the <input> is "A B X D". | 1709 // Verify the text inside the <input> is "A B X D". |
1662 std::string value; | 1710 std::string value; |
1663 ASSERT_TRUE(ExecuteScriptAndExtractString(guest_web_contents, | 1711 ASSERT_TRUE(ExecuteScriptAndExtractString(guest_web_contents, |
1664 "window.domAutomationController." | 1712 "window.domAutomationController." |
1665 "send(document.querySelector('" | 1713 "send(document.querySelector('" |
(...skipping 16 matching lines...) Expand all Loading... |
1682 // Get the input value from the guest. | 1730 // Get the input value from the guest. |
1683 value.clear(); | 1731 value.clear(); |
1684 ASSERT_TRUE(ExecuteScriptAndExtractString(guest_web_contents, | 1732 ASSERT_TRUE(ExecuteScriptAndExtractString(guest_web_contents, |
1685 "window.domAutomationController." | 1733 "window.domAutomationController." |
1686 "send(document.querySelector('" | 1734 "send(document.querySelector('" |
1687 "input').value)", | 1735 "input').value)", |
1688 &value)); | 1736 &value)); |
1689 EXPECT_EQ("A B C D", value); | 1737 EXPECT_EQ("A B C D", value); |
1690 } | 1738 } |
1691 #endif // OS_MACOSX | 1739 #endif // OS_MACOSX |
| 1740 |
| 1741 // This test verifies that focusing an input inside a <webview> will put the |
| 1742 // guest process's render widget into a monitoring mode for composition range |
| 1743 // changes. |
| 1744 IN_PROC_BROWSER_TEST_P(WebViewImeInteractiveTest, CompositionRangeUpdates) { |
| 1745 ASSERT_TRUE(StartEmbeddedTestServer()); // For serving guest pages. |
| 1746 LoadAndLaunchPlatformApp("web_view/ime", "WebViewImeTest.Launched"); |
| 1747 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(GetPlatformAppWindow())); |
| 1748 |
| 1749 // Flush any pending events to make sure we start with a clean slate. |
| 1750 content::RunAllPendingInMessageLoop(); |
| 1751 |
| 1752 content::WebContents* guest_web_contents = |
| 1753 GetGuestViewManager()->GetLastGuestCreated(); |
| 1754 |
| 1755 // Click the <input> element inside the <webview>. In its focus handle, the |
| 1756 // <input> inside the <webview> initializes its value to "A B X D". |
| 1757 ExtensionTestMessageListener focus_listener("WebViewImeTest.InputFocused", |
| 1758 false); |
| 1759 content::WebContents* embedder_web_contents = |
| 1760 guest_view::GuestViewBase::FromWebContents(guest_web_contents) |
| 1761 ->embedder_web_contents(); |
| 1762 |
| 1763 // Event routing in OOPIF and non-OOPIF <webview> is different. With OOPIF, |
| 1764 // input is directly routed to the guest process as opposed to the non OOPIF |
| 1765 // mode where input is always sent to the embedder process first (then hops |
| 1766 // back to the browser and then to the guest). |
| 1767 content::WebContents* target_web_contents = |
| 1768 GetParam() ? guest_web_contents : embedder_web_contents; |
| 1769 |
| 1770 // The guest page has a large input box and (50, 50) lies inside the box. |
| 1771 content::SimulateMouseClickAt(target_web_contents, 0, |
| 1772 blink::WebMouseEvent::Button::kLeft, |
| 1773 gfx::Point(50, 50)); |
| 1774 focus_listener.WaitUntilSatisfied(); |
| 1775 |
| 1776 // Clear the string as it already contains some text. Then verify the text in |
| 1777 // the <input> is empty. |
| 1778 std::string value; |
| 1779 ASSERT_TRUE(ExecuteScriptAndExtractString( |
| 1780 guest_web_contents, |
| 1781 "var input = document.querySelector('input');" |
| 1782 "input.value = '';" |
| 1783 "window.domAutomationController.send(" |
| 1784 " document.querySelector('input').value)", |
| 1785 &value)); |
| 1786 EXPECT_EQ("", value); |
| 1787 |
| 1788 // Now set some composition text which should lead to an update in composition |
| 1789 // range information. |
| 1790 CompositionRangeUpdateObserver observer(embedder_web_contents); |
| 1791 content::SendImeSetCompositionTextToWidget( |
| 1792 target_web_contents->GetRenderWidgetHostView()->GetRenderWidgetHost(), |
| 1793 base::UTF8ToUTF16("ABC"), std::vector<ui::CompositionUnderline>(), |
| 1794 gfx::Range::InvalidRange(), 0, 3); |
| 1795 observer.WaitForCompositionRangeLength(3U); |
| 1796 } |
OLD | NEW |