Index: chrome/browser/chromeos/input_method/ibus_controller_impl.cc |
diff --git a/chrome/browser/chromeos/input_method/ibus_controller_impl.cc b/chrome/browser/chromeos/input_method/ibus_controller_impl.cc |
index 3ebe361532ec04779da04515d2e0b9af76de3d73..5600809561919dc52c0eb989de03d34a4c24a016 100644 |
--- a/chrome/browser/chromeos/input_method/ibus_controller_impl.cc |
+++ b/chrome/browser/chromeos/input_method/ibus_controller_impl.cc |
@@ -29,17 +29,13 @@ |
#include "chromeos/dbus/ibus/ibus_config_client.h" |
#include "chromeos/dbus/ibus/ibus_constants.h" |
#include "chromeos/dbus/ibus/ibus_input_context_client.h" |
+#include "chromeos/dbus/ibus/ibus_panel_service.h" |
+#include "chromeos/dbus/ibus/ibus_property.h" |
#include "content/public/browser/browser_thread.h" |
#include "ui/aura/client/aura_constants.h" |
#include "ui/aura/root_window.h" |
#include "ui/base/ime/input_method_ibus.h" |
-// TODO(nona): Remove libibus dependency from this file. Then, write unit tests |
-// for all functions in this file. crbug.com/26334 |
-#if defined(HAVE_IBUS) |
-#include <ibus.h> |
-#endif |
- |
namespace { |
// Finds a property which has |new_prop.key| from |prop_list|, and replaces the |
@@ -66,123 +62,78 @@ void ConfigSetValueErrorCallback() { |
namespace chromeos { |
namespace input_method { |
-#if defined(HAVE_IBUS) |
-const char kPanelObjectKey[] = "panel-object"; |
- |
namespace { |
-const char* Or(const char* str1, const char* str2) { |
- return str1 ? str1 : str2; |
-} |
- |
// Returns true if |key| is blacklisted. |
-bool PropertyKeyIsBlacklisted(const char* key) { |
+bool PropertyKeyIsBlacklisted(const std::string& key) { |
// The list of input method property keys that we don't handle. |
static const char* kInputMethodPropertyKeysBlacklist[] = { |
"setup", // used in ibus-m17n. |
"status", // used in ibus-m17n. |
}; |
for (size_t i = 0; i < arraysize(kInputMethodPropertyKeysBlacklist); ++i) { |
- if (!std::strcmp(key, kInputMethodPropertyKeysBlacklist[i])) |
+ if (key == kInputMethodPropertyKeysBlacklist[i]) |
return true; |
} |
return false; |
} |
-// Returns true if |prop| has children. |
-bool PropertyHasChildren(IBusProperty* prop) { |
- return prop && ibus_property_get_sub_props(prop) && |
- ibus_prop_list_get(ibus_property_get_sub_props(prop), 0); |
-} |
- |
// This function is called by and FlattenProperty() and converts IBus |
// representation of a property, |ibus_prop|, to our own and push_back the |
// result to |out_prop_list|. This function returns true on success, and |
// returns false if sanity checks for |ibus_prop| fail. |
-bool ConvertProperty(IBusProperty* ibus_prop, |
+bool ConvertProperty(const ibus::IBusProperty& ibus_prop, |
InputMethodPropertyList* out_prop_list) { |
- DCHECK(ibus_prop); |
DCHECK(out_prop_list); |
- |
- const IBusPropType type = ibus_property_get_prop_type(ibus_prop); |
- const IBusPropState state = ibus_property_get_state(ibus_prop); |
- const IBusText* tooltip = ibus_property_get_tooltip(ibus_prop); |
- const IBusText* label = ibus_property_get_label(ibus_prop); |
- const gchar* key = ibus_property_get_key(ibus_prop); |
- DCHECK(key); |
+ DCHECK(ibus_prop.key().empty()); |
+ ibus::IBusProperty::IBusPropertyType type = ibus_prop.type(); |
// Sanity checks. |
- const bool has_sub_props = PropertyHasChildren(ibus_prop); |
- if (has_sub_props && (type != PROP_TYPE_MENU)) { |
+ const bool has_sub_props = !ibus_prop.sub_properties().empty(); |
+ if (has_sub_props && (type != ibus::IBusProperty::IBUS_PROPERTY_TYPE_MENU)) { |
DVLOG(1) << "The property has sub properties, " |
<< "but the type of the property is not PROP_TYPE_MENU"; |
return false; |
} |
- if ((!has_sub_props) && (type == PROP_TYPE_MENU)) { |
+ if ((!has_sub_props) && |
+ (type == ibus::IBusProperty::IBUS_PROPERTY_TYPE_MENU)) { |
// This is usually not an error. ibus-daemon sometimes sends empty props. |
DVLOG(1) << "Property list is empty"; |
return false; |
} |
- if (type == PROP_TYPE_SEPARATOR || type == PROP_TYPE_MENU) { |
+ if (type == ibus::IBusProperty::IBUS_PROPERTY_TYPE_SEPARATOR || |
+ type == ibus::IBusProperty::IBUS_PROPERTY_TYPE_MENU) { |
// This is not an error, but we don't push an item for these types. |
return true; |
} |
- const bool is_selection_item = (type == PROP_TYPE_RADIO); |
- |
- bool is_selection_item_checked = false; |
- if (state == PROP_STATE_INCONSISTENT) { |
- DVLOG(1) << "The property is in PROP_STATE_INCONSISTENT, " |
- << "which is not supported."; |
- } else if ((!is_selection_item) && (state == PROP_STATE_CHECKED)) { |
- DVLOG(1) << "PROP_STATE_CHECKED is meaningful only if the type is " |
- << "PROP_TYPE_RADIO."; |
- } else { |
- is_selection_item_checked = (state == PROP_STATE_CHECKED); |
- } |
- |
- if (!key) |
- DVLOG(1) << "key is NULL"; |
- if (tooltip && !tooltip->text) { |
- DVLOG(1) << "tooltip is NOT NULL, but tooltip->text IS NULL: key=" |
- << Or(key, ""); |
- } |
- if (label && !label->text) { |
- DVLOG(1) << "label is NOT NULL, but label->text IS NULL: key=" |
- << Or(key, ""); |
- } |
- |
// This label will be localized later. |
// See chrome/browser/chromeos/input_method/input_method_util.cc. |
- std::string label_to_use = (tooltip && tooltip->text) ? tooltip->text : ""; |
- if (label_to_use.empty()) { |
- // Usually tooltips are more descriptive than labels. |
- label_to_use = (label && label->text) ? label->text : ""; |
- } |
- if (label_to_use.empty()) { |
- DVLOG(1) << "The tooltip and label are both empty. Use " << key; |
- label_to_use = Or(key, ""); |
- } |
- |
- out_prop_list->push_back(InputMethodProperty(key, |
- label_to_use, |
- is_selection_item, |
- is_selection_item_checked)); |
+ std::string label_to_use; |
+ if (!ibus_prop.tooltip().empty()) |
+ label_to_use = ibus_prop.tooltip(); |
+ else if (!ibus_prop.label().empty()) |
+ label_to_use = ibus_prop.label(); |
+ else |
+ label_to_use = ibus_prop.key(); |
+ |
+ out_prop_list->push_back(InputMethodProperty( |
+ ibus_prop.key(), |
+ label_to_use, |
+ (type == ibus::IBusProperty::IBUS_PROPERTY_TYPE_RADIO), |
+ ibus_prop.checked())); |
return true; |
} |
// Converts |ibus_prop| to |out_prop_list|. Please note that |ibus_prop| |
// may or may not have children. See the comment for FlattenPropertyList |
// for details. Returns true if no error is found. |
-bool FlattenProperty(IBusProperty* ibus_prop, |
+bool FlattenProperty(const ibus::IBusProperty& ibus_prop, |
InputMethodPropertyList* out_prop_list) { |
- DCHECK(ibus_prop); |
DCHECK(out_prop_list); |
- const gchar* key = ibus_property_get_key(ibus_prop); |
- |
// Filter out unnecessary properties. |
- if (PropertyKeyIsBlacklisted(key)) |
+ if (PropertyKeyIsBlacklisted(ibus_prop.key())) |
return true; |
// Convert |prop| to InputMethodProperty and push it to |out_prop_list|. |
@@ -191,13 +142,10 @@ bool FlattenProperty(IBusProperty* ibus_prop, |
// Process childrens iteratively (if any). Push all sub properties to the |
// stack. |
- if (PropertyHasChildren(ibus_prop)) { |
- for (int i = 0;; ++i) { |
- IBusProperty* sub_prop = |
- ibus_prop_list_get(ibus_property_get_sub_props(ibus_prop), i); |
- if (!sub_prop) |
- break; |
- if (!FlattenProperty(sub_prop, out_prop_list)) |
+ if (!ibus_prop.sub_properties().empty()) { |
+ const ibus::IBusPropertyList& sub_props = ibus_prop.sub_properties(); |
+ for (size_t i = 0; i < sub_props.size(); ++i) { |
+ if (!FlattenProperty(*sub_props[i], out_prop_list)) |
return false; |
} |
} |
@@ -227,117 +175,15 @@ bool FlattenProperty(IBusProperty* ibus_prop, |
// Item-1, Item-2, Item-3-1, Item-3-2, Item-3-3, Item-4 |
// (Note: SubMenuRoot does not appear in the output.) |
// ====================================================================== |
-bool FlattenPropertyList(IBusPropList* ibus_prop_list, |
+bool FlattenPropertyList(const ibus::IBusPropertyList& ibus_prop_list, |
InputMethodPropertyList* out_prop_list) { |
- DCHECK(ibus_prop_list); |
DCHECK(out_prop_list); |
- IBusProperty* fake_root_prop = ibus_property_new("Dummy.Key", |
- PROP_TYPE_MENU, |
- NULL, /* label */ |
- "", /* icon */ |
- NULL, /* tooltip */ |
- FALSE, /* sensitive */ |
- FALSE, /* visible */ |
- PROP_STATE_UNCHECKED, |
- ibus_prop_list); |
- g_return_val_if_fail(fake_root_prop, false); |
- // Increase the ref count so it won't get deleted when |fake_root_prop| |
- // is deleted. |
- g_object_ref(ibus_prop_list); |
- const bool result = FlattenProperty(fake_root_prop, out_prop_list); |
- g_object_unref(fake_root_prop); |
- |
- return result; |
-} |
- |
-// Debug print function. |
-const char* PropTypeToString(int prop_type) { |
- switch (static_cast<IBusPropType>(prop_type)) { |
- case PROP_TYPE_NORMAL: |
- return "NORMAL"; |
- case PROP_TYPE_TOGGLE: |
- return "TOGGLE"; |
- case PROP_TYPE_RADIO: |
- return "RADIO"; |
- case PROP_TYPE_MENU: |
- return "MENU"; |
- case PROP_TYPE_SEPARATOR: |
- return "SEPARATOR"; |
- } |
- return "UNKNOWN"; |
-} |
- |
-// Debug print function. |
-const char* PropStateToString(int prop_state) { |
- switch (static_cast<IBusPropState>(prop_state)) { |
- case PROP_STATE_UNCHECKED: |
- return "UNCHECKED"; |
- case PROP_STATE_CHECKED: |
- return "CHECKED"; |
- case PROP_STATE_INCONSISTENT: |
- return "INCONSISTENT"; |
- } |
- return "UNKNOWN"; |
-} |
- |
-// Debug print function. |
-std::string Spacer(int n) { |
- return std::string(n, ' '); |
-} |
- |
-std::string PrintPropList(IBusPropList *prop_list, int tree_level); |
- |
-// Debug print function. |
-std::string PrintProp(IBusProperty *prop, int tree_level) { |
- if (!prop) |
- return ""; |
- |
- const IBusPropType type = ibus_property_get_prop_type(prop); |
- const IBusPropState state = ibus_property_get_state(prop); |
- const IBusText* tooltip = ibus_property_get_tooltip(prop); |
- const IBusText* label = ibus_property_get_label(prop); |
- const gchar* key = ibus_property_get_key(prop); |
- |
- std::stringstream stream; |
- stream << Spacer(tree_level) << "=========================" << std::endl; |
- stream << Spacer(tree_level) << "key: " << Or(key, "<none>") |
- << std::endl; |
- stream << Spacer(tree_level) << "label: " |
- << ((label && label->text) ? label->text : "<none>") |
- << std::endl; |
- stream << Spacer(tree_level) << "tooptip: " |
- << ((tooltip && tooltip->text) |
- ? tooltip->text : "<none>") << std::endl; |
- stream << Spacer(tree_level) << "sensitive: " |
- << (ibus_property_get_sensitive(prop) ? "YES" : "NO") << std::endl; |
- stream << Spacer(tree_level) << "visible: " |
- << (ibus_property_get_visible(prop) ? "YES" : "NO") << std::endl; |
- stream << Spacer(tree_level) << "type: " << PropTypeToString(type) |
- << std::endl; |
- stream << Spacer(tree_level) << "state: " << PropStateToString(state) |
- << std::endl; |
- stream << Spacer(tree_level) << "sub_props: " |
- << (PropertyHasChildren(prop) ? "" : "<none>") << std::endl; |
- stream << PrintPropList(ibus_property_get_sub_props(prop), tree_level + 1); |
- stream << Spacer(tree_level) << "=========================" << std::endl; |
- |
- return stream.str(); |
-} |
- |
-// Debug print function. |
-std::string PrintPropList(IBusPropList *prop_list, int tree_level) { |
- if (!prop_list) |
- return ""; |
- |
- std::stringstream stream; |
- for (int i = 0;; ++i) { |
- IBusProperty* prop = ibus_prop_list_get(prop_list, i); |
- if (!prop) |
- break; |
- stream << PrintProp(prop, tree_level); |
+ bool result = true; |
+ for (size_t i = 0; i < ibus_prop_list.size(); ++i) { |
+ result &= FlattenProperty(*ibus_prop_list[i], out_prop_list); |
} |
- return stream.str(); |
+ return result; |
} |
class IBusAddressWatcher { |
@@ -356,8 +202,6 @@ class IBusAddressWatcher { |
DCHECK(!ibus_address.empty()); |
} |
- virtual ~IBusAddressFileWatcherDelegate() {} |
- |
virtual void OnFilePathChanged(const FilePath& file_path) OVERRIDE { |
if (!watcher_->IsWatching()) |
return; |
@@ -372,6 +216,9 @@ class IBusAddressWatcher { |
watcher_->StopSoon(); |
} |
+ protected: |
+ virtual ~IBusAddressFileWatcherDelegate() {} |
+ |
private: |
// The ibus-daemon address. |
const std::string ibus_address_; |
@@ -436,45 +283,16 @@ class IBusAddressWatcher { |
} // namespace |
IBusControllerImpl::IBusControllerImpl() |
- : ibus_(NULL), |
- process_handle_(base::kNullProcessHandle), |
+ : process_handle_(base::kNullProcessHandle), |
ibus_daemon_status_(IBUS_DAEMON_STOP), |
input_method_(NULL), |
ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
} |
IBusControllerImpl::~IBusControllerImpl() { |
- // Disconnect signals so the handler functions will not be called with |
- // |this| which is already freed. |
- if (ibus_) { |
- g_signal_handlers_disconnect_by_func( |
- ibus_, |
- reinterpret_cast<gpointer>(G_CALLBACK(BusConnectedThunk)), |
- this); |
- // Disconnect signals for the panel service as well. |
- // When Chrome is shutting down, g_object_get_data fails and returns NULL. |
- // TODO(nona): Investigate the reason of failure(crosbug.com/129142). |
- void* attached_data = g_object_get_data(G_OBJECT(ibus_), kPanelObjectKey); |
- if (!attached_data) |
- return; |
- if (!G_TYPE_CHECK_INSTANCE_TYPE(attached_data, IBUS_TYPE_PANEL_SERVICE)) |
- return; |
- IBusPanelService* ibus_panel_service = IBUS_PANEL_SERVICE(attached_data); |
- if (ibus_panel_service) { |
- g_signal_handlers_disconnect_by_func( |
- ibus_panel_service, |
- reinterpret_cast<gpointer>(G_CALLBACK(RegisterPropertiesThunk)), |
- this); |
- g_signal_handlers_disconnect_by_func( |
- ibus_panel_service, |
- reinterpret_cast<gpointer>(G_CALLBACK(UpdatePropertyThunk)), |
- this); |
- } |
- } |
} |
bool IBusControllerImpl::Start() { |
- MaybeInitializeIBusBus(); |
if (IBusConnectionsAreAlive()) |
return true; |
if (ibus_daemon_status_ == IBUS_DAEMON_STOP || |
@@ -546,8 +364,10 @@ bool IBusControllerImpl::ChangeInputMethod(const std::string& id) { |
// 4. Switch back to "mozc". ChangeInputMethod("mozc") is called, but it's |
// basically NOP since ibus-daemon's current IME is already "mozc". |
// IME properties are not sent to Chrome for the same reason. |
- if (id != current_input_method_id_) |
- RegisterProperties(NULL, NULL); |
+ if (id != current_input_method_id_) { |
+ const ibus::IBusPropertyList empty_list; |
+ RegisterProperties(empty_list); |
+ } |
current_input_method_id_ = id; |
@@ -592,38 +412,7 @@ bool IBusControllerImpl::ActivateInputMethodProperty(const std::string& key) { |
} |
bool IBusControllerImpl::IBusConnectionsAreAlive() { |
- return (ibus_daemon_status_ == IBUS_DAEMON_RUNNING) && |
- ibus_ && ibus_bus_is_connected(ibus_); |
-} |
- |
-void IBusControllerImpl::MaybeRestoreConnections() { |
- if (IBusConnectionsAreAlive()) |
- return; |
- if (IBusConnectionsAreAlive()) { |
- DVLOG(1) << "ibus-daemon and ibus-memconf processes are ready."; |
- ConnectPanelServiceSignals(); |
- if (!current_input_method_id_.empty()) |
- SendChangeInputMethodRequest(current_input_method_id_); |
- } |
-} |
- |
-void IBusControllerImpl::MaybeInitializeIBusBus() { |
- if (ibus_) |
- return; |
- |
- ibus_init(); |
- // Establish IBus connection between ibus-daemon to change the current input |
- // method engine, properties, and so on. |
- ibus_ = ibus_bus_new(); |
- DCHECK(ibus_); |
- |
- // Register callback functions for IBusBus signals. |
- ConnectBusSignals(); |
- |
- if (ibus_bus_is_connected(ibus_)) { |
- DVLOG(1) << "IBus connection is ready: ibus-daemon is already running?"; |
- BusConnected(ibus_); |
- } |
+ return ibus_daemon_status_ == IBUS_DAEMON_RUNNING; |
} |
void IBusControllerImpl::SendChangeInputMethodRequest(const std::string& id) { |
@@ -671,74 +460,16 @@ bool IBusControllerImpl::SetInputMethodConfigInternal( |
} |
} |
-void IBusControllerImpl::ConnectBusSignals() { |
- if (!ibus_) |
- return; |
- |
- // We use g_signal_connect_after here since the callback should be called |
- // *after* the IBusBusDisconnectedCallback in chromeos_input_method_ui.cc |
- // is called. chromeos_input_method_ui.cc attaches the panel service object |
- // to |ibus_|, and the callback in this file use the attached object. |
- g_signal_connect_after(ibus_, |
- "connected", |
- G_CALLBACK(BusConnectedThunk), |
- this); |
-} |
- |
-void IBusControllerImpl::ConnectPanelServiceSignals() { |
- if (!ibus_) |
- return; |
- |
- IBusPanelService* ibus_panel_service = IBUS_PANEL_SERVICE( |
- g_object_get_data(G_OBJECT(ibus_), kPanelObjectKey)); |
- if (!ibus_panel_service) { |
- DVLOG(1) << "IBusPanelService is NOT available."; |
- return; |
- } |
- // We don't _ref() or _weak_ref() the panel service object, since we're not |
- // interested in the life time of the object. |
- g_signal_connect(ibus_panel_service, |
- "register-properties", |
- G_CALLBACK(RegisterPropertiesThunk), |
- this); |
- g_signal_connect(ibus_panel_service, |
- "update-property", |
- G_CALLBACK(UpdatePropertyThunk), |
- this); |
-} |
- |
-void IBusControllerImpl::BusConnected(IBusBus* bus) { |
- DVLOG(1) << "IBus connection is established."; |
- MaybeRestoreConnections(); |
-} |
- |
-void IBusControllerImpl::RegisterProperties(IBusPanelService* panel, |
- IBusPropList* ibus_prop_list) { |
+void IBusControllerImpl::RegisterProperties( |
+ const ibus::IBusPropertyList& ibus_prop_list) { |
// Note: |panel| can be NULL. See ChangeInputMethod(). |
- DVLOG(1) << "RegisterProperties" << (ibus_prop_list ? "" : " (clear)"); |
- |
current_property_list_.clear(); |
- if (ibus_prop_list) { |
- // You can call |
- // DVLOG(1) << "\n" << PrintPropList(ibus_prop_list, 0); |
- // here to dump |ibus_prop_list|. |
- if (!FlattenPropertyList(ibus_prop_list, ¤t_property_list_)) { |
- // Clear properties on errors. |
- current_property_list_.clear(); |
- } |
- } |
+ if (!FlattenPropertyList(ibus_prop_list, ¤t_property_list_)) |
+ current_property_list_.clear(); // Clear properties on errors. |
FOR_EACH_OBSERVER(Observer, observers_, PropertyChanged()); |
} |
-void IBusControllerImpl::UpdateProperty(IBusPanelService* panel, |
- IBusProperty* ibus_prop) { |
- DVLOG(1) << "UpdateProperty"; |
- DCHECK(ibus_prop); |
- |
- // You can call |
- // DVLOG(1) << "\n" << PrintProp(ibus_prop, 0); |
- // here to dump |ibus_prop|. |
- |
+void IBusControllerImpl::UpdateProperty(const ibus::IBusProperty& ibus_prop) { |
InputMethodPropertyList prop_list; // our representation. |
if (!FlattenProperty(ibus_prop, &prop_list)) { |
// Don't update the UI on errors. |
@@ -861,7 +592,10 @@ void IBusControllerImpl::IBusDaemonInitializationDone( |
DCHECK(input_method_ibus); |
input_method_ibus->OnConnected(); |
- // Restores previous input method at the beggining of connection. |
+ DBusThreadManager::Get()->GetIBusPanelService()->SetUpPropertyHandler( |
+ controller); |
+ |
+ // Restore previous input method at the beggining of connection. |
if (!controller->current_input_method_id_.empty()) { |
controller->SendChangeInputMethodRequest( |
controller->current_input_method_id_); |
@@ -912,7 +646,6 @@ void IBusControllerImpl::OnIBusDaemonExit(GPid pid, |
LOG(ERROR) << "The ibus-daemon crashed. Re-launching..."; |
controller->StartIBusDaemon(); |
} |
-#endif // defined(HAVE_IBUS) |
// static |
bool IBusControllerImpl::FindAndUpdatePropertyForTesting( |