diff options
author | zork@chromium.org <zork@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-26 09:01:40 +0000 |
---|---|---|
committer | zork@chromium.org <zork@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-26 09:01:40 +0000 |
commit | 36da236c34e8f3433d1a670c4a3ba039dfc975b3 (patch) | |
tree | 8a9a78c7bc7a769f94f32aa10015b306e815f7c7 /chrome/browser/chromeos/cros | |
parent | c5a49592b1cbe19e8866e31f4727dac2e5a8dd64 (diff) | |
download | chromium_src-36da236c34e8f3433d1a670c4a3ba039dfc975b3.zip chromium_src-36da236c34e8f3433d1a670c4a3ba039dfc975b3.tar.gz chromium_src-36da236c34e8f3433d1a670c4a3ba039dfc975b3.tar.bz2 |
Start and stop ibus-daemon on demand.
BUG=chromium-os:4460
TEST=Turn off all input methods except en-US. Open a terminal. run 'ps aux | grep ibus' and check that ibus isn't running. Enable an input method. Ensure that it works.
Review URL: http://codereview.chromium.org/3052009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53614 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/chromeos/cros')
-rw-r--r-- | chrome/browser/chromeos/cros/input_method_library.cc | 126 | ||||
-rw-r--r-- | chrome/browser/chromeos/cros/input_method_library.h | 25 | ||||
-rw-r--r-- | chrome/browser/chromeos/cros/mock_input_method_library.h | 3 |
3 files changed, 149 insertions, 5 deletions
diff --git a/chrome/browser/chromeos/cros/input_method_library.cc b/chrome/browser/chromeos/cros/input_method_library.cc index 260e507..664b745 100644 --- a/chrome/browser/chromeos/cros/input_method_library.cc +++ b/chrome/browser/chromeos/cros/input_method_library.cc @@ -13,6 +13,9 @@ #include "chrome/browser/chromeos/language_preferences.h" #include "third_party/icu/public/common/unicode/uloc.h" +#include <glib.h> +#include <signal.h> + // Allows InvokeLater without adding refcounting. This class is a Singleton and // won't be deleted until it's last InvokeLater is run. DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::InputMethodLibraryImpl); @@ -47,16 +50,17 @@ namespace chromeos { InputMethodLibraryImpl::InputMethodLibraryImpl() : input_method_status_connection_(NULL), previous_input_method_("", "", "", ""), - current_input_method_("", "", "", "") { + current_input_method_("", "", "", ""), + ime_running_(false), + ime_handle_(0), + candidate_window_handle_(0) { scoped_ptr<InputMethodDescriptors> input_method_descriptors( CreateFallbackInputMethodDescriptors()); current_input_method_ = input_method_descriptors->at(0); } InputMethodLibraryImpl::~InputMethodLibraryImpl() { - if (input_method_status_connection_) { - chromeos::DisconnectInputMethodStatus(input_method_status_connection_); - } + StopIme(); } InputMethodLibraryImpl::Observer::~Observer() { @@ -143,6 +147,8 @@ bool InputMethodLibraryImpl::GetImeConfig( bool InputMethodLibraryImpl::SetImeConfig( const char* section, const char* config_name, const ImeConfigValue& value) { + MaybeUpdateImeState(section, config_name, value); + const ConfigKeyType key = std::make_pair(section, config_name); pending_config_requests_.erase(key); pending_config_requests_.insert(std::make_pair(key, value)); @@ -151,6 +157,23 @@ bool InputMethodLibraryImpl::SetImeConfig( return pending_config_requests_.empty(); } +void InputMethodLibraryImpl::MaybeUpdateImeState( + const char* section, const char* config_name, const ImeConfigValue& value) { + if (!strcmp(kGeneralSectionName, section) && + !strcmp(kPreloadEnginesConfigName, config_name)) { + if (EnsureLoadedAndStarted()) { + if (value.type == ImeConfigValue::kValueTypeStringList && + value.string_list_value.size() == 1 && + value.string_list_value[0] == kHardwareKeyboardLayout) { + StopIme(); + } else { + StartIme(); + } + chromeos::SetActiveInputMethods(input_method_status_connection_, value); + } + } +} + void InputMethodLibraryImpl::FlushImeConfig() { bool active_input_methods_are_changed = false; if (EnsureLoadedAndStarted()) { @@ -298,4 +321,99 @@ void InputMethodLibraryImpl::UpdateProperty(const ImePropertyList& prop_list) { FOR_EACH_OBSERVER(Observer, observers_, ImePropertiesChanged(this)); } +void InputMethodLibraryImpl::StartIme() { + ime_running_ = true; + MaybeLaunchIme(); +} + +void InputMethodLibraryImpl::MaybeLaunchIme() { + if (!ime_running_) { + return; + } + + // TODO(zork): export "LD_PRELOAD=/usr/lib/libcrash.so" + GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD; + if (ime_handle_ == 0) { + GError *error = NULL; + gchar **argv; + gint argc; + + if (!g_shell_parse_argv( + "/usr/bin/ibus-daemon --panel=disable --cache=none --restart", + &argc, &argv, &error)) { + LOG(ERROR) << "Could not parse command: " << error->message; + g_error_free(error); + return; + } + + error = NULL; + int handle; + // TODO(zork): Send output to /var/log/ibus.log + gboolean result = g_spawn_async(NULL, argv, NULL, + flags, NULL, NULL, + &handle, &error); + g_strfreev(argv); + if (!result) { + LOG(ERROR) << "Could not launch ime: " << error->message; + g_error_free(error); + return; + } + ime_handle_ = handle; + g_child_watch_add(ime_handle_, (GChildWatchFunc)OnImeShutdown, this); + } + + if (candidate_window_handle_ == 0) { + GError *error = NULL; + gchar **argv; + gint argc; + + if (!g_shell_parse_argv("/opt/google/chrome/candidate_window", + &argc, &argv, &error)) { + LOG(ERROR) << "Could not parse command: " << error->message; + g_error_free(error); + return; + } + + error = NULL; + int handle; + gboolean result = g_spawn_async(NULL, argv, NULL, + flags, NULL, NULL, + &handle, &error); + g_strfreev(argv); + if (!result) { + LOG(ERROR) << "Could not launch ime candidate window" << error->message; + g_error_free(error); + return; + } + candidate_window_handle_ = handle; + g_child_watch_add(candidate_window_handle_, + (GChildWatchFunc)OnImeShutdown, this); + } +} + +void InputMethodLibraryImpl::StopIme() { + ime_running_ = false; + if (ime_handle_) { + kill(ime_handle_, SIGTERM); + ime_handle_ = 0; + } + if (candidate_window_handle_) { + kill(candidate_window_handle_, SIGTERM); + candidate_window_handle_ = 0; + } +} + +// static +void InputMethodLibraryImpl::OnImeShutdown(int pid, int status, + InputMethodLibraryImpl* library) { + g_spawn_close_pid(pid); + if (library->ime_handle_ == pid) { + library->ime_handle_ = 0; + } else if (library->candidate_window_handle_ == pid) { + library->candidate_window_handle_ = 0; + } + + library->MaybeLaunchIme(); +} + } // namespace chromeos diff --git a/chrome/browser/chromeos/cros/input_method_library.h b/chrome/browser/chromeos/cros/input_method_library.h index e92b311..61710b3 100644 --- a/chrome/browser/chromeos/cros/input_method_library.h +++ b/chrome/browser/chromeos/cros/input_method_library.h @@ -80,6 +80,12 @@ class InputMethodLibrary { const char* config_name, const ImeConfigValue& value) = 0; + // Start the IME process. + virtual void StartIme() = 0; + + // Shutdown the IME process. + virtual void StopIme() = 0; + virtual const InputMethodDescriptor& previous_input_method() const = 0; virtual const InputMethodDescriptor& current_input_method() const = 0; @@ -121,6 +127,9 @@ class InputMethodLibraryImpl : public InputMethodLibrary { return current_ime_properties_; } + virtual void StartIme(); + virtual void StopIme(); + private: // This method is called when there's a change in input method status. static void InputMethodChangedHandler( @@ -159,10 +168,21 @@ class InputMethodLibraryImpl : public InputMethodLibrary { // Called by the handler to update input method properties. void UpdateProperty(const ImePropertyList& prop_list); + void MaybeUpdateImeState(const char* section, const char* config_name, + const ImeConfigValue& value); + // Tries to send all pending SetImeConfig requests to the input method config // daemon. void FlushImeConfig(); + // Launch any IME processes that should currently be running, but aren't. + void MaybeLaunchIme(); + + // Handle one of the ime processes shutting down. If it was shutdown by us, + // just close the handle. If it crashed, restart it. + static void OnImeShutdown(int pid, int status, + InputMethodLibraryImpl* library); + // A reference to the language api, to allow callbacks when the input method // status changes. InputMethodStatusConnection* input_method_status_connection_; @@ -193,6 +213,11 @@ class InputMethodLibraryImpl : public InputMethodLibrary { // method config daemon. base::OneShotTimer<InputMethodLibraryImpl> timer_; + bool ime_running_; + + int ime_handle_; + int candidate_window_handle_; + DISALLOW_COPY_AND_ASSIGN(InputMethodLibraryImpl); }; diff --git a/chrome/browser/chromeos/cros/mock_input_method_library.h b/chrome/browser/chromeos/cros/mock_input_method_library.h index ccd0387..0a9e415 100644 --- a/chrome/browser/chromeos/cros/mock_input_method_library.h +++ b/chrome/browser/chromeos/cros/mock_input_method_library.h @@ -32,9 +32,10 @@ class MockInputMethodLibrary : public InputMethodLibrary { MOCK_CONST_METHOD0(previous_input_method, const InputMethodDescriptor&(void)); MOCK_CONST_METHOD0(current_input_method, const InputMethodDescriptor&(void)); MOCK_CONST_METHOD0(current_ime_properties, const ImePropertyList&(void)); + MOCK_METHOD0(StartIme, void(void)); + MOCK_METHOD0(StopIme, void(void)); }; } // namespace chromeos #endif // CHROME_BROWSER_CHROMEOS_CROS_MOCK_INPUT_METHOD_LIBRARY_H_ - |