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"
10 #include "base/callback.h"
11 #include "chromeos/dbus/ibus/ibus_constants.h"
12 #include "chromeos/dbus/ibus/ibus_component.h"
14 #include "dbus/message.h"
15 #include "dbus/object_path.h"
16 #include "dbus/object_proxy.h"
22 // Called when the |signal| is connected.
23 void OnSignalConnected(const std::string
& interface
,
24 const std::string
& signal
,
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
36 // The IBusConfigClient implementation.
37 class IBusConfigClientImpl
: public IBusConfigClient
{
39 explicit IBusConfigClientImpl(dbus::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(
62 ibus::kNameOwnerChangedSignal
,
63 base::Bind(&IBusConfigClientImpl::OnNameOwnerChanged
,
64 weak_ptr_factory_
.GetWeakPtr(),
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(
74 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
75 base::Bind(&IBusConfigClientImpl::OnGetNameOwner
,
76 weak_ptr_factory_
.GetWeakPtr(),
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
{
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
,
105 const ErrorCallback
& error_callback
) OVERRIDE
{
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
,
125 const ErrorCallback
& error_callback
) OVERRIDE
{
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
{
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
);
169 void CallWithDefaultCallback(dbus::MethodCall
* method_call
,
170 const ErrorCallback
& error_callback
) {
173 proxy_
->CallMethodWithErrorCallback(
175 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
176 base::Bind(&IBusConfigClientImpl::OnSetValue
,
177 weak_ptr_factory_
.GetWeakPtr(),
179 base::Bind(&IBusConfigClientImpl::OnSetValueFail
,
180 weak_ptr_factory_
.GetWeakPtr(),
184 void OnSetValue(const ErrorCallback
& error_callback
,
185 dbus::Response
* response
) {
187 LOG(ERROR
) << "Response is NULL.";
188 error_callback
.Run();
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
) {
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();
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
;
225 return; // Already initialized.
227 proxy_
= bus_
->GetObjectProxy(ibus::config::kServiceName
,
229 ibus::config::kServicePath
));
230 if (!on_ready
.is_null())
234 // Handles response of GetNameOwner.
235 void OnGetNameOwner(const OnIBusConfigReady
& on_ready
,
236 dbus::Response
* response
) {
238 LOG(ERROR
) << "Response is NULL.";
242 dbus::MessageReader
reader(response
);
244 if (!reader
.PopString(&owner
)) {
245 LOG(ERROR
) << "Invalid response of GetNameOwner."
246 << response
->ToString();
250 // If the owner is empty, ibus-config daemon is not ready. So will
251 // initialize object proxy on NameOwnerChanged signal.
255 proxy_
= bus_
->GetObjectProxy(ibus::config::kServiceName
,
257 ibus::config::kServicePath
));
258 if (!on_ready
.is_null())
262 dbus::ObjectProxy
* proxy_
;
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
272 class IBusConfigClientStubImpl
: public IBusConfigClient
{
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
,
284 const ErrorCallback
& error_callback
) OVERRIDE
{}
285 virtual void SetBoolValue(const std::string
& section
,
286 const std::string
& key
,
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
{}
296 DISALLOW_COPY_AND_ASSIGN(IBusConfigClientStubImpl
);
301 ///////////////////////////////////////////////////////////////////////////////
304 IBusConfigClient::IBusConfigClient() {}
306 IBusConfigClient::~IBusConfigClient() {}
309 IBusConfigClient
* IBusConfigClient::Create(DBusClientImplementationType type
,
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