Chromium Code Reviews| Index: chromeos/dbus/ibus/ibus_config_client.cc |
| diff --git a/chromeos/dbus/ibus/ibus_config_client.cc b/chromeos/dbus/ibus/ibus_config_client.cc |
| index 659cde41bae779420cb748a81ec0c4286f16c0e9..2c67c368440c1e1db5cef39297f4e80cb68eae45 100644 |
| --- a/chromeos/dbus/ibus/ibus_config_client.cc |
| +++ b/chromeos/dbus/ibus/ibus_config_client.cc |
| @@ -4,6 +4,8 @@ |
| #include "chromeos/dbus/ibus/ibus_config_client.h" |
| +#include <vector> |
| + |
| #include "base/bind.h" |
| #include "base/callback.h" |
| #include "chromeos/dbus/ibus/ibus_constants.h" |
| @@ -17,23 +19,69 @@ namespace chromeos { |
| namespace { |
| +// Called when the |signal| is connected. |
| +void OnSignalConnected(const std::string& interface, |
| + const std::string& signal, |
| + bool succeeded) { |
| + DLOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " |
|
satorux1
2012/11/30 05:52:58
LOG_IF. no need to make it a DLOG?
Seigo Nonaka
2012/11/30 07:36:34
Done.
|
| + << signal << " failed."; |
| +} |
| + |
| +// Called when the GetNameOwner method call is failed. |
| +void OnGetNameOwnerFail(dbus::ErrorResponse* response) { |
| + // Do nothing, because method call sometimes fails due to bootstrap timing of |
| + // ibus-memconf. |
| +} |
| + |
| // The IBusConfigClient implementation. |
| class IBusConfigClientImpl : public IBusConfigClient { |
| public: |
| explicit IBusConfigClientImpl(dbus::Bus* bus) |
| - : proxy_(bus->GetObjectProxy(ibus::kServiceName, |
| - dbus::ObjectPath( |
| - ibus::config::kServicePath))), |
| + : proxy_(NULL), |
| + bus_(bus), |
| weak_ptr_factory_(this) { |
| } |
| virtual ~IBusConfigClientImpl() {} |
| // IBusConfigClient override. |
| + virtual void InitializeAsync(const OnIBusConfigReady& on_ready) OVERRIDE { |
| + // We should check that the ibus-config daemon actually works first, so we |
| + // can't initialize synchronously. |
| + dbus::ObjectProxy* dbus_proxy = bus_->GetObjectProxy( |
| + ibus::kServiceName, |
| + dbus::ObjectPath(ibus::kDBusObjectPath)); |
| + |
| + // Watch NameOwnerChanged signal which is fired when the ibus-config daemon |
| + // request its name ownership. |
| + dbus_proxy->ConnectToSignal( |
| + ibus::kDBusInterface, |
| + ibus::kNameOwnerChangedSignal, |
| + base::Bind(&IBusConfigClientImpl::OnNameOwnerChanged, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + on_ready), |
| + base::Bind(&OnSignalConnected)); |
| + |
| + dbus::MethodCall method_call(ibus::kDBusInterface, |
| + ibus::kGetNameOwnerMethod); |
| + dbus::MessageWriter writer(&method_call); |
| + writer.AppendString(ibus::config::kServiceName); |
| + dbus_proxy->CallMethodWithErrorCallback( |
| + &method_call, |
| + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| + base::Bind(&IBusConfigClientImpl::OnGetNameOwner, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + on_ready), |
| + base::Bind(&OnGetNameOwnerFail)); |
| + } |
| + |
| + // IBusConfigClient override. |
| virtual void SetStringValue(const std::string& section, |
| const std::string& key, |
| const std::string& value, |
| const ErrorCallback& error_callback) OVERRIDE { |
| + if (!proxy_) |
| + return; |
| DCHECK(!error_callback.is_null()); |
| dbus::MethodCall method_call(ibus::config::kServiceInterface, |
| ibus::config::kSetValueMethod); |
| @@ -52,6 +100,8 @@ class IBusConfigClientImpl : public IBusConfigClient { |
| const std::string& key, |
| int value, |
| const ErrorCallback& error_callback) OVERRIDE { |
| + if (!proxy_) |
| + return; |
| DCHECK(!error_callback.is_null()); |
| dbus::MethodCall method_call(ibus::config::kServiceInterface, |
| ibus::config::kSetValueMethod); |
| @@ -70,6 +120,8 @@ class IBusConfigClientImpl : public IBusConfigClient { |
| const std::string& key, |
| bool value, |
| const ErrorCallback& error_callback) OVERRIDE { |
| + if (!proxy_) |
| + return; |
| DCHECK(!error_callback.is_null()); |
| dbus::MethodCall method_call(ibus::config::kServiceInterface, |
| ibus::config::kSetValueMethod); |
| @@ -89,6 +141,8 @@ class IBusConfigClientImpl : public IBusConfigClient { |
| const std::string& key, |
| const std::vector<std::string>& value, |
| const ErrorCallback& error_callback) OVERRIDE { |
| + if (!proxy_) |
| + return; |
| DCHECK(!error_callback.is_null()); |
| dbus::MethodCall method_call(ibus::config::kServiceInterface, |
| ibus::config::kSetValueMethod); |
| @@ -111,6 +165,8 @@ class IBusConfigClientImpl : public IBusConfigClient { |
| private: |
| void CallWithDefaultCallback(dbus::MethodCall* method_call, |
| const ErrorCallback& error_callback) { |
| + if (!proxy_) |
| + return; |
| proxy_->CallMethodWithErrorCallback( |
| method_call, |
| dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| @@ -136,7 +192,72 @@ class IBusConfigClientImpl : public IBusConfigClient { |
| error_callback.Run(); |
| } |
| + void OnNameOwnerChanged(const OnIBusConfigReady& on_ready, |
| + dbus::Signal* signal) { |
| + DCHECK(signal); |
| + std::string name; |
| + std::string old_owner; |
| + std::string new_owner; |
| + |
| + dbus::MessageReader reader(signal); |
| + if (!reader.PopString(&name) || |
| + !reader.PopString(&old_owner) || |
| + !reader.PopString(&new_owner)) { |
| + DLOG(ERROR) << "Invalid response of NameOwnerChanged." |
| + << signal->ToString(); |
| + return; |
| + } |
| + |
| + if (name != ibus::config::kServiceName) |
| + return; // Not a signal for ibus-config. |
| + |
| + if (!old_owner.empty() || new_owner.empty()) { |
| + DVLOG(1) << "Unexpected name owner change: name=" << name |
| + << ", old_owner=" << old_owner << ", new_owner=" << new_owner; |
| + proxy_ = NULL; |
| + return; |
| + } |
| + |
| + if (proxy_) |
| + return; // Already initialized. |
| + |
| + proxy_ = bus_->GetObjectProxy(ibus::config::kServiceName, |
| + dbus::ObjectPath( |
| + ibus::config::kServicePath)); |
| + if (!on_ready.is_null()) |
| + on_ready.Run(); |
| + } |
| + |
| + // Handles response of GetNameOwner. |
| + void OnGetNameOwner(const OnIBusConfigReady& on_ready, |
| + dbus::Response* response) { |
| + if (!response) { |
| + DLOG(ERROR) << "Response is NULL."; |
|
satorux1
2012/11/30 05:52:58
LOG(ERROR) ? For ERRORs, I think we should use LOG
Seigo Nonaka
2012/11/30 07:36:34
Done.
|
| + return; |
| + } |
| + std::string owner; |
| + dbus::MessageReader reader(response); |
| + |
| + if (!reader.PopString(&owner)) { |
| + DLOG(ERROR) << "Invalid response of GetNameOwner." |
|
satorux1
2012/11/30 05:52:58
ditto
Seigo Nonaka
2012/11/30 07:36:34
Done.
|
| + << response->ToString(); |
| + return; |
| + } |
| + |
| + // If the owner is empty, ibus-config daemon is not ready. So will |
| + // initialize object proxy on NameOwnerChanged signal. |
| + if (owner.empty()) |
| + return; |
| + |
| + proxy_ = bus_->GetObjectProxy(ibus::config::kServiceName, |
| + dbus::ObjectPath( |
| + ibus::config::kServicePath)); |
| + if (!on_ready.is_null()) |
| + on_ready.Run(); |
| + } |
| + |
| dbus::ObjectProxy* proxy_; |
| + dbus::Bus* bus_; |
| base::WeakPtrFactory<IBusConfigClientImpl> weak_ptr_factory_; |
| DISALLOW_COPY_AND_ASSIGN(IBusConfigClientImpl); |
| @@ -147,6 +268,7 @@ class IBusConfigClientStubImpl : public IBusConfigClient { |
| public: |
| IBusConfigClientStubImpl() {} |
| virtual ~IBusConfigClientStubImpl() {} |
| + virtual void InitializeAsync(const OnIBusConfigReady& on_ready) OVERRIDE {} |
| virtual void SetStringValue(const std::string& section, |
| const std::string& key, |
| const std::string& value, |