Commit 3ba2a7ed authored by Anupam Snigdha's avatar Anupam Snigdha Committed by Commit Bot

Rewrite Virtual Keyboard API tests without touch injection APIs.

On 1909 Windows builds, it looks like the touch injection APIs are
very flaky and thus leading to increased flakiness in the VK API
tests that use touch gesture to show/hide VK and test the VK policy.
In this change I've rewritten all the tests using simulated touch
gesture APIs that don't use system touch injections.

Bug: 1108551

Change-Id: I936f4835cc3688b865ec8f1587c4d8a6eaba2a36
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2368158Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Commit-Queue: Anupam Snigdha <snianu@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#800646}
parent 2d32c60f
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/windows_version.h"
#include "build/build_config.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/text_input_test_utils.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/base/test/ui_controls.h"
#include "ui/events/keycodes/keyboard_codes.h"
namespace {
const int kTextAreaHeight = 36;
const int kTextAreaWidth = 162;
const int kTextAreaOffsetX = 100;
// TextInputManager Observers
// A base class for observing the TextInputManager owned by the given
// WebContents. Subclasses could observe the TextInputManager for different
// changes. The class wraps a public tester which accepts callbacks that
// are run after specific changes in TextInputManager. Different observers can
// be subclassed from this by providing their specific callback methods.
class TextInputManagerObserverBase {
public:
explicit TextInputManagerObserverBase(content::WebContents* web_contents)
: tester_(new content::TextInputManagerTester(web_contents)),
success_(false) {}
virtual ~TextInputManagerObserverBase() {}
// Wait for derived class's definition of success.
void Wait() {
if (success_)
return;
run_loop.Run();
}
bool success() const { return success_; }
protected:
content::TextInputManagerTester* tester() { return tester_.get(); }
void OnSuccess() {
success_ = true;
run_loop.Quit();
// By deleting |tester_| we make sure that the internal observer used in
// content/ is removed from the observer list of TextInputManager.
tester_.reset(nullptr);
}
private:
std::unique_ptr<content::TextInputManagerTester> tester_;
bool success_;
base::RunLoop run_loop;
DISALLOW_COPY_AND_ASSIGN(TextInputManagerObserverBase);
};
// This class observes TextInputManager for changes in
// |TextInputState.vk_policy|.
class TextInputManagerVkPolicyObserver : public TextInputManagerObserverBase {
public:
TextInputManagerVkPolicyObserver(
content::WebContents* web_contents,
ui::mojom::VirtualKeyboardPolicy expected_value)
: TextInputManagerObserverBase(web_contents),
expected_value_(expected_value) {
tester()->SetUpdateTextInputStateCalledCallback(
base::BindRepeating(&TextInputManagerVkPolicyObserver::VerifyVkPolicy,
base::Unretained(this)));
}
private:
void VerifyVkPolicy() {
ui::mojom::VirtualKeyboardPolicy value;
if (tester()->GetTextInputVkPolicy(&value) && expected_value_ == value)
OnSuccess();
}
ui::mojom::VirtualKeyboardPolicy expected_value_;
DISALLOW_COPY_AND_ASSIGN(TextInputManagerVkPolicyObserver);
};
// This class observes TextInputManager for changes in
// |TextInputState.last_vk_visibility_request|.
class TextInputManagerVkVisibilityRequestObserver
: public TextInputManagerObserverBase {
public:
TextInputManagerVkVisibilityRequestObserver(
content::WebContents* web_contents,
ui::mojom::VirtualKeyboardVisibilityRequest expected_value)
: TextInputManagerObserverBase(web_contents),
expected_value_(expected_value) {
tester()->SetUpdateTextInputStateCalledCallback(base::BindRepeating(
&TextInputManagerVkVisibilityRequestObserver::VerifyVkVisibilityRequest,
base::Unretained(this)));
}
private:
void VerifyVkVisibilityRequest() {
ui::mojom::VirtualKeyboardVisibilityRequest value;
if (tester()->GetTextInputVkVisibilityRequest(&value) &&
expected_value_ == value)
OnSuccess();
}
ui::mojom::VirtualKeyboardVisibilityRequest expected_value_;
DISALLOW_COPY_AND_ASSIGN(TextInputManagerVkVisibilityRequestObserver);
};
// This class observes TextInputManager for changes in
// |TextInputState.show_ime_if_needed|.
class TextInputManagerShowImeIfNeededObserver
: public TextInputManagerObserverBase {
public:
TextInputManagerShowImeIfNeededObserver(content::WebContents* web_contents,
bool expected_value)
: TextInputManagerObserverBase(web_contents),
expected_value_(expected_value) {
tester()->SetUpdateTextInputStateCalledCallback(base::BindRepeating(
&TextInputManagerShowImeIfNeededObserver::VerifyShowImeIfNeeded,
base::Unretained(this)));
}
private:
void VerifyShowImeIfNeeded() {
bool show_ime_if_needed;
if (tester()->GetTextInputShowImeIfNeeded(&show_ime_if_needed) &&
expected_value_ == show_ime_if_needed)
OnSuccess();
}
bool expected_value_;
DISALLOW_COPY_AND_ASSIGN(TextInputManagerShowImeIfNeededObserver);
};
class VirtualKeyboardPolicyTest : public InProcessBrowserTest {
public:
VirtualKeyboardPolicyTest() {}
// InProcessBrowserTest:
void SetUpOnMainThread() override {
ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
}
content::WebContents* GetActiveWebContents() const {
return browser()->tab_strip_model()->GetActiveWebContents();
}
ui::BaseWindow* GetWindow() const { return browser()->window(); }
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
"VirtualKeyboard,EditContext");
InProcessBrowserTest::SetUpCommandLine(command_line);
}
// Wait for the active web contents title to match |title|.
void WaitForTitle(const std::string& title) {
const base::string16 expected_title(base::ASCIIToUTF16(title));
content::TitleWatcher title_watcher(GetActiveWebContents(), expected_title);
ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
}
void NavigateAndWaitForLoad() {
ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
// Navigate to the test page and wait for onload to be called.
const GURL url = ui_test_utils::GetTestUrl(
base::FilePath(),
base::FilePath(FILE_PATH_LITERAL("virtual_keyboard_policy.html")));
ui_test_utils::NavigateToURL(browser(), url);
WaitForTitle("onload");
}
DISALLOW_COPY_AND_ASSIGN(VirtualKeyboardPolicyTest);
};
IN_PROC_BROWSER_TEST_F(VirtualKeyboardPolicyTest, Load) {
NavigateAndWaitForLoad();
}
// Tapping on an editable element should show VK.
IN_PROC_BROWSER_TEST_F(VirtualKeyboardPolicyTest, ShowVK) {
// ui_controls::SendTouchEvents which uses InjectTouchInput API only works
// on Windows 8 and up.
if (base::win::GetVersion() < base::win::Version::WIN8) {
return;
}
NavigateAndWaitForLoad();
// Tap on the third textarea to open VK.
gfx::Rect bounds = GetActiveWebContents()->GetContainerBounds();
TextInputManagerVkPolicyObserver type_observer_auto(
GetActiveWebContents(), ui::mojom::VirtualKeyboardPolicy::AUTO);
ASSERT_TRUE(ui_controls::SendTouchEvents(
ui_controls::PRESS, 1,
bounds.x() + kTextAreaWidth / 2 + kTextAreaOffsetX * 2,
bounds.y() + kTextAreaHeight / 2));
type_observer_auto.Wait();
}
// Tapping on an editable element with virtualkeyboardpolicy="auto" should
// raise the VK but JS focus shouldn't.
IN_PROC_BROWSER_TEST_F(VirtualKeyboardPolicyTest, DontShowVKOnJSFocus) {
// ui_controls::SendTouchEvents which uses InjectTouchInput API only works
// on Windows 8 and up.
if (base::win::GetVersion() < base::win::Version::WIN8) {
return;
}
NavigateAndWaitForLoad();
content::RenderFrameHost* current = GetActiveWebContents()->GetMainFrame();
TextInputManagerShowImeIfNeededObserver show_ime_observer_false(
GetActiveWebContents(), false);
// Run the JS that focuses the edit control.
std::string script =
"inputField = document.getElementById('txt4');"
"inputField.focus();";
EXPECT_TRUE(ExecuteScriptWithoutUserGesture(current, script));
show_ime_observer_false.Wait();
TextInputManagerShowImeIfNeededObserver show_ime_observer_true(
GetActiveWebContents(), true);
// Tap on the third textarea to open VK.
gfx::Rect bounds = GetActiveWebContents()->GetContainerBounds();
ASSERT_TRUE(ui_controls::SendTouchEvents(
ui_controls::PRESS, 1,
bounds.x() + kTextAreaWidth / 2 + kTextAreaOffsetX * 2,
bounds.y() + kTextAreaHeight / 2));
show_ime_observer_true.Wait();
}
// Tapping on an editable element with virtualkeyboardpolicy="manual" that
// calls hide() explicitly should hide VK.
IN_PROC_BROWSER_TEST_F(VirtualKeyboardPolicyTest, HideVK) {
// ui_controls::SendTouchEvents which uses InjectTouchInput API only works
// on Windows 8 and up.
if (base::win::GetVersion() < base::win::Version::WIN8) {
return;
}
NavigateAndWaitForLoad();
// Tap on the first textarea that would trigger show() call.
gfx::Rect bounds = GetActiveWebContents()->GetContainerBounds();
TextInputManagerVkVisibilityRequestObserver type_observer_hide(
GetActiveWebContents(),
ui::mojom::VirtualKeyboardVisibilityRequest::HIDE);
ASSERT_TRUE(ui_controls::SendTouchEvents(
ui_controls::PRESS, 1, bounds.x() + kTextAreaWidth / 2 + kTextAreaOffsetX,
bounds.y() + kTextAreaHeight / 2));
type_observer_hide.Wait();
}
// Tapping on an editable element with virtualkeyboardpolicy="manual" that
// calls show() explicitly should show the VK and if hide()is called, then it
// should hide VK.
IN_PROC_BROWSER_TEST_F(VirtualKeyboardPolicyTest, ShowAndThenHideVK) {
// ui_controls::SendTouchEvents which uses InjectTouchInput API only works
// on Windows 8 and up.
if (base::win::GetVersion() < base::win::Version::WIN8) {
return;
}
NavigateAndWaitForLoad();
// Tap on the first textarea that would trigger show() call and then on the
// second textarea that would trigger hide() call.
gfx::Rect bounds = GetActiveWebContents()->GetContainerBounds();
TextInputManagerVkVisibilityRequestObserver type_observer_show(
GetActiveWebContents(),
ui::mojom::VirtualKeyboardVisibilityRequest::SHOW);
ASSERT_TRUE(ui_controls::SendTouchEvents(ui_controls::PRESS, 1,
bounds.x() + kTextAreaWidth / 2,
bounds.y() + kTextAreaHeight / 2));
type_observer_show.Wait();
TextInputManagerVkVisibilityRequestObserver type_observer_hide(
GetActiveWebContents(),
ui::mojom::VirtualKeyboardVisibilityRequest::HIDE);
ASSERT_TRUE(ui_controls::SendTouchEvents(
ui_controls::PRESS, 1, bounds.x() + kTextAreaWidth / 2 + kTextAreaOffsetX,
bounds.y() + kTextAreaHeight / 2));
type_observer_hide.Wait();
}
// Tapping on an editable element with virtualkeyboardpolicy="manual" that
// calls show() explicitly should show the VK and if hide()is called, then it
// should hide VK on keydown.
IN_PROC_BROWSER_TEST_F(VirtualKeyboardPolicyTest, ShowAndThenHideVKOnKeyDown) {
// ui_controls::SendTouchEvents which uses InjectTouchInput API only works
// on Windows 8 and up.
if (base::win::GetVersion() < base::win::Version::WIN8) {
return;
}
NavigateAndWaitForLoad();
// Tap on the first textarea that would trigger show() call and then on the
// second textarea that would trigger hide() call.
gfx::Rect bounds = GetActiveWebContents()->GetContainerBounds();
TextInputManagerVkVisibilityRequestObserver type_observer_show(
GetActiveWebContents(),
ui::mojom::VirtualKeyboardVisibilityRequest::SHOW);
ASSERT_TRUE(ui_controls::SendTouchEvents(ui_controls::PRESS, 1,
bounds.x() + kTextAreaWidth / 2,
bounds.y() + kTextAreaHeight / 2));
type_observer_show.Wait();
TextInputManagerVkVisibilityRequestObserver type_observer_hide(
GetActiveWebContents(),
ui::mojom::VirtualKeyboardVisibilityRequest::HIDE);
ASSERT_TRUE(ui_controls::SendKeyPress(GetWindow()->GetNativeWindow(),
ui::VKEY_RETURN, false, false, false,
false));
type_observer_hide.Wait();
}
IN_PROC_BROWSER_TEST_F(VirtualKeyboardPolicyTest,
VKVisibilityRequestInDeletedDocument) {
// ui_controls::SendTouchEvents which uses InjectTouchInput API only works
// on Windows 8 and up.
if (base::win::GetVersion() < base::win::Version::WIN8) {
return;
}
NavigateAndWaitForLoad();
// Tap on the first textarea that would trigger show() call and then on the
// second textarea that would trigger hide() call.
gfx::Rect bounds = GetActiveWebContents()->GetContainerBounds();
TextInputManagerVkVisibilityRequestObserver type_observer_none(
GetActiveWebContents(),
ui::mojom::VirtualKeyboardVisibilityRequest::NONE);
ASSERT_TRUE(ui_controls::SendTouchEvents(
ui_controls::PRESS, 1,
bounds.x() + kTextAreaWidth / 2 + kTextAreaOffsetX * 8,
bounds.y() + kTextAreaHeight / 2));
type_observer_none.Wait();
}
// Tapping on an editcontext with inputpanelpolicy="manual" that
// calls show() explicitly should show the VK and if hide() is called, then it
// should hide VK.
IN_PROC_BROWSER_TEST_F(VirtualKeyboardPolicyTest,
ShowAndThenHideVKInEditContext) {
// ui_controls::SendTouchEvents which uses InjectTouchInput API only works
// on Windows 8 and up.
if (base::win::GetVersion() < base::win::Version::WIN8) {
return;
}
NavigateAndWaitForLoad();
// Tap on the textarea that would trigger show() call and then on the
// second textarea that would trigger hide() call.
gfx::Rect bounds = GetActiveWebContents()->GetContainerBounds();
TextInputManagerVkVisibilityRequestObserver type_observer_show(
GetActiveWebContents(),
ui::mojom::VirtualKeyboardVisibilityRequest::SHOW);
ASSERT_TRUE(ui_controls::SendTouchEvents(
ui_controls::PRESS, 1,
bounds.x() + kTextAreaWidth / 2 + kTextAreaOffsetX * 4,
bounds.y() + kTextAreaHeight / 2));
type_observer_show.Wait();
TextInputManagerVkVisibilityRequestObserver type_observer_hide(
GetActiveWebContents(),
ui::mojom::VirtualKeyboardVisibilityRequest::HIDE);
ASSERT_TRUE(ui_controls::SendKeyPress(GetWindow()->GetNativeWindow(),
ui::VKEY_RETURN, false, false, false,
false));
type_observer_hide.Wait();
}
} // namespace
...@@ -6093,10 +6093,6 @@ if (!is_android) { ...@@ -6093,10 +6093,6 @@ if (!is_android) {
sources += [ "../browser/ui/views/autofill/autofill_accessibility_win_browsertest.cc" ] sources += [ "../browser/ui/views/autofill/autofill_accessibility_win_browsertest.cc" ]
} }
if (is_win) {
sources += [ "../browser/virtual_keyboard_policy_uitest_win.cc" ]
}
configs += [ "//build/config:precompiled_headers" ] configs += [ "//build/config:precompiled_headers" ]
if ((is_linux || is_chromeos) && !is_component_build) { if ((is_linux || is_chromeos) && !is_component_build) {
configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
......
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
#txt1 {
position: absolute;
top: 0px;
left: 0px;
}
#txt2 {
position: absolute;
top: 0px;
left: 100px;
}
#txt3 {
position: absolute;
top: 0px;
left: 200px;
}
#txt4 {
position: absolute;
top: 0px;
left: 400px;
}
#txt5 {
position: absolute;
top: 0px;
left: 800px;
}
</style>
<script>
const editContext = new EditContext();
editContext.inputPanelPolicy = "manual";
function log(text) {
document.title = text;
}
function FocusIn1() {
log('focusin1');
navigator.virtualKeyboard.show();
}
function HideVKCalled() {
log('KeyDown1');
navigator.virtualKeyboard.hide();
}
function FocusIn2() {
log('focusin2');
navigator.virtualKeyboard.hide();
}
function FocusIn3() {
log('focusin3');
}
function FocusIn4() {
editContext.focus();
navigator.virtualKeyboard.show();
log('focusin4');
}
function HideVKIn4() {
navigator.virtualKeyboard.hide();
log('hidevkin4');
}
function FocusIn5() {
navigator.virtualKeyboard.show();
const child = document.createElement("iframe");
document.body.appendChild(child);
const childDocument = child.contentDocument;
const textarea = childDocument.createElement('textarea');
textarea.setAttribute("virtualKeyboardPolicy", "manual");
childDocument.body.appendChild(textarea);
textarea.addEventListener("onfocusin", e => {
child.remove();
});
child.contentWindow.focus();
textarea.focus();
log('focusin5');
}
</script>
</head>
<body onload="log('onload')">
<textarea id="txt1" virtualkeyboardpolicy="manual" onfocusin="FocusIn1()" onkeydown="HideVKCalled()"></textarea>
<textarea id="txt2" virtualkeyboardpolicy="manual" onfocusin="FocusIn2()"></textarea>
<textarea id="txt3" onfocusin="FocusIn3()"></textarea>
<textarea id="txt4" onfocusin="FocusIn4()" onkeydown="HideVKIn4()"></textarea>
<textarea id="txt5" ontouchstart="FocusIn5()"></textarea>
</body>
</html>
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "content/public/test/browser_test_utils.h" #include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h" #include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/text_input_test_utils.h"
#include "content/shell/browser/shell.h" #include "content/shell/browser/shell.h"
#include "ui/base/ime/init/input_method_factory.h" #include "ui/base/ime/init/input_method_factory.h"
#include "ui/base/ime/input_method_keyboard_controller.h" #include "ui/base/ime/input_method_keyboard_controller.h"
...@@ -30,6 +31,140 @@ ...@@ -30,6 +31,140 @@
namespace content { namespace content {
// TextInputManager Observers
// A base class for observing the TextInputManager owned by the given
// WebContents. Subclasses could observe the TextInputManager for different
// changes. The class wraps a public tester which accepts callbacks that
// are run after specific changes in TextInputManager. Different observers can
// be subclassed from this by providing their specific callback methods.
class TextInputManagerObserverBase {
public:
explicit TextInputManagerObserverBase(WebContents* web_contents)
: tester_(std::make_unique<TextInputManagerTester>(web_contents)) {}
virtual ~TextInputManagerObserverBase() = default;
TextInputManagerObserverBase(const TextInputManagerObserverBase&) = delete;
TextInputManagerObserverBase operator=(const TextInputManagerObserverBase&) =
delete;
// Wait for derived class's definition of success.
void Wait() {
if (success_)
return;
run_loop.Run();
}
bool success() const { return success_; }
protected:
TextInputManagerTester* tester() { return tester_.get(); }
void OnSuccess() {
success_ = true;
run_loop.Quit();
// By deleting |tester_| we make sure that the internal observer used in
// content/ is removed from the observer list of TextInputManager.
tester_.reset(nullptr);
}
private:
std::unique_ptr<TextInputManagerTester> tester_;
bool success_ = false;
base::RunLoop run_loop;
};
// This class observes TextInputManager for changes in
// |TextInputState.vk_policy|.
class TextInputManagerVkPolicyObserver : public TextInputManagerObserverBase {
public:
TextInputManagerVkPolicyObserver(
WebContents* web_contents,
ui::mojom::VirtualKeyboardPolicy expected_value)
: TextInputManagerObserverBase(web_contents),
expected_value_(expected_value) {
tester()->SetUpdateTextInputStateCalledCallback(
base::BindRepeating(&TextInputManagerVkPolicyObserver::VerifyVkPolicy,
base::Unretained(this)));
}
TextInputManagerVkPolicyObserver(const TextInputManagerVkPolicyObserver&) =
delete;
TextInputManagerVkPolicyObserver operator=(
const TextInputManagerVkPolicyObserver&) = delete;
private:
void VerifyVkPolicy() {
ui::mojom::VirtualKeyboardPolicy value;
if (tester()->GetTextInputVkPolicy(&value) && expected_value_ == value)
OnSuccess();
}
ui::mojom::VirtualKeyboardPolicy expected_value_;
};
// This class observes TextInputManager for changes in
// |TextInputState.last_vk_visibility_request|.
class TextInputManagerVkVisibilityRequestObserver
: public TextInputManagerObserverBase {
public:
TextInputManagerVkVisibilityRequestObserver(
WebContents* web_contents,
ui::mojom::VirtualKeyboardVisibilityRequest expected_value)
: TextInputManagerObserverBase(web_contents),
expected_value_(expected_value) {
tester()->SetUpdateTextInputStateCalledCallback(base::BindRepeating(
&TextInputManagerVkVisibilityRequestObserver::VerifyVkVisibilityRequest,
base::Unretained(this)));
}
TextInputManagerVkVisibilityRequestObserver(
const TextInputManagerVkVisibilityRequestObserver&) = delete;
TextInputManagerVkVisibilityRequestObserver operator=(
const TextInputManagerVkVisibilityRequestObserver&) = delete;
private:
void VerifyVkVisibilityRequest() {
ui::mojom::VirtualKeyboardVisibilityRequest value;
if (tester()->GetTextInputVkVisibilityRequest(&value) &&
expected_value_ == value)
OnSuccess();
}
ui::mojom::VirtualKeyboardVisibilityRequest expected_value_;
};
// This class observes TextInputManager for changes in
// |TextInputState.show_ime_if_needed|.
class TextInputManagerShowImeIfNeededObserver
: public TextInputManagerObserverBase {
public:
TextInputManagerShowImeIfNeededObserver(WebContents* web_contents,
bool expected_value)
: TextInputManagerObserverBase(web_contents),
expected_value_(expected_value) {
tester()->SetUpdateTextInputStateCalledCallback(base::BindRepeating(
&TextInputManagerShowImeIfNeededObserver::VerifyShowImeIfNeeded,
base::Unretained(this)));
}
TextInputManagerShowImeIfNeededObserver(
const TextInputManagerShowImeIfNeededObserver&) = delete;
TextInputManagerShowImeIfNeededObserver operator=(
const TextInputManagerShowImeIfNeededObserver&) = delete;
private:
void VerifyShowImeIfNeeded() {
bool show_ime_if_needed;
if (tester()->GetTextInputShowImeIfNeeded(&show_ime_if_needed) &&
expected_value_ == show_ime_if_needed)
OnSuccess();
}
bool expected_value_ = false;
};
class MockKeyboardController : public ui::InputMethodKeyboardController { class MockKeyboardController : public ui::InputMethodKeyboardController {
public: public:
bool DisplayVirtualKeyboard() override { bool DisplayVirtualKeyboard() override {
...@@ -112,7 +247,7 @@ class RenderWidgetHostViewAuraBrowserMockIMETest : public ContentBrowserTest { ...@@ -112,7 +247,7 @@ class RenderWidgetHostViewAuraBrowserMockIMETest : public ContentBrowserTest {
void SetUpCommandLine(base::CommandLine* command_line) override { void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures, command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
"VirtualKeyboard"); "VirtualKeyboard,EditContext");
ContentBrowserTest::SetUpCommandLine(command_line); ContentBrowserTest::SetUpCommandLine(command_line);
} }
...@@ -182,6 +317,7 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest, ...@@ -182,6 +317,7 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest,
if (base::win::GetVersion() <= base::win::Version::WIN7) { if (base::win::GetVersion() <= base::win::Version::WIN7) {
return; return;
} }
const char kVirtualKeyboardDataURL[] = const char kVirtualKeyboardDataURL[] =
"data:text/html,<!DOCTYPE html>" "data:text/html,<!DOCTYPE html>"
"<script>" "<script>"
...@@ -197,13 +333,12 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest, ...@@ -197,13 +333,12 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest,
"</script>"; "</script>";
EXPECT_TRUE(NavigateToURL(shell(), GURL(kVirtualKeyboardDataURL))); EXPECT_TRUE(NavigateToURL(shell(), GURL(kVirtualKeyboardDataURL)));
RenderWidgetHostViewAura* rwhvi = GetRenderWidgetHostView();
// Send a touch event so that RenderWidgetHostViewAura will create the // Send a touch event so that RenderWidgetHostViewAura will create the
// keyboard observer (requires last_pointer_type_ to be TOUCH). // keyboard observer (requires last_pointer_type_ to be TOUCH).
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(30, 30), ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(30, 30),
base::TimeTicks::Now(), base::TimeTicks::Now(),
ui::PointerDetails(ui::EventPointerType::kTouch, 0)); ui::PointerDetails(ui::EventPointerType::kTouch, 0));
RenderWidgetHostViewAura* rwhvi = GetRenderWidgetHostView();
rwhvi->OnTouchEvent(&press); rwhvi->OnTouchEvent(&press);
// Emulate input type text focus in the root frame (the only frame), by // Emulate input type text focus in the root frame (the only frame), by
...@@ -275,6 +410,7 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest, ...@@ -275,6 +410,7 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest,
if (base::win::GetVersion() <= base::win::Version::WIN7) { if (base::win::GetVersion() <= base::win::Version::WIN7) {
return; return;
} }
const char kVirtualKeyboardDataURL[] = const char kVirtualKeyboardDataURL[] =
"data:text/html,<!DOCTYPE html>" "data:text/html,<!DOCTYPE html>"
"<style>" "<style>"
...@@ -376,12 +512,14 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest, ...@@ -376,12 +512,14 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest,
EXPECT_EQ("0px", EvalJs(shell(), "style.getPropertyValue('margin-bottom')") EXPECT_EQ("0px", EvalJs(shell(), "style.getPropertyValue('margin-bottom')")
.ExtractString()); .ExtractString());
} }
IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest, IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest,
VirtualKeyboardAccessibilityFocusTest) { VirtualKeyboardAccessibilityFocusTest) {
// The keyboard input pane events are not supported on Win7. // The keyboard input pane events are not supported on Win7.
if (base::win::GetVersion() <= base::win::Version::WIN7) { if (base::win::GetVersion() <= base::win::Version::WIN7) {
return; return;
} }
LoadInitialAccessibilityTreeFromHtml(R"HTML( LoadInitialAccessibilityTreeFromHtml(R"HTML(
<div><button>Before</button></div> <div><button>Before</button></div>
<div contenteditable>Editable text</div> <div contenteditable>Editable text</div>
...@@ -408,6 +546,223 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest, ...@@ -408,6 +546,223 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest,
EXPECT_EQ(true, mock_keyboard_observer_->IsKeyboardDisplayCalled()); EXPECT_EQ(true, mock_keyboard_observer_->IsKeyboardDisplayCalled());
} }
IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest,
VirtualKeyboardShowVKTest) {
// The keyboard input pane events are not supported on Win7.
if (base::win::GetVersion() <= base::win::Version::WIN7) {
return;
}
const char kVirtualKeyboardDataURL[] =
"data:text/html,<!DOCTYPE html>"
"<body>"
"<textarea id='txt3'></textarea>"
"<script>"
" let elemRect = txt3.getBoundingClientRect();"
"</script>"
"</body>";
EXPECT_TRUE(NavigateToURL(shell(), GURL(kVirtualKeyboardDataURL)));
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
auto* root = web_contents->GetFrameTree()->root();
web_contents->GetFrameTree()->SetFocusedFrame(
root, root->current_frame_host()->GetSiteInstance());
// Send a touch event so that RenderWidgetHostViewAura will create the
// keyboard observer (requires last_pointer_type_ to be TOUCH).
// Tap on the third textarea to open VK.
TextInputManagerVkPolicyObserver type_observer_auto(
web_contents, ui::mojom::VirtualKeyboardPolicy::AUTO);
const int top = EvalJs(shell(), "elemRect.top").ExtractInt();
const int left = EvalJs(shell(), "elemRect.left").ExtractInt();
SimulateTapDownAt(web_contents, gfx::Point(left + 1, top + 1));
SimulateTapAt(web_contents, gfx::Point(left + 1, top + 1));
type_observer_auto.Wait();
}
IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest,
DontShowVKOnJSFocus) {
// The keyboard input pane events are not supported on Win7.
if (base::win::GetVersion() <= base::win::Version::WIN7) {
return;
}
const char kVirtualKeyboardDataURL[] =
"data:text/html,<!DOCTYPE html>"
"<body>"
"<textarea id='txt3'></textarea>"
"<script>"
" let elemRect = txt3.getBoundingClientRect();"
" txt3.focus();"
"</script>"
"</body>";
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
TextInputManagerShowImeIfNeededObserver show_ime_observer_false(web_contents,
false);
// Note: This data URL has JS that focuses the edit control.
EXPECT_TRUE(NavigateToURL(shell(), GURL(kVirtualKeyboardDataURL)));
show_ime_observer_false.Wait();
// Send a touch event so that RenderWidgetHostViewAura will create the
// keyboard observer (requires last_pointer_type_ to be TOUCH).
// Tap on the third textarea to open VK.
TextInputManagerShowImeIfNeededObserver show_ime_observer_true(web_contents,
true);
const int top = EvalJs(shell(), "elemRect.top").ExtractInt();
const int left = EvalJs(shell(), "elemRect.left").ExtractInt();
SimulateTapDownAt(web_contents, gfx::Point(left + 1, top + 1));
SimulateTapAt(web_contents, gfx::Point(left + 1, top + 1));
show_ime_observer_true.Wait();
}
IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest,
ShowAndThenHideVK) {
// The keyboard input pane events are not supported on Win7.
if (base::win::GetVersion() <= base::win::Version::WIN7) {
return;
}
const char kVirtualKeyboardDataURL[] =
"data:text/html,<!DOCTYPE html>"
"<body>"
"<textarea id='txt3' virtualkeyboardpolicy='manual' "
"onfocusin='FocusIn1()' onkeydown='HideVKCalled()'></textarea>"
"<script>"
" let elemRect = txt3.getBoundingClientRect();"
" function FocusIn1() {"
" navigator.virtualKeyboard.show();"
" }"
" function HideVKCalled() {"
" navigator.virtualKeyboard.hide();"
" }"
"</script>"
"</body>";
EXPECT_TRUE(NavigateToURL(shell(), GURL(kVirtualKeyboardDataURL)));
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
auto* root = web_contents->GetFrameTree()->root();
web_contents->GetFrameTree()->SetFocusedFrame(
root, root->current_frame_host()->GetSiteInstance());
// Send a touch event so that RenderWidgetHostViewAura will create the
// keyboard observer (requires last_pointer_type_ to be TOUCH).
// Tap on the third textarea to open VK.
TextInputManagerVkVisibilityRequestObserver type_observer_show(
web_contents, ui::mojom::VirtualKeyboardVisibilityRequest::SHOW);
const int top = EvalJs(shell(), "elemRect.top").ExtractInt();
const int left = EvalJs(shell(), "elemRect.left").ExtractInt();
SimulateTapDownAt(web_contents, gfx::Point(left + 1, top + 1));
SimulateTapAt(web_contents, gfx::Point(left + 1, top + 1));
type_observer_show.Wait();
TextInputManagerVkVisibilityRequestObserver type_observer_hide(
web_contents, ui::mojom::VirtualKeyboardVisibilityRequest::HIDE);
SimulateKeyPress(web_contents, ui::DomKey::ENTER, ui::DomCode::ENTER,
ui::VKEY_RETURN, false, false, false, false);
type_observer_hide.Wait();
}
IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest,
ShowAndThenHideVKInEditContext) {
// The keyboard input pane events are not supported on Win7.
if (base::win::GetVersion() <= base::win::Version::WIN7) {
return;
}
const char kVirtualKeyboardDataURL[] =
"data:text/html,<!DOCTYPE html>"
"<body>"
"<textarea id='txt3' virtualkeyboardpolicy='manual' "
"onfocusin='FocusIn1()' onkeydown='HideVKCalled()'></textarea>"
"<script>"
" let elemRect = txt3.getBoundingClientRect();"
" const editContext = new EditContext();"
" editContext.inputPanelPolicy = \"manual\";"
" function FocusIn1() {"
" editContext.focus();"
" navigator.virtualKeyboard.show();"
" }"
" function HideVKCalled() {"
" navigator.virtualKeyboard.hide();"
" }"
"</script>"
"</body>";
EXPECT_TRUE(NavigateToURL(shell(), GURL(kVirtualKeyboardDataURL)));
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
auto* root = web_contents->GetFrameTree()->root();
web_contents->GetFrameTree()->SetFocusedFrame(
root, root->current_frame_host()->GetSiteInstance());
// Send a touch event so that RenderWidgetHostViewAura will create the
// keyboard observer (requires last_pointer_type_ to be TOUCH).
// Tap on the third textarea to open VK.
TextInputManagerVkVisibilityRequestObserver type_observer_show(
web_contents, ui::mojom::VirtualKeyboardVisibilityRequest::SHOW);
const int top = EvalJs(shell(), "elemRect.top").ExtractInt();
const int left = EvalJs(shell(), "elemRect.left").ExtractInt();
SimulateTapDownAt(web_contents, gfx::Point(left + 1, top + 1));
SimulateTapAt(web_contents, gfx::Point(left + 1, top + 1));
type_observer_show.Wait();
TextInputManagerVkVisibilityRequestObserver type_observer_hide(
web_contents, ui::mojom::VirtualKeyboardVisibilityRequest::HIDE);
SimulateKeyPress(web_contents, ui::DomKey::ENTER, ui::DomCode::ENTER,
ui::VKEY_RETURN, false, false, false, false);
type_observer_hide.Wait();
}
IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserMockIMETest,
VKVisibilityRequestInDeletedDocument) {
// The keyboard input pane events are not supported on Win7.
if (base::win::GetVersion() <= base::win::Version::WIN7) {
return;
}
const char kVirtualKeyboardDataURL[] =
"data:text/html,<!DOCTYPE html>"
"<body>"
"<textarea id='txt3' virtualkeyboardpolicy='manual' "
"onfocusin='FocusIn1()'></textarea>"
"<script>"
" let elemRect = txt3.getBoundingClientRect();"
" function FocusIn1() {"
" navigator.virtualKeyboard.show();"
" const child = document.createElement(\"iframe\");"
" document.body.appendChild(child);"
" const childDocument = child.contentDocument;"
" const textarea = childDocument.createElement('textarea');"
" textarea.setAttribute(\"virtualKeyboardPolicy\", \"manual\");"
" childDocument.body.appendChild(textarea);"
" textarea.addEventListener(\"onfocusin\", e => {"
" child.remove();"
" });"
" child.contentWindow.focus();"
" textarea.focus();"
" }"
"</script>"
"</body>";
EXPECT_TRUE(NavigateToURL(shell(), GURL(kVirtualKeyboardDataURL)));
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
auto* root = web_contents->GetFrameTree()->root();
web_contents->GetFrameTree()->SetFocusedFrame(
root, root->current_frame_host()->GetSiteInstance());
// Send a touch event so that RenderWidgetHostViewAura will create the
// keyboard observer (requires last_pointer_type_ to be TOUCH).
TextInputManagerVkVisibilityRequestObserver type_observer_none(
web_contents, ui::mojom::VirtualKeyboardVisibilityRequest::NONE);
const int top = EvalJs(shell(), "elemRect.top").ExtractInt();
const int left = EvalJs(shell(), "elemRect.left").ExtractInt();
SimulateTapDownAt(web_contents, gfx::Point(left + 1, top + 1));
SimulateTapAt(web_contents, gfx::Point(left + 1, top + 1));
type_observer_none.Wait();
}
#endif // #ifdef OS_WIN #endif // #ifdef OS_WIN
} // namespace content } // namespace content
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment