Commit afb74195 authored by Jing Wang's avatar Jing Wang Committed by Commit Bot

Implement OnInputMethodOptionsUpdated API

The OnInputMethodOptionsUpdated event is fire when any change is made
to the input method specific settings in pref so that ime extension can
reload options immediately.

We register an observer in input method engine, and whenever we observe
the change, we check settings of which input method is changed and then
fire the event with that input method code.

Test: tested in Chrome on Linux, added browser tests.
Bug: 1042084
Change-Id: I4971b838f3a3b0eff32ad454f19d273e6804ef3c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2257119
Commit-Queue: Jing Wang <jiwan@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Reviewed-by: default avatarYuichiro Hanada <yhanada@chromium.org>
Reviewed-by: default avatarKeith Lee <keithlee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#786630}
parent 3bb16a4e
......@@ -192,6 +192,7 @@ class ArcInputMethodManagerService::InputMethodEngineObserver
void OnScreenProjectionChanged(bool is_projected) override {}
void OnSuggestionsChanged(
const std::vector<std::string>& suggestions) override {}
void OnInputMethodOptionsChanged(const std::string& engine_id) override {}
private:
ArcInputMethodManagerService* const owner_;
......
......@@ -54,6 +54,7 @@ class DummyInputMethodEngineObserver
void OnScreenProjectionChanged(bool is_projected) override {}
void OnSuggestionsChanged(
const std::vector<std::string>& suggestions) override {}
void OnInputMethodOptionsChanged(const std::string& engine_id) override {}
private:
DISALLOW_COPY_AND_ASSIGN(DummyInputMethodEngineObserver);
......
......@@ -15,6 +15,8 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/ime/chromeos/ime_bridge.h"
......@@ -141,7 +143,8 @@ InputMethodEngineBase::InputMethodEngineBase()
composition_changed_(false),
text_(""),
commit_text_changed_(false),
handling_key_event_(false) {}
handling_key_event_(false),
pref_change_registrar_(nullptr) {}
InputMethodEngineBase::~InputMethodEngineBase() {}
......@@ -155,6 +158,39 @@ void InputMethodEngineBase::Initialize(
observer_ = std::move(observer);
extension_id_ = extension_id;
profile_ = profile;
if (profile_ && profile->GetPrefs()) {
input_method_settings_snapshot_ =
profile->GetPrefs()
->GetDictionary(prefs::kLanguageInputMethodSpecificSettings)
->Clone();
pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
pref_change_registrar_->Init(profile->GetPrefs());
pref_change_registrar_->Add(
prefs::kLanguageInputMethodSpecificSettings,
base::BindRepeating(&InputMethodEngineBase::OnInputMethodOptionsChanged,
base::Unretained(this)));
}
}
void InputMethodEngineBase::OnInputMethodOptionsChanged() {
const base::DictionaryValue* new_settings =
profile_->GetPrefs()->GetDictionary(
prefs::kLanguageInputMethodSpecificSettings);
const base::DictionaryValue& old_settings =
base::Value::AsDictionaryValue(input_method_settings_snapshot_);
for (const auto& it : new_settings->DictItems()) {
if (old_settings.HasKey(it.first)) {
if (*(old_settings.FindPath(it.first)) !=
*(new_settings->FindPath(it.first))) {
observer_->OnInputMethodOptionsChanged(it.first);
}
} else {
observer_->OnInputMethodOptionsChanged(it.first);
}
}
input_method_settings_snapshot_ = new_settings->Clone();
}
void InputMethodEngineBase::FocusIn(
......@@ -201,6 +237,9 @@ void InputMethodEngineBase::Disable() {
void InputMethodEngineBase::Reset() {
observer_->OnReset(active_component_id_);
if (pref_change_registrar_) {
pref_change_registrar_.reset();
}
}
void InputMethodEngineBase::ProcessKeyEvent(const ui::KeyEvent& key_event,
......
......@@ -11,6 +11,8 @@
#include <vector>
#include "base/time/time.h"
#include "base/values.h"
#include "components/prefs/pref_change_registrar.h"
#include "ui/base/ime/chromeos/input_method_descriptor.h"
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/ime_engine_handler_interface.h"
......@@ -127,6 +129,9 @@ class InputMethodEngineBase : virtual public ui::IMEEngineHandlerInterface {
// Called when the suggestions to display have changed.
virtual void OnSuggestionsChanged(
const std::vector<std::string>& suggestions) = 0;
// Called when the input method options are updated.
virtual void OnInputMethodOptionsChanged(const std::string& engine_id) = 0;
};
InputMethodEngineBase();
......@@ -228,6 +233,8 @@ class InputMethodEngineBase : virtual public ui::IMEEngineHandlerInterface {
const std::string& component_id,
ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback);
void OnInputMethodOptionsChanged();
int GetContextIdForTesting() const { return context_id_; }
// Get the composition bounds.
......@@ -330,6 +337,10 @@ class InputMethodEngineBase : virtual public ui::IMEEngineHandlerInterface {
private:
ui::KeyEvent ConvertKeyboardEventToUIKeyEvent(const KeyboardEvent& event);
std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
base::Value input_method_settings_snapshot_;
};
} // namespace chromeos
......
......@@ -17,7 +17,6 @@
#include "chrome/browser/chromeos/input_method/input_method_configuration.h"
#include "chrome/browser/chromeos/input_method/input_method_engine_base.h"
#include "chrome/browser/chromeos/input_method/mock_input_method_manager_impl.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -123,6 +122,7 @@ class TestObserver : public InputMethodEngineBase::Observer {
void OnSuggestionsChanged(
const std::vector<std::string>& suggestions) override {}
void OnInputMethodOptionsChanged(const std::string& engine_id) override {}
void OnReset(const std::string& engine_id) override {
calls_bitmap_ |= RESET;
......@@ -176,7 +176,7 @@ class InputMethodEngineTest : public testing::Test {
std::unique_ptr<InputMethodEngineBase::Observer> observer_ptr(observer_);
engine_->Initialize(std::move(observer_ptr),
whitelisted ? kTestExtensionId : kTestExtensionId2,
ProfileManager::GetActiveUserProfile());
nullptr);
}
void FocusIn(ui::TextInputType input_type) {
......
......@@ -281,6 +281,11 @@ void NativeInputMethodEngine::ImeObserver::OnSuggestionsChanged(
base_observer_->OnSuggestionsChanged(suggestions);
}
void NativeInputMethodEngine::ImeObserver::OnInputMethodOptionsChanged(
const std::string& engine_id) {
base_observer_->OnInputMethodOptionsChanged(engine_id);
}
void NativeInputMethodEngine::ImeObserver::FlushForTesting() {
remote_manager_.FlushForTesting();
if (remote_to_engine_.is_bound())
......
......@@ -83,6 +83,7 @@ class NativeInputMethodEngine : public InputMethodEngine {
void OnScreenProjectionChanged(bool is_projected) override;
void OnSuggestionsChanged(
const std::vector<std::string>& suggestions) override;
void OnInputMethodOptionsChanged(const std::string& engine_id) override;
// mojom::InputChannel:
void ProcessMessage(const std::vector<uint8_t>& message,
......
......@@ -10,12 +10,14 @@
#include "base/test/metrics/user_action_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/values.h"
#include "chrome/browser/autofill/personal_data_manager_factory.h"
#include "chrome/browser/chromeos/input_method/textinput_test_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chromeos/constants/chromeos_features.h"
......@@ -78,8 +80,14 @@ class TestObserver : public InputMethodEngineBase::Observer {
void OnReset(const std::string& engine_id) override {}
void OnSuggestionsChanged(
const std::vector<std::string>& suggestions) override {}
void OnInputMethodOptionsChanged(const std::string& engine_id) override {
changed_engine_id_ = engine_id;
}
void ClearChangedEngineId() { changed_engine_id_ = ""; }
std::string GetChangedEngineId() { return changed_engine_id_; }
private:
std::string changed_engine_id_ = "";
DISALLOW_COPY_AND_ASSIGN(TestObserver);
};
......@@ -145,12 +153,18 @@ class NativeInputMethodEngineTest : public InProcessBrowserTest,
ui::IMEBridge::Get()->SetCurrentEngineHandler(&engine_);
auto observer = std::make_unique<TestObserver>();
observer_ = observer.get();
profile_ = browser()->profile();
prefs_ = profile_->GetPrefs();
prefs_->Set(prefs::kLanguageInputMethodSpecificSettings,
base::DictionaryValue());
engine_.Initialize(std::move(observer), "", profile_);
InProcessBrowserTest::SetUpOnMainThread();
}
void TearDown() override { engine_.Reset(); }
void SetUpTextInput(chromeos::TextInputTestHelper& helper) {
GURL url = ui_test_utils::GetTestUrl(
base::FilePath(FILE_PATH_LITERAL("textinput")),
......@@ -199,6 +213,8 @@ class NativeInputMethodEngineTest : public InProcessBrowserTest,
chromeos::NativeInputMethodEngine engine_;
Profile* profile_;
PrefService* prefs_;
TestObserver* observer_;
private:
ui::InputMethodChromeOS input_method_;
......@@ -453,3 +469,23 @@ IN_PROC_BROWSER_TEST_F(
user_action_tester.GetActionCount(
"ChromeOS.Settings.SmartInputs.PersonalInfoSuggestions.Open"));
}
IN_PROC_BROWSER_TEST_F(NativeInputMethodEngineTest,
FiresOnInputMethodOptionsChangedEvent) {
base::DictionaryValue settings;
// Add key will trigger event.
base::Value pinyin1(base::Value::Type::DICTIONARY);
pinyin1.SetBoolKey("foo", true);
settings.SetPath("pinyin", std::move(pinyin1));
prefs_->Set(prefs::kLanguageInputMethodSpecificSettings, settings);
EXPECT_EQ(observer_->GetChangedEngineId(), "pinyin");
observer_->ClearChangedEngineId();
// Change key will trigger event.
base::Value pinyin2(base::Value::Type::DICTIONARY);
pinyin2.SetBoolKey("foo", false);
settings.SetPath("pinyin", std::move(pinyin2));
prefs_->Set(prefs::kLanguageInputMethodSpecificSettings, settings);
EXPECT_EQ(observer_->GetChangedEngineId(), "pinyin");
}
......@@ -324,6 +324,15 @@ class ImeObserverChromeOS : public ui::ImeObserver {
std::move(args));
}
void OnInputMethodOptionsChanged(const std::string& engine_id) override {
std::unique_ptr<base::ListValue> args(
input_method_private::OnInputMethodOptionsChanged::Create(engine_id));
DispatchEventToExtension(
extensions::events::INPUT_IME_ON_INPUT_METHOD_OPTIONS_CHANGED,
input_method_private::OnInputMethodOptionsChanged::kEventName,
std::move(args));
}
private:
// ui::ImeObserver overrides.
void DispatchEventToExtension(
......
......@@ -477,6 +477,7 @@ enum HistogramValue {
PASSWORDS_PRIVATE_ON_PASSWORD_CHECK_STATUS_CHANGED = 455,
INPUT_IME_ON_ASSISTIVE_WINDOW_BUTTON_CLICKED = 456,
INPUT_IME_ON_SUGGESTIONS_CHANGED = 457,
INPUT_IME_ON_INPUT_METHOD_OPTIONS_CHANGED = 458,
// Last entry: Add new entries above, then run:
// python tools/metrics/histograms/update_extension_histograms.py
ENUM_BOUNDARY
......
......@@ -22299,6 +22299,7 @@ Called by update_extension_histograms.py.-->
<int value="455" label="PASSWORDS_PRIVATE_ON_PASSWORD_CHECK_STATUS_CHANGED"/>
<int value="456" label="INPUT_IME_ON_ASSISTIVE_WINDOW_BUTTON_CLICKED"/>
<int value="457" label="INPUT_IME_ON_SUGGESTIONS_CHANGED"/>
<int value="458" label="INPUT_IME_ON_INPUT_METHOD_OPTIONS_CHANGED"/>
</enum>
<enum name="ExtensionFileWriteResult">
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