summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/cros
diff options
context:
space:
mode:
authorzork@chromium.org <zork@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-26 09:01:40 +0000
committerzork@chromium.org <zork@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-26 09:01:40 +0000
commit36da236c34e8f3433d1a670c4a3ba039dfc975b3 (patch)
tree8a9a78c7bc7a769f94f32aa10015b306e815f7c7 /chrome/browser/chromeos/cros
parentc5a49592b1cbe19e8866e31f4727dac2e5a8dd64 (diff)
downloadchromium_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.cc126
-rw-r--r--chrome/browser/chromeos/cros/input_method_library.h25
-rw-r--r--chrome/browser/chromeos/cros/mock_input_method_library.h3
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_
-