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 8159e149c8f8e528b936dadf79d1a8d5460011f6..07dc434f23e664001136f82ea626c5333ee168e6 100644 |
--- a/chrome/browser/chromeos/input_method/input_method_manager.cc |
+++ b/chrome/browser/chromeos/input_method/input_method_manager.cc |
@@ -4,1277 +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 |
- |
-#if defined(HAVE_IBUS) |
-#include <ibus.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()); |
-#if defined(HAVE_IBUS) |
-#if IBUS_CHECK_VERSION(1, 4, 99) |
- ibus_controller_->ChangeInputMethod(value.string_list_value[0]); |
-#endif |
-#endif |
- } 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], ¤t_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 |
Zachary Kuznia
2012/04/17 01:26:36
It's supposed to be safe to call delete on a null
Yusuke Sato
2012/04/17 02:23:32
Done.
|
+ // '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 |