Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Unified Diff: chrome/browser/chromeos/input_method/input_method_manager.cc

Issue 9999018: chrome/browser/chromeos/input_method/ refactoring [part 6 of 6] (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase, remove preferences.h and language_preference.* from this CL Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/input_method/input_method_manager.cc
diff --git a/chrome/browser/chromeos/input_method/input_method_manager.cc b/chrome/browser/chromeos/input_method/input_method_manager.cc
index 7b0f302f9fd65405c1c4d1e58bcfa7b323469384..07dc434f23e664001136f82ea626c5333ee168e6 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager.cc
@@ -4,1268 +4,51 @@
#include "chrome/browser/chromeos/input_method/input_method_manager.h"
-#include <algorithm>
-
-#include <glib.h>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/singleton.h"
-#include "base/message_loop.h"
-#include "base/process_util.h"
-#include "base/string_split.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/input_method/browser_state_monitor.h"
-#include "chrome/browser/chromeos/input_method/input_method_util.h"
-#include "chrome/browser/chromeos/input_method/input_method_whitelist.h"
-#include "chrome/browser/chromeos/input_method/virtual_keyboard_selector.h"
-#include "chrome/browser/chromeos/input_method/xkeyboard.h"
-#include "chrome/browser/chromeos/language_preferences.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
-#include "googleurl/src/gurl.h"
-#include "ui/base/accelerators/accelerator.h"
-#include "unicode/uloc.h"
-
-#if !defined(USE_VIRTUAL_KEYBOARD)
-#include "chrome/browser/chromeos/input_method/candidate_window.h"
-#endif
-
-using content::BrowserThread;
-
-namespace {
-
-const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon";
-
-// Finds a property which has |new_prop.key| from |prop_list|, and replaces the
-// property with |new_prop|. Returns true if such a property is found.
-bool FindAndUpdateProperty(
- const chromeos::input_method::InputMethodProperty& new_prop,
- chromeos::input_method::InputMethodPropertyList* prop_list) {
- for (size_t i = 0; i < prop_list->size(); ++i) {
- chromeos::input_method::InputMethodProperty& prop = prop_list->at(i);
- if (prop.key == new_prop.key) {
- const int saved_id = prop.selection_item_id;
- // Update the list except the radio id. As written in
- // chromeos_input_method.h, |prop.selection_item_id| is dummy.
- prop = new_prop;
- prop.selection_item_id = saved_id;
- return true;
- }
- }
- return false;
-}
-
-} // namespace
+#include "chrome/browser/chromeos/input_method/input_method_manager_impl.h"
namespace chromeos {
namespace input_method {
-// The implementation of InputMethodManager.
-class InputMethodManagerImpl : public InputMethodManager,
- public content::NotificationObserver,
-#if !defined(USE_VIRTUAL_KEYBOARD)
- public CandidateWindowController::Observer,
-#endif
- public IBusController::Observer {
- public:
- InputMethodManagerImpl()
- : ibus_controller_(IBusController::Create()),
- should_hide_properties_(true),
- should_launch_ime_(false),
- ime_connected_(false),
- enable_auto_ime_shutdown_(false), // workaround for crosbug.com/27051.
- enable_extension_imes_(true),
- shutting_down_(false),
- ibus_daemon_process_handle_(base::kNullProcessHandle),
- util_(whitelist_.GetSupportedInputMethods()),
- xkeyboard_(XKeyboard::Create(util_)),
- ALLOW_THIS_IN_INITIALIZER_LIST(
- browser_state_monitor_(new BrowserStateMonitor(this))),
- ignore_hotkeys_(false) {
- // Observe APP_TERMINATING to stop input method daemon gracefully.
- // We should not use APP_EXITING here since logout might be canceled by
- // JavaScript after APP_EXITING is sent (crosbug.com/11055).
- // Note that even if we fail to stop input method daemon from
- // Chrome in case of a sudden crash, we have a way to do it from an
- // upstart script. See crosbug.com/6515 and crosbug.com/6995 for
- // details.
- notification_registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING,
- content::NotificationService::AllSources());
-
- // The observer should be added before Connect() so we can capture the
- // initial connection change.
- ibus_controller_->AddObserver(this);
- ibus_controller_->Connect();
-
- EnableHotkeys();
- }
-
- virtual ~InputMethodManagerImpl() {
- ibus_controller_->RemoveObserver(this);
-#if !defined(USE_VIRTUAL_KEYBOARD)
- if (candidate_window_controller_.get())
- candidate_window_controller_->RemoveObserver(this);
-#endif
- }
-
- virtual void AddObserver(InputMethodManager::Observer* observer) {
- observers_.AddObserver(observer);
- }
-
- virtual void RemoveObserver(InputMethodManager::Observer* observer) {
- observers_.RemoveObserver(observer);
- }
-
- virtual void AddCandidateWindowObserver(
- InputMethodManager::CandidateWindowObserver* observer) {
- candidate_window_observers_.AddObserver(observer);
- }
-
- virtual void RemoveCandidateWindowObserver(
- InputMethodManager::CandidateWindowObserver* observer) {
- candidate_window_observers_.RemoveObserver(observer);
- }
-
- virtual void AddVirtualKeyboardObserver(VirtualKeyboardObserver* observer) {
- virtual_keyboard_observers_.AddObserver(observer);
- }
-
- virtual void RemoveVirtualKeyboardObserver(
- VirtualKeyboardObserver* observer) {
- virtual_keyboard_observers_.RemoveObserver(observer);
- }
-
- virtual InputMethodDescriptors* GetActiveInputMethods() {
- InputMethodDescriptors* result = new InputMethodDescriptors;
- // Build the active input method descriptors from the active input
- // methods cache |active_input_method_ids_|.
- for (size_t i = 0; i < active_input_method_ids_.size(); ++i) {
- const std::string& input_method_id = active_input_method_ids_[i];
- const InputMethodDescriptor* descriptor =
- util_.GetInputMethodDescriptorFromId(input_method_id);
- if (descriptor) {
- result->push_back(*descriptor);
- } else {
- std::map<std::string, InputMethodDescriptor>::
- const_iterator ix = extra_input_method_ids_.find(input_method_id);
- if (ix != extra_input_method_ids_.end()) {
- result->push_back(ix->second);
- } else {
- LOG(ERROR) << "Descriptor is not found for: " << input_method_id;
- }
- }
- }
- // Initially active_input_method_ids_ is empty. In this case, just
- // returns the fallback input method descriptor.
- if (result->empty()) {
- // Since browser_tests call neither
- // SetInputMethodConfig("preload_engines") nor EnableInputMethod(), this
- // path might be taken.
- result->push_back(
- InputMethodDescriptor::GetFallbackInputMethodDescriptor());
- }
- return result;
- }
-
- virtual size_t GetNumActiveInputMethods() {
- scoped_ptr<InputMethodDescriptors> input_methods(GetActiveInputMethods());
- return input_methods->size();
- }
-
- virtual InputMethodDescriptors* GetSupportedInputMethods() {
- return whitelist_.GetSupportedInputMethods();
- }
-
- virtual void ChangeInputMethod(const std::string& input_method_id) {
- // Changing the input method isn't guaranteed to succeed here, but we
- // should remember the last one regardless. See comments in
- // FlushImeConfig() for details.
- tentative_current_input_method_id_ = input_method_id;
-
- if (InputMethodUtil::IsKeyboardLayout(input_method_id)) {
- // We shouldn't use SetCurrentKeyboardLayoutByName() here. See
- // comments at ChangeCurrentInputMethod() for details.
- ChangeCurrentInputMethodFromId(input_method_id);
- OnRegisterImeProperties(InputMethodPropertyList()); // notify the button.
- } else {
- // Otherwise, start the input method daemon, and change the input
- // method via the daemon.
- StartInputMethodDaemon();
- // ChangeInputMethodViaIBus() fails if the IBus daemon is not
- // ready yet. In this case, we'll defer the input method change
- // until the daemon is ready.
- if (!ChangeInputMethodViaIBus(input_method_id)) {
- VLOG(1) << "Failed to change the input method to " << input_method_id
- << " (deferring)";
- }
- }
- }
-
- virtual void EnableLayouts(const std::string& language_code,
- const std::string& initial_input_method_id) {
- std::vector<std::string> candidates;
- // Add input methods associated with the language.
- util_.GetInputMethodIdsFromLanguageCode(language_code,
- kKeyboardLayoutsOnly,
- &candidates);
- // Add the hardware keyboard as well. We should always add this so users
- // can use the hardware keyboard on the login screen and the screen locker.
- candidates.push_back(util_.GetHardwareInputMethodId());
-
- std::vector<std::string> input_method_ids;
- // First, add the initial input method ID, if it's requested, to
- // input_method_ids, so it appears first on the list of active input
- // methods at the input language status menu.
- if (!initial_input_method_id.empty()) {
- input_method_ids.push_back(initial_input_method_id);
- }
-
- // Add candidates to input_method_ids, while skipping duplicates.
- for (size_t i = 0; i < candidates.size(); ++i) {
- const std::string& candidate = candidates[i];
- // Not efficient, but should be fine, as the two vectors are very
- // short (2-5 items).
- if (std::count(input_method_ids.begin(), input_method_ids.end(),
- candidate) == 0) {
- input_method_ids.push_back(candidate);
- }
- }
-
- // Update ibus-daemon setting. Here, we don't save the input method list
- // in the user's preferences.
- InputMethodConfigValue value;
- value.type = InputMethodConfigValue::kValueTypeStringList;
- value.string_list_value = input_method_ids;
- SetInputMethodConfig(language_prefs::kGeneralSectionName,
- language_prefs::kPreloadEnginesConfigName,
- value);
-
- // Finaly, change to the initial input method, as needed.
- if (!initial_input_method_id.empty()) {
- ChangeInputMethod(initial_input_method_id);
- }
- }
-
- virtual void SetImePropertyActivated(const std::string& key,
- bool activated) {
- DCHECK(!key.empty());
- ibus_controller_->SetImePropertyActivated(key, activated);
- }
-
- virtual bool InputMethodIsActivated(const std::string& input_method_id) {
- scoped_ptr<InputMethodDescriptors> active_input_method_descriptors(
- GetActiveInputMethods());
- for (size_t i = 0; i < active_input_method_descriptors->size(); ++i) {
- if (active_input_method_descriptors->at(i).id() == input_method_id) {
- return true;
- }
- }
- return false;
- }
-
- virtual bool SetInputMethodConfig(const std::string& section,
- const std::string& config_name,
- const InputMethodConfigValue& value) {
- // If the config change is for preload engines, update the active
- // input methods cache |active_input_method_ids_| here. We need to
- // update the cache before actually flushing the config. since we need
- // to return active input methods from GetActiveInputMethods() before
- // the input method daemon starts. For instance, we need to show the
- // list of available input methods (keyboard layouts) on the login
- // screen before the input method starts.
- if (section == language_prefs::kGeneralSectionName &&
- config_name == language_prefs::kPreloadEnginesConfigName &&
- value.type == InputMethodConfigValue::kValueTypeStringList) {
- active_input_method_ids_ = value.string_list_value;
-
- if (enable_extension_imes_) {
- std::map<std::string, InputMethodDescriptor>::const_iterator ix;
- for (ix = extra_input_method_ids_.begin();
- ix != extra_input_method_ids_.end(); ++ix) {
- active_input_method_ids_.push_back(ix->first);
- }
- }
- }
-
- // Before calling FlushImeConfig(), start input method process if necessary.
- MaybeStartInputMethodDaemon(section, config_name, value);
-
- const ConfigKeyType key = std::make_pair(section, config_name);
- current_config_values_[key] = value;
- if (ime_connected_) {
- pending_config_requests_[key] = value;
- FlushImeConfig();
- }
-
- if (section == language_prefs::kGeneralSectionName &&
- config_name == language_prefs::kPreloadEnginesConfigName) {
- // Stop input method process if necessary.
- MaybeStopInputMethodDaemon();
- }
- // Change the current keyboard layout if necessary.
- MaybeChangeCurrentKeyboardLayout(section, config_name, value);
- return pending_config_requests_.empty();
- }
-
- // TODO(yusukes): Support input method specific hotkeys.
- virtual void AddActiveIme(const std::string& id,
- const std::string& name,
- const std::vector<std::string>& layouts,
- const std::string& language) {
- std::string virtual_layouts = JoinString(layouts, ',');
-
- extra_input_method_ids_[id] = ibus_controller_->CreateInputMethodDescriptor(
- id, name, virtual_layouts, language);
- active_input_method_ids_.push_back(id);
-
- // Ensure that the input method daemon is running.
- StartInputMethodDaemon();
- }
-
- virtual void RemoveActiveIme(const std::string& id) {
- std::vector<std::string>::iterator ix =
- std::find(active_input_method_ids_.begin(),
- active_input_method_ids_.end(),
- id);
- if (ix != active_input_method_ids_.end()) {
- active_input_method_ids_.erase(ix);
- // TODO(yusukes): this is a workaround for crosbug.com/27051. Uncomment
- // this when the bug is fixed.
- if (!active_input_method_ids_.empty()) {
- ChangeInputMethod(active_input_method_ids_[0]);
- }
- }
- extra_input_method_ids_.erase(id);
-
- // Stop the IME daemon if needed.
- MaybeStopInputMethodDaemon();
- }
-
- virtual bool GetExtraDescriptor(const std::string& id,
- InputMethodDescriptor* descriptor) {
- std::map<std::string, InputMethodDescriptor>::const_iterator ix =
- extra_input_method_ids_.find(id);
- if (ix != extra_input_method_ids_.end()) {
- *descriptor = ix->second;
- return true;
- } else {
- return false;
- }
- }
-
- virtual InputMethodDescriptor GetPreviousInputMethod() const {
- if (previous_input_method_.id().empty()) {
- return InputMethodDescriptor::GetFallbackInputMethodDescriptor();
- }
- return previous_input_method_;
- }
-
- virtual InputMethodDescriptor GetCurrentInputMethod() const {
- if (current_input_method_.id().empty()) {
- return InputMethodDescriptor::GetFallbackInputMethodDescriptor();
- }
- return current_input_method_;
- }
-
- virtual InputMethodPropertyList GetCurrentInputMethodProperties() const {
- if (should_hide_properties_ ||
- InputMethodUtil::IsKeyboardLayout(GetCurrentInputMethod().id())) {
- return InputMethodPropertyList();
- }
- return current_ime_properties_;
- }
-
- virtual void SendHandwritingStroke(const HandwritingStroke& stroke) {
- ibus_controller_->SendHandwritingStroke(stroke);
- }
-
- virtual void CancelHandwritingStrokes(int stroke_count) {
- // TODO(yusukes): Rename the function to CancelHandwritingStrokes.
- ibus_controller_->CancelHandwriting(stroke_count);
- }
-
- virtual void RegisterVirtualKeyboard(const GURL& launch_url,
- const std::string& name,
- const std::set<std::string>& layouts,
- bool is_system) {
- virtual_keyboard_selector_.AddVirtualKeyboard(launch_url,
- name,
- layouts,
- is_system);
- }
-
- virtual const std::map<GURL, const VirtualKeyboard*>&
- GetUrlToKeyboardMapping() const {
- return virtual_keyboard_selector_.url_to_keyboard();
- }
-
- virtual const std::multimap<std::string, const VirtualKeyboard*>&
- GetLayoutNameToKeyboardMapping() const {
- return virtual_keyboard_selector_.layout_to_keyboard();
- }
-
- virtual bool SetVirtualKeyboardPreference(const std::string& input_method_id,
- const GURL& extention_url) {
- const bool result = virtual_keyboard_selector_.SetUserPreference(
- input_method_id, extention_url);
- UpdateVirtualKeyboardUI();
- return result;
- }
-
- virtual void ClearAllVirtualKeyboardPreferences() {
- virtual_keyboard_selector_.ClearAllUserPreferences();
- UpdateVirtualKeyboardUI();
- }
-
- virtual InputMethodUtil* GetInputMethodUtil() {
- return &util_;
- }
-
- virtual XKeyboard* GetXKeyboard() {
- return xkeyboard_.get();
- }
-
- virtual void CandidateWindowOpened() {
- FOR_EACH_OBSERVER(InputMethodManager::CandidateWindowObserver,
- candidate_window_observers_,
- CandidateWindowOpened(this));
- }
-
- virtual void CandidateWindowClosed() {
- FOR_EACH_OBSERVER(InputMethodManager::CandidateWindowObserver,
- candidate_window_observers_,
- CandidateWindowClosed(this));
- }
-
- virtual bool SwitchToNextInputMethod() {
- if (ignore_hotkeys_) {
- return false;
- }
-
- // Sanity checks.
- if (active_input_method_ids_.empty()) {
- LOG(ERROR) << "active input method is empty";
- return false;
- }
- if (current_input_method_.id().empty()) {
- LOG(ERROR) << "current_input_method_ is unknown";
- return false;
- }
-
- // Find the next input method.
- std::vector<std::string>::const_iterator iter =
- std::find(active_input_method_ids_.begin(),
- active_input_method_ids_.end(),
- current_input_method_.id());
- if (iter != active_input_method_ids_.end()) {
- ++iter;
- }
- if (iter == active_input_method_ids_.end()) {
- iter = active_input_method_ids_.begin();
- }
- ChangeInputMethod(*iter);
- return true;
- }
-
- virtual bool SwitchToPreviousInputMethod() {
- if (ignore_hotkeys_) {
- return false;
- }
-
- // Sanity check.
- if (active_input_method_ids_.empty()) {
- LOG(ERROR) << "active input method is empty";
- return false;
- }
-
- if (previous_input_method_.id().empty() ||
- previous_input_method_.id() == current_input_method_.id()) {
- return SwitchToNextInputMethod();
- }
-
- std::vector<std::string>::const_iterator iter =
- std::find(active_input_method_ids_.begin(),
- active_input_method_ids_.end(),
- previous_input_method_.id());
- if (iter == active_input_method_ids_.end()) {
- // previous_input_method_ is not supported.
- return SwitchToNextInputMethod();
- }
- ChangeInputMethod(*iter);
- return true;
- }
-
- virtual bool SwitchInputMethod(const ui::Accelerator& accelerator) {
- if (ignore_hotkeys_) {
- return false;
- }
-
- // Sanity check.
- if (active_input_method_ids_.empty()) {
- LOG(ERROR) << "active input method is empty";
- return false;
- }
-
- // Get the list of input method ids for the |accelerator|. For example, get
- // { "mozc-hangul", "xkb:kr:kr104:kor" } for ui::VKEY_DBE_SBCSCHAR.
- std::vector<std::string> input_method_ids_to_switch;
- switch (accelerator.key_code()) {
- case ui::VKEY_CONVERT: // Henkan key on JP106 keyboard
- input_method_ids_to_switch.push_back("mozc-jp");
- break;
- case ui::VKEY_NONCONVERT: // Muhenkan key on JP106 keyboard
- input_method_ids_to_switch.push_back("xkb:jp::jpn");
- break;
- case ui::VKEY_DBE_SBCSCHAR: // ZenkakuHankaku key on JP106 keyboard
- case ui::VKEY_DBE_DBCSCHAR:
- input_method_ids_to_switch.push_back("mozc-jp");
- input_method_ids_to_switch.push_back("xkb:jp::jpn");
- break;
- case ui::VKEY_HANGUL: // Hangul (or right Alt) key on Korean keyboard
- case ui::VKEY_SPACE: // Shift+Space
- input_method_ids_to_switch.push_back("mozc-hangul");
- input_method_ids_to_switch.push_back("xkb:kr:kr104:kor");
- break;
- default:
- NOTREACHED();
- break;
- }
- if (input_method_ids_to_switch.empty()) {
- LOG(ERROR) << "Unexpected VKEY: " << accelerator.key_code();
- return false;
- }
-
- // Obtain the intersection of input_method_ids_to_switch and
- // active_input_method_ids_. The order of IDs in active_input_method_ids_ is
- // preserved.
- std::vector<std::string> ids;
- for (size_t i = 0; i < input_method_ids_to_switch.size(); ++i) {
- const std::string& id = input_method_ids_to_switch[i];
- if (std::find(active_input_method_ids_.begin(),
- active_input_method_ids_.end(),
- id) != active_input_method_ids_.end()) {
- ids.push_back(id);
- }
- }
- if (ids.empty()) {
- // No input method for the accelerator is active. For example, we should
- // just ignore VKEY_HANGUL when mozc-hangul is not active.
- return false;
- }
-
- // If |current_input_method_| is not in ids, switch to ids[0]. If
- // |current_input_method_| is ids[N], switch to ids[N+1].
- std::vector<std::string>::const_iterator iter =
- std::find(ids.begin(), ids.end(), current_input_method_.id());
- if (iter != ids.end()) {
- ++iter;
- }
- if (iter == ids.end()) {
- iter = ids.begin();
- }
- ChangeInputMethod(*iter);
- return true; // consume the accelerator.
- }
-
- virtual void EnableHotkeys() {
- ignore_hotkeys_ = false;
- }
-
- virtual void DisableHotkeys() {
- ignore_hotkeys_ = true;
- }
-
- static InputMethodManagerImpl* GetInstance() {
- return Singleton<InputMethodManagerImpl,
- DefaultSingletonTraits<InputMethodManagerImpl> >::get();
- }
-
- private:
- friend struct DefaultSingletonTraits<InputMethodManagerImpl>;
-
- // Returns true if the given input method config value is a string list
- // that only contains an input method ID of a keyboard layout.
- bool ContainOnlyKeyboardLayout(const std::vector<std::string>& value) {
- for (size_t i = 0; i < value.size(); ++i) {
- if (!InputMethodUtil::IsKeyboardLayout(value[i])) {
- return false;
- }
- }
- return true;
- }
-
- // Starts input method daemon based on the input method configuration being
- // updated. |section| is a section name of the input method configuration
- // (e.g. "general", "general/hotkey"). |config_name| is a name of the
- // configuration (e.g. "preload_engines", "previous_engine"). |value| is the
- // configuration value to be set.
- void MaybeStartInputMethodDaemon(const std::string& section,
- const std::string& config_name,
- const InputMethodConfigValue& value) {
- if (section == language_prefs::kGeneralSectionName &&
- config_name == language_prefs::kPreloadEnginesConfigName &&
- value.type == InputMethodConfigValue::kValueTypeStringList &&
- !value.string_list_value.empty()) {
- // If there is only one input method which is a keyboard layout,
- // we don't start the input method processes.
- if (ContainOnlyKeyboardLayout(value.string_list_value)) {
- // Do not start the input method daemon.
- return;
- }
-
- // Otherwise, start the input method daemon.
- const bool just_started = StartInputMethodDaemon();
- if (!just_started) {
- // The daemon is already running.
- // Do not |update tentative_current_input_method_id_|.
- return;
- }
-
- // The daemon has just been started. To select the initial input method
- // engine correctly, update |tentative_current_input_method_id_|.
- if (tentative_current_input_method_id_.empty()) {
- // Since the |current_input_method_| is in the preloaded engine list,
- // switch to the engine. This is necessary ex. for the following case:
- // 1. "xkb:jp::jpn" is enabled. ibus-daemon is not running.
- // 2. A user enabled "mozc" via DOMUI as well. ibus-daemon is started
- // and the preloaded engine list is set to "mozc,xkb:jp::jpn".
- // 3. ibus-daemon selects "mozc" as its current engine since "mozc" is
- // on top of the preloaded engine list.
- // 4. Therefore, we have to change the current engine to "xkb:jp::jpn"
- // explicitly to avoid unexpected engine switch.
- tentative_current_input_method_id_ = current_input_method_.id();
- }
-
- if (std::find(value.string_list_value.begin(),
- value.string_list_value.end(),
- tentative_current_input_method_id_)
- == value.string_list_value.end()) {
- // The |current_input_method_| is NOT in the preloaded engine list.
- // In this case, ibus-daemon will automatically select the first engine
- // in the list, |value.string_list_value[0]|, and send global engine
- // changed signal to Chrome. See crosbug.com/13406.
- tentative_current_input_method_id_.clear();
- }
- }
- }
-
- // Stops input method daemon based on the |enable_auto_ime_shutdown_| flag
- // and input method configuration being updated.
- // See also: MaybeStartInputMethodDaemon().
- void MaybeStopInputMethodDaemon() {
- // If there is only one input method which is a keyboard layout,
- // and |enable_auto_ime_shutdown_| is true, we'll stop the input
- // method daemon.
- if (ContainOnlyKeyboardLayout(active_input_method_ids_) &&
- enable_auto_ime_shutdown_) {
- if (StopInputMethodDaemon()) {
- // The process is killed. Change the current keyboard layout.
- // We shouldn't use SetCurrentKeyboardLayoutByName() here. See
- // comments at ChangeCurrentInputMethod() for details.
- ChangeCurrentInputMethodFromId(active_input_method_ids_[0]);
- }
- }
- }
-
- // Change the keyboard layout per input method configuration being
- // updated, if necessary. See also: MaybeStartInputMethodDaemon().
- void MaybeChangeCurrentKeyboardLayout(const std::string& section,
- const std::string& config_name,
- const InputMethodConfigValue& value) {
- if (section == language_prefs::kGeneralSectionName &&
- config_name == language_prefs::kPreloadEnginesConfigName) {
- if (value.string_list_value.size() == 1 ||
- (value.string_list_value.size() != 0 &&
- std::find(value.string_list_value.begin(),
- value.string_list_value.end(),
- current_input_method_.id()) ==
- value.string_list_value.end())) {
- // This is necessary to initialize current_input_method_. This is also
- // necessary when the current layout (e.g. INTL) out of two or more
- // active ones (e.g. US, DV, and INTL) is disabled.
- ChangeCurrentInputMethodFromId(value.string_list_value[0]);
- }
- DCHECK(!current_input_method_.id().empty());
-
- // Update the indicator.
- // TODO(yusukes): Remove ActiveInputMethodsChanged notification in
- // FlushImeConfig().
- const size_t num_active_input_methods = GetNumActiveInputMethods();
- FOR_EACH_OBSERVER(InputMethodManager::Observer, observers_,
- ActiveInputMethodsChanged(this,
- GetCurrentInputMethod(),
- num_active_input_methods));
- }
- }
-
- // Changes the current input method to |input_method_id| via IBus
- // daemon. If the id is not in the preload_engine list, this function
- // changes the current method to the first preloaded engine. Returns
- // true if the current engine is switched to |input_method_id| or the
- // first one.
- bool ChangeInputMethodViaIBus(const std::string& input_method_id) {
- std::string input_method_id_to_switch = input_method_id;
-
- if (!InputMethodIsActivated(input_method_id)) {
- // This path might be taken if prefs::kLanguageCurrentInputMethod (NOT
- // synced with cloud) and kLanguagePreloadEngines (synced with cloud) are
- // mismatched. e.g. the former is 'xkb:us::eng' and the latter (on the
- // sync server) is 'xkb:jp::jpn,mozc'.
- scoped_ptr<InputMethodDescriptors> input_methods(GetActiveInputMethods());
- DCHECK(!input_methods->empty());
- if (!input_methods->empty()) {
- input_method_id_to_switch = input_methods->at(0).id();
- LOG(INFO) << "Can't change the current input method to "
- << input_method_id << " since the engine is not preloaded. "
- << "Switch to " << input_method_id_to_switch << " instead.";
- }
- }
-
- if (ibus_controller_->ChangeInputMethod(input_method_id_to_switch)) {
- return true;
- }
-
- // ChangeInputMethod() fails if the IBus daemon is not yet ready.
- LOG(ERROR) << "Can't switch input method to " << input_method_id_to_switch;
- return false;
- }
-
- // Flushes the input method config data. The config data is queued up in
- // |pending_config_requests_| until the config backend (ibus-memconf)
- // starts.
- void FlushImeConfig() {
- bool active_input_methods_are_changed = false;
- InputMethodConfigRequests::iterator iter = pending_config_requests_.begin();
- while (iter != pending_config_requests_.end()) {
- const std::string& section = iter->first.first;
- const std::string& config_name = iter->first.second;
- InputMethodConfigValue& value = iter->second;
-
- if (config_name == language_prefs::kPreloadEnginesConfigName &&
- !tentative_current_input_method_id_.empty()) {
- // We should use |tentative_current_input_method_id_| as the initial
- // active input method for the following reasons:
- //
- // 1) Calls to ChangeInputMethod() will fail if the input method has not
- // yet been added to preload_engines. As such, the call is deferred
- // until after all config values have been sent to the IME process.
- //
- // 2) We might have already changed the current input method to one
- // of XKB layouts without going through the IBus daemon (we can do
- // it without the IBus daemon started).
- std::vector<std::string>::iterator engine_iter = std::find(
- value.string_list_value.begin(),
- value.string_list_value.end(),
- tentative_current_input_method_id_);
- if (engine_iter != value.string_list_value.end()) {
- // Use std::rotate to keep the relative order of engines the same e.g.
- // from "A,B,C" to "C,A,B".
- // We don't have to |active_input_method_ids_|, which decides the
- // order of engines in the switcher menu, since the relative order
- // of |value.string_list_value| is not changed.
- std::rotate(value.string_list_value.begin(),
- engine_iter, // this becomes the new first element
- value.string_list_value.end());
- } else {
- LOG(WARNING) << tentative_current_input_method_id_
- << " is not in preload_engines: " << value.ToString();
- }
- tentative_current_input_method_id_.erase();
- }
-
- if (ibus_controller_->SetInputMethodConfig(section, config_name, value)) {
- // Check if it's a change in active input methods.
- if (config_name == language_prefs::kPreloadEnginesConfigName) {
- active_input_methods_are_changed = true;
- VLOG(1) << "Updated preload_engines: " << value.ToString();
- }
- // Successfully sent. Remove the command and proceed to the next one.
- pending_config_requests_.erase(iter++);
- } else {
- // If SetInputMethodConfig() fails, subsequent calls will likely fail.
- break;
- }
- }
-
- // Notify the current input method and the number of active input methods to
- // the UI so that the UI could determine e.g. if it should show/hide the
- // input method indicator, etc. We have to call FOR_EACH_OBSERVER here since
- // updating "preload_engine" does not necessarily trigger a DBus signal such
- // as "global-engine-changed". For example,
- // 1) If we change the preload_engine from "xkb:us:intl:eng" (i.e. the
- // indicator is hidden) to "xkb:us:intl:eng,mozc", we have to update UI
- // so it shows the indicator, but no signal is sent from ibus-daemon
- // because the current input method is not changed.
- // 2) If we change the preload_engine from "xkb:us::eng,mozc" (i.e. the
- // indicator is shown and ibus-daemon is started) to "xkb:us::eng", we
- // have to update UI so it hides the indicator, but we should not expect
- // that ibus-daemon could send a DBus signal since the daemon is killed
- // right after this FlushImeConfig() call.
- if (active_input_methods_are_changed) {
- // The |current_input_method_| member might be stale here as
- // SetInputMethodConfig("preload_engine") call above might change the
- // current input method in ibus-daemon (ex. this occurs when the
- // input method currently in use is removed from the options
- // page). However, it should be safe to use the member here,
- // for the following reasons:
- // 1. If ibus-daemon is to be killed, we'll switch to the only one
- // keyboard layout, and observers are notified. See
- // MaybeStopInputMethodDaemon() for details.
- // 2. Otherwise, "global-engine-changed" signal is delivered from
- // ibus-daemon, and observers are notified. See
- // InputMethodChangedHandler() for details.
- const size_t num_active_input_methods = GetNumActiveInputMethods();
- FOR_EACH_OBSERVER(InputMethodManager::Observer, observers_,
- ActiveInputMethodsChanged(this,
- current_input_method_,
- num_active_input_methods));
- }
- }
-
- // IBusController override.
- virtual void OnCurrentInputMethodChanged(
- const InputMethodDescriptor& current_input_method) {
- // The handler is called when the input method method change is
- // notified via a DBus connection. Since the DBus notificatiosn are
- // handled in the UI thread, we can assume that this function always
- // runs on the UI thread, but just in case.
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- LOG(ERROR) << "Not on UI thread";
- return;
- }
-
- ChangeCurrentInputMethod(current_input_method);
- }
-
- // IBusController override.
- virtual void OnRegisterImeProperties(
- const InputMethodPropertyList& prop_list) {
- // See comments in InputMethodChangedHandler.
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- LOG(ERROR) << "Not on UI thread";
- return;
- }
-
- RegisterProperties(prop_list);
- }
-
- // IBusController override.
- virtual void OnUpdateImeProperty(
- const InputMethodPropertyList& prop_list) {
- // See comments in InputMethodChangedHandler.
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- LOG(ERROR) << "Not on UI thread";
- return;
- }
-
- UpdateProperty(prop_list);
- }
-
- // IBusController override.
- virtual void OnConnectionChange(bool connected) {
- // See comments in InputMethodChangedHandler.
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- LOG(ERROR) << "Not on UI thread";
- return;
- }
-
- ime_connected_ = connected;
- if (connected) {
- pending_config_requests_.clear();
- pending_config_requests_.insert(current_config_values_.begin(),
- current_config_values_.end());
- FlushImeConfig();
- }
- }
-
- // Changes the current input method from the given input method
- // descriptor. This function updates states like current_input_method_
- // and notifies observers about the change (that will update the
- // preferences), hence this function should always be used even if you
- // just need to change the current keyboard layout.
- void ChangeCurrentInputMethod(const InputMethodDescriptor& new_input_method) {
- if (current_input_method_.id() != new_input_method.id()) {
- previous_input_method_ = current_input_method_;
- current_input_method_ = new_input_method;
-
- // Change the keyboard layout to a preferred layout for the input method.
- if (!xkeyboard_->SetCurrentKeyboardLayoutByName(
- current_input_method_.keyboard_layout())) {
- LOG(ERROR) << "Failed to change keyboard layout to "
- << current_input_method_.keyboard_layout();
- }
- }
-
- // Update input method indicators (e.g. "US", "DV") in Chrome windows.
- // For now, we have to do this every time to keep indicators updated. See
- // comments near the FOR_EACH_OBSERVER call in FlushImeConfig() for details.
- const size_t num_active_input_methods = GetNumActiveInputMethods();
- FOR_EACH_OBSERVER(InputMethodManager::Observer, observers_,
- InputMethodChanged(this,
- current_input_method_,
- num_active_input_methods));
-
- UpdateVirtualKeyboardUI();
- }
-
- void UpdateVirtualKeyboardUI() {
-#if defined(USE_VIRTUAL_KEYBOARD)
- const VirtualKeyboard* virtual_keyboard = NULL;
- std::string virtual_keyboard_layout = "";
-
- const std::vector<std::string>& layouts_vector =
- current_input_method_.virtual_keyboard_layouts();
- std::vector<std::string>::const_iterator iter;
- for (iter = layouts_vector.begin(); iter != layouts_vector.end(); ++iter) {
- virtual_keyboard =
- virtual_keyboard_selector_.SelectVirtualKeyboard(*iter);
- if (virtual_keyboard) {
- virtual_keyboard_layout = *iter;
- break;
- }
- }
-
- if (!virtual_keyboard) {
- // The system virtual keyboard does not support some XKB layouts? or
- // a third-party input method engine uses a wrong virtual keyboard
- // layout name? Fallback to the default layout.
- LOG(ERROR) << "Could not find a virtual keyboard for "
- << current_input_method_.id();
-
- // If the hardware is for US, show US Qwerty virtual keyboard.
- // If it's for France, show Azerty one.
- const std::string fallback_id = GetInputMethodUtil()->
- GetHardwareInputMethodId();
- const InputMethodDescriptor* fallback_desc =
- GetInputMethodUtil()->GetInputMethodDescriptorFromId(fallback_id);
-
- DCHECK(fallback_desc);
- const std::vector<std::string>& fallback_layouts_vector =
- fallback_desc->virtual_keyboard_layouts();
-
- for (iter = fallback_layouts_vector.begin();
- iter != fallback_layouts_vector.end();
- ++iter) {
- virtual_keyboard =
- virtual_keyboard_selector_.SelectVirtualKeyboard(*iter);
- if (virtual_keyboard) {
- virtual_keyboard_layout = *iter;
- LOG(ERROR) << "Fall back to '" << (*iter) << "' virtual keyboard";
- break;
- }
- }
- }
-
- if (!virtual_keyboard) {
- // kFallbackVirtualKeyboardLayout should always be supported by one of the
- // system virtual keyboards.
- static const char kFallbackVirtualKeyboardLayout[] = "us";
-
- LOG(ERROR) << "Could not find a FALLBACK virtual keyboard for "
- << current_input_method_.id()
- << ". Use '" << kFallbackVirtualKeyboardLayout
- << "' virtual keyboard";
- virtual_keyboard = virtual_keyboard_selector_.SelectVirtualKeyboard(
- kFallbackVirtualKeyboardLayout);
- virtual_keyboard_layout = kFallbackVirtualKeyboardLayout;
- }
-
- if (virtual_keyboard) {
- FOR_EACH_OBSERVER(VirtualKeyboardObserver, virtual_keyboard_observers_,
- VirtualKeyboardChanged(this,
- *virtual_keyboard,
- virtual_keyboard_layout));
- }
-#endif // USE_VIRTUAL_KEYBOARD
- }
-
- // Changes the current input method from the given input method ID.
- // This function is just a wrapper of ChangeCurrentInputMethod().
- void ChangeCurrentInputMethodFromId(const std::string& input_method_id) {
- const InputMethodDescriptor* descriptor =
- util_.GetInputMethodDescriptorFromId(input_method_id);
- if (descriptor) {
- ChangeCurrentInputMethod(*descriptor);
- } else {
- LOG(ERROR) << "Descriptor is not found for: " << input_method_id;
- }
- }
-
- // Registers the properties used by the current input method.
- void RegisterProperties(const InputMethodPropertyList& prop_list) {
- // |prop_list| might be empty. This means "hide properties."
- if (prop_list.empty()) {
- should_hide_properties_ = true;
- } else {
- should_hide_properties_ = false;
- current_ime_properties_ = prop_list;
- }
- // Update input method menu
- FOR_EACH_OBSERVER(InputMethodManager::Observer, observers_,
- PropertyListChanged(this,
- GetCurrentInputMethodProperties()));
- }
-
- // Starts the input method daemon. Unlike MaybeStopInputMethodDaemon(),
- // this function always starts the daemon. Returns true if the daemon is
- // started. Otherwise, e.g. the daemon is already started, returns false.
- bool StartInputMethodDaemon() {
- should_launch_ime_ = true;
- return MaybeLaunchInputMethodDaemon();
- }
-
- // Updates the properties used by the current input method.
- void UpdateProperty(const InputMethodPropertyList& prop_list) {
- for (size_t i = 0; i < prop_list.size(); ++i) {
- FindAndUpdateProperty(prop_list[i], &current_ime_properties_);
- }
-
- // Update input method menu
- FOR_EACH_OBSERVER(InputMethodManager::Observer, observers_,
- PropertyListChanged(this,
- GetCurrentInputMethodProperties()));
- }
-
- // Launches an input method procsess specified by the given command
- // line. On success, returns true and stores the process handle in
- // |process_handle|. Otherwise, returns false, and the contents of
- // |process_handle| is untouched. OnImeShutdown will be called when the
- // process terminates.
- bool LaunchInputMethodProcess(const std::string& command_line,
- base::ProcessHandle* process_handle) {
- std::vector<std::string> argv;
- base::ProcessHandle handle = base::kNullProcessHandle;
-
- // TODO(zork): export "LD_PRELOAD=/usr/lib/libcrash.so"
- base::SplitString(command_line, ' ', &argv);
-
- if (!base::LaunchProcess(argv, base::LaunchOptions(), &handle)) {
- LOG(ERROR) << "Could not launch: " << command_line;
- return false;
- }
-
- // g_child_watch_add is necessary to prevent the process from becoming a
- // zombie.
- // TODO(yusukes): port g_child_watch_add to base/process_utils_posix.cc.
- const base::ProcessId pid = base::GetProcId(handle);
- g_child_watch_add(pid,
- reinterpret_cast<GChildWatchFunc>(OnImeShutdown),
- this);
-
- *process_handle = handle;
- VLOG(1) << command_line << " (PID=" << pid << ") is started";
- return true;
- }
-
- // Launches input method daemon if these are not yet running. Returns true if
- // the daemon is started. Otherwise, e.g. the daemon is already started,
- // returns false.
- bool MaybeLaunchInputMethodDaemon() {
- if (!should_launch_ime_) {
- return false;
- }
-
- if (shutting_down_) {
- NOTREACHED() << "Trying to launch input method while shutting down";
- return false;
- }
-
-#if !defined(USE_VIRTUAL_KEYBOARD)
- if (!candidate_window_controller_.get()) {
- candidate_window_controller_.reset(
- CandidateWindowController::CreateCandidateWindowController());
- if (candidate_window_controller_->Init()) {
- candidate_window_controller_->AddObserver(this);
- } else {
- LOG(WARNING) << "Failed to initialize the candidate window controller";
- }
- }
-#endif
-
- if (ibus_daemon_process_handle_ != base::kNullProcessHandle) {
- return false; // ibus-daemon is already running.
- }
-
- // TODO(zork): Send output to /var/log/ibus.log
- const std::string ibus_daemon_command_line =
- base::StringPrintf(
- "%s --panel=disable --cache=none --restart --replace",
- kIBusDaemonPath);
- if (!LaunchInputMethodProcess(
- ibus_daemon_command_line, &ibus_daemon_process_handle_)) {
- LOG(ERROR) << "Failed to launch " << ibus_daemon_command_line;
- return false;
- }
- return true;
- }
-
- // Called when the input method process is shut down.
- static void OnImeShutdown(GPid pid,
- gint status,
- InputMethodManagerImpl* library) {
- if (library->ibus_daemon_process_handle_ != base::kNullProcessHandle &&
- base::GetProcId(library->ibus_daemon_process_handle_) == pid) {
- library->ibus_daemon_process_handle_ = base::kNullProcessHandle;
- }
-
- // Restart input method daemon if needed.
- library->MaybeLaunchInputMethodDaemon();
- }
-
- // Stops the backend input method daemon. This function should also be
- // called from MaybeStopInputMethodDaemon(), except one case where we
- // stop the input method daemon at Chrome shutdown in Observe(). Returns true
- // if the daemon is stopped. Otherwise, e.g. the daemon is already stopped,
- // returns false.
- bool StopInputMethodDaemon() {
- should_launch_ime_ = false;
- if (ibus_daemon_process_handle_ != base::kNullProcessHandle) {
- const base::ProcessId pid = base::GetProcId(ibus_daemon_process_handle_);
- if (!ibus_controller_->StopInputMethodProcess()) {
- LOG(ERROR) << "StopInputMethodProcess IPC failed. Sending SIGTERM to "
- << "PID " << pid;
- base::KillProcess(ibus_daemon_process_handle_, -1, false /* wait */);
- }
- VLOG(1) << "ibus-daemon (PID=" << pid << ") is terminated";
- ibus_daemon_process_handle_ = base::kNullProcessHandle;
- return true;
- }
- return false;
- }
-
- void SetEnableAutoImeShutdown(bool enable) {
- // TODO(yusukes): this is a workaround for crosbug.com/27051. Uncommen this
- // when the bug is fixed.
-
- // enable_auto_ime_shutdown_ = enable;
- }
-
- void SetEnableExtensionIMEs(bool enable) {
- enable_extension_imes_ = enable;
- }
-
- // content::NotificationObserver implementation:
- void Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- // Stop the input method daemon on browser shutdown.
- if (type == content::NOTIFICATION_APP_TERMINATING) {
- shutting_down_ = true;
- notification_registrar_.RemoveAll();
- StopInputMethodDaemon();
-#if !defined(USE_VIRTUAL_KEYBOARD)
- if (candidate_window_controller_.get())
- candidate_window_controller_->RemoveObserver(this);
- candidate_window_controller_.reset(NULL);
-#endif
- // |browser_state_monitor_| has to be destructed while the PrefService
- // object associated with the monitor is alive. (crbug.com/120183)
- browser_state_monitor_.reset();
- }
- }
-
- // The IBus controller is used to control the input method status and
- // allow allow callbacks when the input method status changes.
- scoped_ptr<IBusController> ibus_controller_;
- ObserverList<InputMethodManager::Observer> observers_;
- ObserverList<InputMethodManager::CandidateWindowObserver>
- candidate_window_observers_;
- ObserverList<VirtualKeyboardObserver> virtual_keyboard_observers_;
-
- // The input method which was/is selected.
- InputMethodDescriptor previous_input_method_;
- InputMethodDescriptor current_input_method_;
-
- // The input method properties which the current input method uses. The list
- // might be empty when no input method is used.
- InputMethodPropertyList current_ime_properties_;
- bool should_hide_properties_;
-
- typedef std::pair<std::string, std::string> ConfigKeyType;
- typedef std::map<
- ConfigKeyType, InputMethodConfigValue> InputMethodConfigRequests;
- // SetInputMethodConfig requests that are not yet completed.
- // Use a map to queue config requests, so we only send the last request for
- // the same config key (i.e. we'll discard ealier requests for the same
- // config key). As we discard old requests for the same config key, the order
- // of requests doesn't matter, so it's safe to use a map.
- InputMethodConfigRequests pending_config_requests_;
-
- // Values that have been set via SetInputMethodConfig(). We keep a copy
- // available to resend if the ime restarts and loses its state.
- InputMethodConfigRequests current_config_values_;
-
- // This is used to register this object to APP_TERMINATING notification.
- content::NotificationRegistrar notification_registrar_;
-
- // True if we should launch the input method daemon.
- bool should_launch_ime_;
- // True if the connection to the IBus daemon is alive.
- bool ime_connected_;
- // True if we should stop input method daemon when there are no input
- // methods other than one for the hardware keyboard.
- bool enable_auto_ime_shutdown_;
- // True if extension IMEs can be enabled.
- bool enable_extension_imes_;
- // The ID of the tentative current input method (ex. "mozc"). This value
- // can be different from the actual current input method, if
- // ChangeInputMethod() fails.
- // TODO(yusukes): clear this variable when a user logs in.
- std::string tentative_current_input_method_id_;
-
- // The candidate window. This will be deleted when the APP_TERMINATING
- // message is sent.
-#if !defined(USE_VIRTUAL_KEYBOARD)
- scoped_ptr<CandidateWindowController> candidate_window_controller_;
-#endif
-
- // True if we've received the APP_TERMINATING notification.
- bool shutting_down_;
-
- // The process handle of the IBus daemon. kNullProcessHandle if it's not
- // running.
- base::ProcessHandle ibus_daemon_process_handle_;
-
- // An object which keeps a list of available virtual keyboards.
- VirtualKeyboardSelector virtual_keyboard_selector_;
-
- // The active input method ids cache.
- std::vector<std::string> active_input_method_ids_;
-
- // Extra input methods that have been explicitly added to the menu, such as
- // those created by extension.
- std::map<std::string, InputMethodDescriptor> extra_input_method_ids_;
-
- InputMethodWhitelist whitelist_;
-
- // An object which provides miscellaneous input method utility functions. Note
- // that |util_| is required to initialize |xkeyboard_|.
- InputMethodUtil util_;
-
- // An object for switching XKB layouts and keyboard status like caps lock and
- // auto-repeat interval.
- scoped_ptr<XKeyboard> xkeyboard_;
+namespace {
+InputMethodManager* g_input_method_manager = NULL;
+} // namespace
- // An object which monitors a notification from the browser to keep track of
- // the browser state (not logged in, logged in, etc.).
- scoped_ptr<BrowserStateMonitor> browser_state_monitor_;
+// static
+void InputMethodManager::Initialize() {
+ DCHECK(!g_input_method_manager);
+ InputMethodManagerImpl* impl = new InputMethodManagerImpl;
+ impl->Init();
+ g_input_method_manager = impl;
+ VLOG(1) << "InputMethodManager initialized";
+}
- // true when DisableHotkeys() is called to temporarily disable IME hotkeys.
- // EnableHotkeys() resets the flag to the default value, false.
- bool ignore_hotkeys_;
+// static
+void InputMethodManager::InitializeForTesting(
+ InputMethodManager* mock_manager) {
+ DCHECK(!g_input_method_manager);
+ g_input_method_manager = mock_manager;
+ VLOG(1) << "InputMethodManager for testing initialized";
+}
- DISALLOW_COPY_AND_ASSIGN(InputMethodManagerImpl);
-};
+// static
+void InputMethodManager::Shutdown() {
+ // TODO(yusukes): The NULL check is needed for some unit_tests such as
+ // 'WarmConnectionFieldTrial_WarmestSocket' which seem to destruct a
+ // ChromeBrowserMainPartsChromeos instance without calling
+ // ChromeBrowserMainPartsChromeos::PostMainMessageLoopStart(). It's probably
+ // better to fix the tests and remove the hack here.
+ if (!g_input_method_manager)
+ LOG(WARNING) << "InputMethodManager:Shutdown() called with NULL manager";
+ else
+ delete g_input_method_manager;
+ g_input_method_manager = NULL;
+ VLOG(1) << "InputMethodManager shutdown";
+}
// static
InputMethodManager* InputMethodManager::GetInstance() {
- return InputMethodManagerImpl::GetInstance();
+ DCHECK(g_input_method_manager);
+ return g_input_method_manager;
}
} // namespace input_method

Powered by Google App Engine
This is Rietveld 408576698