Commit c3664a6a authored by Darren Shen's avatar Darren Shen Committed by Commit Bot

rule-based: Use native code for handling key events.

<This change is hidden behind a flag>

As part of migrating PK IMEs to native code, this CL migrates key
handling to native code path.

We port Background#maybeHandleKeyEvent [1] and
RuleBasedController#handleEvent [2].

[1] chos/background.js
[2] chos/pk/rulebasedcontroller.js

Note that the JS code has already been guarded by the runtime flag.

Bug: 1009903
Change-Id: I801505f11af95dbc066b12d7bb70f6a9765fea65
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1921589Reviewed-by: default avatarShu Chen <shuchen@chromium.org>
Commit-Queue: Darren Shen <shend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#726128}
parent baa2dad0
...@@ -3,15 +3,36 @@ ...@@ -3,15 +3,36 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/chromeos/input_method/native_input_method_engine.h" #include "chrome/browser/chromeos/input_method/native_input_method_engine.h"
#include "base/feature_list.h"
#include "base/i18n/i18n_constants.h"
#include "base/i18n/icu_string_conversions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chromeos/constants/chromeos_features.h"
#include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/ime/chromeos/input_method_manager.h"
#include "ui/base/ime/ime_bridge.h"
namespace chromeos { namespace chromeos {
namespace { namespace {
// Returns the current input context. This may change during the session, even
// if the IME engine does not change.
ui::IMEInputContextHandlerInterface* GetInputContext() {
return ui::IMEBridge::Get()->GetInputContextHandler();
}
bool ShouldEngineUseMojo(const std::string& engine_id) { bool ShouldEngineUseMojo(const std::string& engine_id) {
return base::StartsWith(engine_id, "vkd_", base::CompareCase::SENSITIVE); return base::FeatureList::IsEnabled(
chromeos::features::kNativeRuleBasedTyping) &&
base::StartsWith(engine_id, "vkd_", base::CompareCase::SENSITIVE);
}
std::string NormalizeString(const std::string& str) {
std::string normalized_str;
base::ConvertToUtf8AndNormalize(str, base::kCodepageUTF8, &normalized_str);
return normalized_str;
} }
} // namespace } // namespace
...@@ -83,7 +104,16 @@ void NativeInputMethodEngine::ImeObserver::OnKeyEvent( ...@@ -83,7 +104,16 @@ void NativeInputMethodEngine::ImeObserver::OnKeyEvent(
const std::string& engine_id, const std::string& engine_id,
const InputMethodEngineBase::KeyboardEvent& event, const InputMethodEngineBase::KeyboardEvent& event,
ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback) { ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback) {
base_observer_->OnKeyEvent(engine_id, event, std::move(callback)); if (ShouldEngineUseMojo(engine_id)) {
remote_to_engine_->ProcessKeypressForRulebased(
ime::mojom::KeypressInfoForRulebased::New(
event.type, event.code, event.shift_key, event.altgr_key,
event.caps_lock, event.ctrl_key, event.alt_key),
base::BindOnce(&ImeObserver::OnKeyEventResponse, base::Unretained(this),
base::Time::Now(), std::move(callback)));
} else {
base_observer_->OnKeyEvent(engine_id, event, std::move(callback));
}
} }
void NativeInputMethodEngine::ImeObserver::OnReset( void NativeInputMethodEngine::ImeObserver::OnReset(
...@@ -144,4 +174,28 @@ void NativeInputMethodEngine::ImeObserver::OnConnected(bool bound) { ...@@ -144,4 +174,28 @@ void NativeInputMethodEngine::ImeObserver::OnConnected(bool bound) {
connected_to_engine_ = bound; connected_to_engine_ = bound;
} }
void NativeInputMethodEngine::ImeObserver::OnKeyEventResponse(
base::Time start,
ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback,
ime::mojom::KeypressResponseForRulebasedPtr response) {
UMA_HISTOGRAM_CUSTOM_COUNTS(
"InputMethod.Mojo.Extension.Rulebased.ProcessLatency",
(base::Time::Now() - start).InMilliseconds(), 0, 1000, 50);
for (const auto& op : response->operations) {
switch (op->method) {
case ime::mojom::OperationMethodForRulebased::COMMIT_TEXT:
GetInputContext()->CommitText(NormalizeString(op->arguments));
break;
case ime::mojom::OperationMethodForRulebased::SET_COMPOSITION:
ui::CompositionText composition;
composition.text = base::UTF8ToUTF16(NormalizeString(op->arguments));
GetInputContext()->UpdateCompositionText(
composition, composition.text.length(), /*visible=*/true);
break;
}
}
std::move(callback).Run(response->result);
}
} // namespace chromeos } // namespace chromeos
...@@ -101,6 +101,12 @@ class NativeInputMethodEngine : public InputMethodEngine { ...@@ -101,6 +101,12 @@ class NativeInputMethodEngine : public InputMethodEngine {
// the success of the connection. // the success of the connection.
void OnConnected(bool bound); void OnConnected(bool bound);
// Called when a key press is processed by Mojo.
void OnKeyEventResponse(
base::Time start,
ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback,
ime::mojom::KeypressResponseForRulebasedPtr response);
std::unique_ptr<InputMethodEngineBase::Observer> base_observer_; std::unique_ptr<InputMethodEngineBase::Observer> base_observer_;
mojo::Remote<ime::mojom::InputEngineManager> remote_manager_; mojo::Remote<ime::mojom::InputEngineManager> remote_manager_;
mojo::Receiver<ime::mojom::InputChannel> receiver_from_engine_; mojo::Receiver<ime::mojom::InputChannel> receiver_from_engine_;
......
...@@ -4,10 +4,22 @@ ...@@ -4,10 +4,22 @@
#include "chrome/browser/chromeos/input_method/native_input_method_engine.h" #include "chrome/browser/chromeos/input_method/native_input_method_engine.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/in_process_browser_test.h"
#include "chromeos/constants/chromeos_features.h"
#include "content/public/test/test_utils.h" #include "content/public/test/test_utils.h"
#include "mojo/core/embedder/embedder.h" #include "mojo/core/embedder/embedder.h"
#include "ui/base/ime/chromeos/input_method_chromeos.h"
#include "ui/base/ime/dummy_text_input_client.h"
#include "ui/base/ime/ime_bridge.h"
#include "ui/base/ime/ime_engine_handler_interface.h"
#include "ui/base/ime/input_method_delegate.h"
#include "ui/base/ime/text_input_flags.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/events/keycodes/keyboard_codes_posix.h"
namespace { namespace {
...@@ -49,27 +61,99 @@ class TestObserver : public InputMethodEngineBase::Observer { ...@@ -49,27 +61,99 @@ class TestObserver : public InputMethodEngineBase::Observer {
DISALLOW_COPY_AND_ASSIGN(TestObserver); DISALLOW_COPY_AND_ASSIGN(TestObserver);
}; };
class NativeInputMethodEngineTest : public InProcessBrowserTest { class KeyProcessingWaiter {
public:
ui::IMEEngineHandlerInterface::KeyEventDoneCallback CreateCallback() {
return base::BindOnce(&KeyProcessingWaiter::OnKeyEventDone,
base::Unretained(this));
}
void OnKeyEventDone(bool consumed) { run_loop_.Quit(); }
void Wait() { run_loop_.Run(); }
private:
base::RunLoop run_loop_;
};
class NativeInputMethodEngineTest : public InProcessBrowserTest,
public ui::internal::InputMethodDelegate {
public:
NativeInputMethodEngineTest() : input_method_(this) {
feature_list_.InitWithFeatureState(
chromeos::features::kNativeRuleBasedTyping, true);
}
protected: protected:
void SetUp() override { void SetUp() override {
mojo::core::Init(); mojo::core::Init();
InProcessBrowserTest::SetUp(); InProcessBrowserTest::SetUp();
ui::IMEBridge::Initialize();
} }
void SetUpOnMainThread() override { void SetUpOnMainThread() override {
ui::IMEBridge::Get()->SetInputContextHandler(&input_method_);
auto observer = std::make_unique<TestObserver>(); auto observer = std::make_unique<TestObserver>();
engine_.Initialize(std::move(observer), "", nullptr); engine_.Initialize(std::move(observer), "", nullptr);
InProcessBrowserTest::SetUpOnMainThread(); InProcessBrowserTest::SetUpOnMainThread();
} }
// Overridden from ui::internal::InputMethodDelegate:
ui::EventDispatchDetails DispatchKeyEventPostIME(
ui::KeyEvent* event) override {
return ui::EventDispatchDetails();
}
void DispatchKeyPress(ui::KeyboardCode code, int flags = ui::EF_NONE) {
KeyProcessingWaiter waiterPressed;
KeyProcessingWaiter waiterReleased;
engine_.ProcessKeyEvent({ui::ET_KEY_PRESSED, code, flags},
waiterPressed.CreateCallback());
engine_.ProcessKeyEvent({ui::ET_KEY_RELEASED, code, flags},
waiterReleased.CreateCallback());
engine_.FlushForTesting();
waiterPressed.Wait();
waiterReleased.Wait();
}
void SetFocus(ui::TextInputClient* client) {
input_method_.SetFocusedTextInputClient(client);
}
chromeos::NativeInputMethodEngine engine_; chromeos::NativeInputMethodEngine engine_;
private:
ui::InputMethodChromeOS input_method_;
base::test::ScopedFeatureList feature_list_;
}; };
} // namespace } // namespace
IN_PROC_BROWSER_TEST_F(NativeInputMethodEngineTest, CanConnectToInputEngine) { IN_PROC_BROWSER_TEST_F(NativeInputMethodEngineTest,
// ID for Arabic is specified in google_xkb_manifest.json. VietnameseTelex_SimpleTransform) {
engine_.Enable("vkd_ar"); // ID is specified in google_xkb_manifest.json.
engine_.Enable("vkd_vi_telex");
engine_.FlushForTesting(); engine_.FlushForTesting();
EXPECT_TRUE(engine_.IsConnectedForTesting()); EXPECT_TRUE(engine_.IsConnectedForTesting());
// Create a fake text field.
ui::DummyTextInputClient text_input_client(ui::TEXT_INPUT_TYPE_TEXT);
SetFocus(&text_input_client);
DispatchKeyPress(ui::VKEY_A, ui::EF_SHIFT_DOWN);
DispatchKeyPress(ui::VKEY_S);
DispatchKeyPress(ui::VKEY_SPACE);
// Expect to commit 'Á '.
ASSERT_EQ(text_input_client.composition_history().size(), 2U);
EXPECT_EQ(text_input_client.composition_history()[0].text,
base::ASCIIToUTF16("A"));
EXPECT_EQ(text_input_client.composition_history()[1].text,
base::UTF8ToUTF16(u8"\u00c1"));
ASSERT_EQ(text_input_client.insert_text_history().size(), 1U);
EXPECT_EQ(text_input_client.insert_text_history()[0],
base::UTF8ToUTF16(u8"\u00c1 "));
SetFocus(nullptr);
} }
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