Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / chromeos / dbus / ibus / ibus_config_client.cc
blob1e01d27fcf74270a1144c6f3fc5c433af4647482
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chromeos/dbus/ibus/ibus_config_client.h"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "chromeos/dbus/ibus/ibus_constants.h"
12 #include "chromeos/dbus/ibus/ibus_component.h"
13 #include "dbus/bus.h"
14 #include "dbus/message.h"
15 #include "dbus/object_path.h"
16 #include "dbus/object_proxy.h"
18 namespace chromeos {
20 namespace {
22 // Called when the |signal| is connected.
23 void OnSignalConnected(const std::string& interface,
24 const std::string& signal,
25 bool succeeded) {
26 LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " "
27 << signal << " failed.";
30 // Called when the GetNameOwner method call is failed.
31 void OnGetNameOwnerFail(dbus::ErrorResponse* response) {
32 // Do nothing, because method call sometimes fails due to bootstrap timing of
33 // ibus-memconf.
36 // The IBusConfigClient implementation.
37 class IBusConfigClientImpl : public IBusConfigClient {
38 public:
39 explicit IBusConfigClientImpl(dbus::Bus* bus)
40 : proxy_(NULL),
41 bus_(bus),
42 weak_ptr_factory_(this) {
45 virtual ~IBusConfigClientImpl() {}
47 // IBusConfigClient override.
48 virtual void InitializeAsync(const OnIBusConfigReady& on_ready) OVERRIDE {
49 // We should check that the ibus-config daemon actually works first, so we
50 // can't initialize synchronously.
51 // NameOwnerChanged signal will be emitted by ibus-daemon, but from the
52 // service name kDBusServiceName instead of kServiceName. The signal will be
53 // used to detect start of ibus-daemon.
54 dbus::ObjectProxy* dbus_proxy = bus_->GetObjectProxy(
55 ibus::kDBusServiceName,
56 dbus::ObjectPath(ibus::kDBusObjectPath));
58 // Watch NameOwnerChanged signal which is fired when the ibus-config daemon
59 // request its name ownership.
60 dbus_proxy->ConnectToSignal(
61 ibus::kDBusInterface,
62 ibus::kNameOwnerChangedSignal,
63 base::Bind(&IBusConfigClientImpl::OnNameOwnerChanged,
64 weak_ptr_factory_.GetWeakPtr(),
65 on_ready),
66 base::Bind(&OnSignalConnected));
68 dbus::MethodCall method_call(ibus::kDBusInterface,
69 ibus::kGetNameOwnerMethod);
70 dbus::MessageWriter writer(&method_call);
71 writer.AppendString(ibus::config::kServiceName);
72 dbus_proxy->CallMethodWithErrorCallback(
73 &method_call,
74 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
75 base::Bind(&IBusConfigClientImpl::OnGetNameOwner,
76 weak_ptr_factory_.GetWeakPtr(),
77 on_ready),
78 base::Bind(&OnGetNameOwnerFail));
81 // IBusConfigClient override.
82 virtual void SetStringValue(const std::string& section,
83 const std::string& key,
84 const std::string& value,
85 const ErrorCallback& error_callback) OVERRIDE {
86 if (!proxy_)
87 return;
88 DCHECK(!error_callback.is_null());
89 dbus::MethodCall method_call(ibus::config::kServiceInterface,
90 ibus::config::kSetValueMethod);
91 dbus::MessageWriter writer(&method_call);
92 writer.AppendString(section);
93 writer.AppendString(key);
94 dbus::MessageWriter variant_writer(NULL);
95 writer.OpenVariant("s", &variant_writer);
96 variant_writer.AppendString(value);
97 writer.CloseContainer(&variant_writer);
98 CallWithDefaultCallback(&method_call, error_callback);
101 // IBusConfigClient override.
102 virtual void SetIntValue(const std::string& section,
103 const std::string& key,
104 int value,
105 const ErrorCallback& error_callback) OVERRIDE {
106 if (!proxy_)
107 return;
108 DCHECK(!error_callback.is_null());
109 dbus::MethodCall method_call(ibus::config::kServiceInterface,
110 ibus::config::kSetValueMethod);
111 dbus::MessageWriter writer(&method_call);
112 writer.AppendString(section);
113 writer.AppendString(key);
114 dbus::MessageWriter variant_writer(NULL);
115 writer.OpenVariant("i", &variant_writer);
116 variant_writer.AppendInt32(value);
117 writer.CloseContainer(&variant_writer);
118 CallWithDefaultCallback(&method_call, error_callback);
121 // IBusConfigClient override.
122 virtual void SetBoolValue(const std::string& section,
123 const std::string& key,
124 bool value,
125 const ErrorCallback& error_callback) OVERRIDE {
126 if (!proxy_)
127 return;
128 DCHECK(!error_callback.is_null());
129 dbus::MethodCall method_call(ibus::config::kServiceInterface,
130 ibus::config::kSetValueMethod);
131 dbus::MessageWriter writer(&method_call);
132 writer.AppendString(section);
133 writer.AppendString(key);
134 dbus::MessageWriter variant_writer(NULL);
135 writer.OpenVariant("b", &variant_writer);
136 variant_writer.AppendBool(value);
137 writer.CloseContainer(&variant_writer);
138 CallWithDefaultCallback(&method_call, error_callback);
141 // IBusConfigClient override.
142 virtual void SetStringListValue(
143 const std::string& section,
144 const std::string& key,
145 const std::vector<std::string>& value,
146 const ErrorCallback& error_callback) OVERRIDE {
147 if (!proxy_)
148 return;
149 DCHECK(!error_callback.is_null());
150 dbus::MethodCall method_call(ibus::config::kServiceInterface,
151 ibus::config::kSetValueMethod);
152 dbus::MessageWriter writer(&method_call);
153 writer.AppendString(section);
154 writer.AppendString(key);
155 dbus::MessageWriter variant_writer(NULL);
156 dbus::MessageWriter array_writer(NULL);
158 writer.OpenVariant("as", &variant_writer);
159 variant_writer.OpenArray("s", &array_writer);
160 for (size_t i = 0; i < value.size(); ++i) {
161 array_writer.AppendString(value[i]);
163 variant_writer.CloseContainer(&array_writer);
164 writer.CloseContainer(&variant_writer);
165 CallWithDefaultCallback(&method_call, error_callback);
168 private:
169 void CallWithDefaultCallback(dbus::MethodCall* method_call,
170 const ErrorCallback& error_callback) {
171 if (!proxy_)
172 return;
173 proxy_->CallMethodWithErrorCallback(
174 method_call,
175 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
176 base::Bind(&IBusConfigClientImpl::OnSetValue,
177 weak_ptr_factory_.GetWeakPtr(),
178 error_callback),
179 base::Bind(&IBusConfigClientImpl::OnSetValueFail,
180 weak_ptr_factory_.GetWeakPtr(),
181 error_callback));
184 void OnSetValue(const ErrorCallback& error_callback,
185 dbus::Response* response) {
186 if (!response) {
187 LOG(ERROR) << "Response is NULL.";
188 error_callback.Run();
189 return;
193 void OnSetValueFail(const ErrorCallback& error_callback,
194 dbus::ErrorResponse* response) {
195 error_callback.Run();
198 void OnNameOwnerChanged(const OnIBusConfigReady& on_ready,
199 dbus::Signal* signal) {
200 DCHECK(signal);
201 std::string name;
202 std::string old_owner;
203 std::string new_owner;
205 dbus::MessageReader reader(signal);
206 if (!reader.PopString(&name) ||
207 !reader.PopString(&old_owner) ||
208 !reader.PopString(&new_owner)) {
209 DLOG(ERROR) << "Invalid response of NameOwnerChanged."
210 << signal->ToString();
211 return;
214 if (name != ibus::config::kServiceName)
215 return; // Not a signal for ibus-config.
217 if (!old_owner.empty() || new_owner.empty()) {
218 DVLOG(1) << "Unexpected name owner change: name=" << name
219 << ", old_owner=" << old_owner << ", new_owner=" << new_owner;
220 proxy_ = NULL;
221 return;
224 if (proxy_)
225 return; // Already initialized.
227 proxy_ = bus_->GetObjectProxy(ibus::config::kServiceName,
228 dbus::ObjectPath(
229 ibus::config::kServicePath));
230 if (!on_ready.is_null())
231 on_ready.Run();
234 // Handles response of GetNameOwner.
235 void OnGetNameOwner(const OnIBusConfigReady& on_ready,
236 dbus::Response* response) {
237 if (!response) {
238 LOG(ERROR) << "Response is NULL.";
239 return;
241 std::string owner;
242 dbus::MessageReader reader(response);
244 if (!reader.PopString(&owner)) {
245 LOG(ERROR) << "Invalid response of GetNameOwner."
246 << response->ToString();
247 return;
250 // If the owner is empty, ibus-config daemon is not ready. So will
251 // initialize object proxy on NameOwnerChanged signal.
252 if (owner.empty())
253 return;
255 proxy_ = bus_->GetObjectProxy(ibus::config::kServiceName,
256 dbus::ObjectPath(
257 ibus::config::kServicePath));
258 if (!on_ready.is_null())
259 on_ready.Run();
262 dbus::ObjectProxy* proxy_;
263 dbus::Bus* bus_;
264 base::WeakPtrFactory<IBusConfigClientImpl> weak_ptr_factory_;
266 DISALLOW_COPY_AND_ASSIGN(IBusConfigClientImpl);
269 // A stub implementation of IBusConfigClient.
270 // A configuration framework based on ibus will not be used after Extension IME
271 // migration.
272 class IBusConfigClientStubImpl : public IBusConfigClient {
273 public:
274 IBusConfigClientStubImpl() {}
275 virtual ~IBusConfigClientStubImpl() {}
276 virtual void InitializeAsync(const OnIBusConfigReady& on_ready) OVERRIDE {}
277 virtual void SetStringValue(const std::string& section,
278 const std::string& key,
279 const std::string& value,
280 const ErrorCallback& error_callback) OVERRIDE {}
281 virtual void SetIntValue(const std::string& section,
282 const std::string& key,
283 int value,
284 const ErrorCallback& error_callback) OVERRIDE {}
285 virtual void SetBoolValue(const std::string& section,
286 const std::string& key,
287 bool value,
288 const ErrorCallback& error_callback) OVERRIDE {}
289 virtual void SetStringListValue(
290 const std::string& section,
291 const std::string& key,
292 const std::vector<std::string>& value,
293 const ErrorCallback& error_callback) OVERRIDE {}
295 private:
296 DISALLOW_COPY_AND_ASSIGN(IBusConfigClientStubImpl);
299 } // namespace
301 ///////////////////////////////////////////////////////////////////////////////
302 // IBusConfigClient
304 IBusConfigClient::IBusConfigClient() {}
306 IBusConfigClient::~IBusConfigClient() {}
308 // static
309 IBusConfigClient* IBusConfigClient::Create(DBusClientImplementationType type,
310 dbus::Bus* bus) {
311 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) {
312 return new IBusConfigClientImpl(bus);
314 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
315 return new IBusConfigClientStubImpl();
318 } // namespace chromeos