Commit 39b0cc3c authored by nona@chromium.org's avatar nona@chromium.org

Makes IBusConfigClient initialize asynchronous.

IBusConfigClient can not always initialize synchronously, because there is a case that the ibus-config daemon is not running.

BUG=158265
TEST=ran chromeos_unittests

Review URL: https://chromiumcodereview.appspot.com/11413165

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@170432 0039d316-1c4b-4281-b951-d872f2087c98
parent 9154d10e
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "chromeos/dbus/ibus/ibus_config_client.h" #include "chromeos/dbus/ibus/ibus_config_client.h"
#include <vector>
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "chromeos/dbus/ibus/ibus_constants.h" #include "chromeos/dbus/ibus/ibus_constants.h"
...@@ -17,23 +19,69 @@ namespace chromeos { ...@@ -17,23 +19,69 @@ namespace chromeos {
namespace { namespace {
// Called when the |signal| is connected.
void OnSignalConnected(const std::string& interface,
const std::string& signal,
bool succeeded) {
LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " "
<< 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. // The IBusConfigClient implementation.
class IBusConfigClientImpl : public IBusConfigClient { class IBusConfigClientImpl : public IBusConfigClient {
public: public:
explicit IBusConfigClientImpl(dbus::Bus* bus) explicit IBusConfigClientImpl(dbus::Bus* bus)
: proxy_(bus->GetObjectProxy(ibus::kServiceName, : proxy_(NULL),
dbus::ObjectPath( bus_(bus),
ibus::config::kServicePath))),
weak_ptr_factory_(this) { weak_ptr_factory_(this) {
} }
virtual ~IBusConfigClientImpl() {} 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. // IBusConfigClient override.
virtual void SetStringValue(const std::string& section, virtual void SetStringValue(const std::string& section,
const std::string& key, const std::string& key,
const std::string& value, const std::string& value,
const ErrorCallback& error_callback) OVERRIDE { const ErrorCallback& error_callback) OVERRIDE {
if (!proxy_)
return;
DCHECK(!error_callback.is_null()); DCHECK(!error_callback.is_null());
dbus::MethodCall method_call(ibus::config::kServiceInterface, dbus::MethodCall method_call(ibus::config::kServiceInterface,
ibus::config::kSetValueMethod); ibus::config::kSetValueMethod);
...@@ -52,6 +100,8 @@ class IBusConfigClientImpl : public IBusConfigClient { ...@@ -52,6 +100,8 @@ class IBusConfigClientImpl : public IBusConfigClient {
const std::string& key, const std::string& key,
int value, int value,
const ErrorCallback& error_callback) OVERRIDE { const ErrorCallback& error_callback) OVERRIDE {
if (!proxy_)
return;
DCHECK(!error_callback.is_null()); DCHECK(!error_callback.is_null());
dbus::MethodCall method_call(ibus::config::kServiceInterface, dbus::MethodCall method_call(ibus::config::kServiceInterface,
ibus::config::kSetValueMethod); ibus::config::kSetValueMethod);
...@@ -70,6 +120,8 @@ class IBusConfigClientImpl : public IBusConfigClient { ...@@ -70,6 +120,8 @@ class IBusConfigClientImpl : public IBusConfigClient {
const std::string& key, const std::string& key,
bool value, bool value,
const ErrorCallback& error_callback) OVERRIDE { const ErrorCallback& error_callback) OVERRIDE {
if (!proxy_)
return;
DCHECK(!error_callback.is_null()); DCHECK(!error_callback.is_null());
dbus::MethodCall method_call(ibus::config::kServiceInterface, dbus::MethodCall method_call(ibus::config::kServiceInterface,
ibus::config::kSetValueMethod); ibus::config::kSetValueMethod);
...@@ -89,6 +141,8 @@ class IBusConfigClientImpl : public IBusConfigClient { ...@@ -89,6 +141,8 @@ class IBusConfigClientImpl : public IBusConfigClient {
const std::string& key, const std::string& key,
const std::vector<std::string>& value, const std::vector<std::string>& value,
const ErrorCallback& error_callback) OVERRIDE { const ErrorCallback& error_callback) OVERRIDE {
if (!proxy_)
return;
DCHECK(!error_callback.is_null()); DCHECK(!error_callback.is_null());
dbus::MethodCall method_call(ibus::config::kServiceInterface, dbus::MethodCall method_call(ibus::config::kServiceInterface,
ibus::config::kSetValueMethod); ibus::config::kSetValueMethod);
...@@ -111,6 +165,8 @@ class IBusConfigClientImpl : public IBusConfigClient { ...@@ -111,6 +165,8 @@ class IBusConfigClientImpl : public IBusConfigClient {
private: private:
void CallWithDefaultCallback(dbus::MethodCall* method_call, void CallWithDefaultCallback(dbus::MethodCall* method_call,
const ErrorCallback& error_callback) { const ErrorCallback& error_callback) {
if (!proxy_)
return;
proxy_->CallMethodWithErrorCallback( proxy_->CallMethodWithErrorCallback(
method_call, method_call,
dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
...@@ -136,7 +192,72 @@ class IBusConfigClientImpl : public IBusConfigClient { ...@@ -136,7 +192,72 @@ class IBusConfigClientImpl : public IBusConfigClient {
error_callback.Run(); 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) {
LOG(ERROR) << "Response is NULL.";
return;
}
std::string owner;
dbus::MessageReader reader(response);
if (!reader.PopString(&owner)) {
LOG(ERROR) << "Invalid response of GetNameOwner."
<< 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::ObjectProxy* proxy_;
dbus::Bus* bus_;
base::WeakPtrFactory<IBusConfigClientImpl> weak_ptr_factory_; base::WeakPtrFactory<IBusConfigClientImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(IBusConfigClientImpl); DISALLOW_COPY_AND_ASSIGN(IBusConfigClientImpl);
...@@ -147,6 +268,7 @@ class IBusConfigClientStubImpl : public IBusConfigClient { ...@@ -147,6 +268,7 @@ class IBusConfigClientStubImpl : public IBusConfigClient {
public: public:
IBusConfigClientStubImpl() {} IBusConfigClientStubImpl() {}
virtual ~IBusConfigClientStubImpl() {} virtual ~IBusConfigClientStubImpl() {}
virtual void InitializeAsync(const OnIBusConfigReady& on_ready) OVERRIDE {}
virtual void SetStringValue(const std::string& section, virtual void SetStringValue(const std::string& section,
const std::string& key, const std::string& key,
const std::string& value, const std::string& value,
......
...@@ -30,8 +30,13 @@ class IBusInputContextClient; ...@@ -30,8 +30,13 @@ class IBusInputContextClient;
class CHROMEOS_EXPORT IBusConfigClient { class CHROMEOS_EXPORT IBusConfigClient {
public: public:
typedef base::Callback<void()> ErrorCallback; typedef base::Callback<void()> ErrorCallback;
typedef base::Callback<void()> OnIBusConfigReady;
virtual ~IBusConfigClient(); virtual ~IBusConfigClient();
// Initializes IBusConfig asynchronously. |on_ready| will be called if it is
// ready.
virtual void InitializeAsync(const OnIBusConfigReady& on_ready) = 0;
// Requests the IBusConfig to set a string value. // Requests the IBusConfig to set a string value.
virtual void SetStringValue(const std::string& section, virtual void SetStringValue(const std::string& section,
const std::string& key, const std::string& key,
...@@ -72,4 +77,4 @@ class CHROMEOS_EXPORT IBusConfigClient { ...@@ -72,4 +77,4 @@ class CHROMEOS_EXPORT IBusConfigClient {
} // namespace chromeos } // namespace chromeos
#endif // CHROMEOS_DBUS_IBUS_IBUS_CLIENT_H_ #endif // CHROMEOS_DBUS_IBUS_IBUS_CONFIG_CLIENT_H_
...@@ -11,6 +11,12 @@ namespace ibus { ...@@ -11,6 +11,12 @@ namespace ibus {
const char kServiceName[] = "org.freedesktop.IBus"; const char kServiceName[] = "org.freedesktop.IBus";
const char kDBusServiceName[] = "org.freedesktop.DBus";
const char kDBusObjectPath[] = "/org/freedesktop/DBus";
const char kDBusInterface[] = "org.freedesktop.DBus";
const char kGetNameOwnerMethod[] = "GetNameOwner";
const char kNameOwnerChangedSignal[] = "NameOwnerChanged";
namespace bus { namespace bus {
const char kServicePath[] = "/org/freedesktop/IBus"; const char kServicePath[] = "/org/freedesktop/IBus";
const char kServiceInterface[] = "org.freedesktop.IBus"; const char kServiceInterface[] = "org.freedesktop.IBus";
...@@ -69,6 +75,7 @@ const char kCommitTextSignal[] = "CommitText"; ...@@ -69,6 +75,7 @@ const char kCommitTextSignal[] = "CommitText";
} // namespace engine } // namespace engine
namespace panel { namespace panel {
const char kServiceName[] = "org.freedesktop.IBus.Panel";
const char kServicePath[] = "/org/freedesktop/IBus/Panel"; const char kServicePath[] = "/org/freedesktop/IBus/Panel";
const char kServiceInterface[] = "org.freedesktop.IBus.Panel"; const char kServiceInterface[] = "org.freedesktop.IBus.Panel";
const char kUpdateLookupTableMethod[] = "UpdateLookupTable"; const char kUpdateLookupTableMethod[] = "UpdateLookupTable";
...@@ -102,6 +109,7 @@ enum IBusMouseButton { ...@@ -102,6 +109,7 @@ enum IBusMouseButton {
}; };
namespace config { namespace config {
const char kServiceName[] = "org.freedesktop.IBus.Config";
const char kServicePath[] = "/org/freedesktop/IBus/Config"; const char kServicePath[] = "/org/freedesktop/IBus/Config";
const char kServiceInterface[] = "org.freedesktop.IBus.Config"; const char kServiceInterface[] = "org.freedesktop.IBus.Config";
const char kSetValueMethod[] = "SetValue"; const char kSetValueMethod[] = "SetValue";
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "chromeos/dbus/ibus/mock_ibus_config_client.h" #include "chromeos/dbus/ibus/mock_ibus_config_client.h"
#include <vector>
namespace chromeos { namespace chromeos {
MockIBusConfigClient::MockIBusConfigClient() { MockIBusConfigClient::MockIBusConfigClient() {
...@@ -11,6 +13,9 @@ MockIBusConfigClient::MockIBusConfigClient() { ...@@ -11,6 +13,9 @@ MockIBusConfigClient::MockIBusConfigClient() {
MockIBusConfigClient::~MockIBusConfigClient() {} MockIBusConfigClient::~MockIBusConfigClient() {}
void MockIBusConfigClient::InitializeAsync(const OnIBusConfigReady& onready) {
}
void MockIBusConfigClient::SetStringValue(const std::string& key, void MockIBusConfigClient::SetStringValue(const std::string& key,
const std::string& section, const std::string& section,
const std::string& value, const std::string& value,
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define CHROMEOS_DBUS_IBUS_MOCK_IBUS_CONFIG_CLIENT_H_ #define CHROMEOS_DBUS_IBUS_MOCK_IBUS_CONFIG_CLIENT_H_
#include <string> #include <string>
#include <vector>
#include "chromeos/dbus/ibus/ibus_config_client.h" #include "chromeos/dbus/ibus/ibus_config_client.h"
...@@ -15,6 +16,7 @@ class MockIBusConfigClient : public IBusConfigClient { ...@@ -15,6 +16,7 @@ class MockIBusConfigClient : public IBusConfigClient {
public: public:
MockIBusConfigClient(); MockIBusConfigClient();
virtual ~MockIBusConfigClient(); virtual ~MockIBusConfigClient();
virtual void InitializeAsync(const OnIBusConfigReady& onready) OVERRIDE;
virtual void SetStringValue(const std::string& key, virtual void SetStringValue(const std::string& key,
const std::string& section, const std::string& section,
...@@ -42,4 +44,4 @@ class MockIBusConfigClient : public IBusConfigClient { ...@@ -42,4 +44,4 @@ class MockIBusConfigClient : public IBusConfigClient {
} // namespace chromeos } // namespace chromeos
#endif // CHROMEOS_DBUS_IBUS_MOCK_IBUS_CLIENT_H_ #endif // CHROMEOS_DBUS_IBUS_MOCK_IBUS_CONFIG_CLIENT_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment