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_client.h"
8 #include "base/callback.h"
9 #include "chromeos/dbus/ibus/ibus_constants.h"
10 #include "chromeos/dbus/ibus/ibus_component.h"
11 #include "chromeos/dbus/ibus/ibus_engine_service.h"
12 #include "chromeos/ime/ibus_bridge.h"
14 #include "dbus/message.h"
15 #include "dbus/object_path.h"
16 #include "dbus/object_proxy.h"
22 // The IBusClient implementation.
23 class IBusClientImpl
: public IBusClient
{
25 explicit IBusClientImpl(dbus::Bus
* bus
)
26 : proxy_(bus
->GetObjectProxy(ibus::kServiceName
,
27 dbus::ObjectPath(ibus::bus::kServicePath
))),
28 weak_ptr_factory_(this) {
31 virtual ~IBusClientImpl() {}
33 // IBusClient override.
34 virtual void CreateInputContext(
35 const std::string
& client_name
,
36 const CreateInputContextCallback
& callback
,
37 const ErrorCallback
& error_callback
) OVERRIDE
{
38 DCHECK(!callback
.is_null());
39 DCHECK(!error_callback
.is_null());
40 dbus::MethodCall
method_call(ibus::bus::kServiceInterface
,
41 ibus::bus::kCreateInputContextMethod
);
42 dbus::MessageWriter
writer(&method_call
);
43 writer
.AppendString(client_name
);
44 proxy_
->CallMethodWithErrorCallback(
46 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
47 base::Bind(&IBusClientImpl::OnCreateInputContext
,
48 weak_ptr_factory_
.GetWeakPtr(),
51 base::Bind(&IBusClientImpl::OnDBusMethodCallFail
,
52 weak_ptr_factory_
.GetWeakPtr(),
56 // IBusClient override.
57 virtual void RegisterComponent(
58 const IBusComponent
& ibus_component
,
59 const RegisterComponentCallback
& callback
,
60 const ErrorCallback
& error_callback
) OVERRIDE
{
61 DCHECK(!callback
.is_null());
62 DCHECK(!error_callback
.is_null());
63 dbus::MethodCall
method_call(ibus::bus::kServiceInterface
,
64 ibus::bus::kRegisterComponentMethod
);
65 dbus::MessageWriter
writer(&method_call
);
66 AppendIBusComponent(ibus_component
, &writer
);
67 proxy_
->CallMethodWithErrorCallback(
69 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
70 base::Bind(&IBusClientImpl::OnRegisterComponent
,
71 weak_ptr_factory_
.GetWeakPtr(),
74 base::Bind(&IBusClientImpl::OnDBusMethodCallFail
,
75 weak_ptr_factory_
.GetWeakPtr(),
79 // IBusClient override.
80 virtual void SetGlobalEngine(const std::string
& engine_name
,
81 const ErrorCallback
& error_callback
) OVERRIDE
{
82 DCHECK(!error_callback
.is_null());
83 dbus::MethodCall
method_call(ibus::bus::kServiceInterface
,
84 ibus::bus::kSetGlobalEngineMethod
);
85 dbus::MessageWriter
writer(&method_call
);
86 writer
.AppendString(engine_name
);
87 proxy_
->CallMethodWithErrorCallback(
89 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
90 base::Bind(&IBusClientImpl::OnSetGlobalEngine
,
91 weak_ptr_factory_
.GetWeakPtr(),
93 base::Bind(&IBusClientImpl::OnDBusMethodCallFail
,
94 weak_ptr_factory_
.GetWeakPtr(),
98 // IBusClient override.
99 virtual void Exit(ExitOption option
,
100 const ErrorCallback
& error_callback
) OVERRIDE
{
101 DCHECK(!error_callback
.is_null());
102 dbus::MethodCall
method_call(ibus::bus::kServiceInterface
,
103 ibus::bus::kExitMethod
);
104 dbus::MessageWriter
writer(&method_call
);
105 writer
.AppendBool(option
== RESTART_IBUS_DAEMON
);
106 proxy_
->CallMethodWithErrorCallback(
108 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
109 base::Bind(&IBusClientImpl::OnExit
,
110 weak_ptr_factory_
.GetWeakPtr(),
112 base::Bind(&IBusClientImpl::OnDBusMethodCallFail
,
113 weak_ptr_factory_
.GetWeakPtr(),
118 // Handles responses of CreateInputContext method calls.
119 void OnCreateInputContext(const CreateInputContextCallback
& callback
,
120 const ErrorCallback
& error_callback
,
121 dbus::Response
* response
) {
123 LOG(ERROR
) << "Cannot get input context: response is NULL.";
124 error_callback
.Run();
127 dbus::MessageReader
reader(response
);
128 dbus::ObjectPath object_path
;
129 if (!reader
.PopObjectPath(&object_path
)) {
130 // The IBus message structure may be changed.
131 LOG(ERROR
) << "Invalid response: " << response
->ToString();
132 error_callback
.Run();
135 callback
.Run(object_path
);
138 // Handles responses of RegisterComponent method calls.
139 void OnRegisterComponent(const RegisterComponentCallback
& callback
,
140 const ErrorCallback
& error_callback
,
141 dbus::Response
* response
) {
143 LOG(ERROR
) << "Response is NULL.";
144 error_callback
.Run();
150 // Handles responses of RegisterComponent method calls.
151 void OnSetGlobalEngine(const ErrorCallback
& error_callback
,
152 dbus::Response
* response
) {
154 LOG(ERROR
) << "Response is NULL.";
155 error_callback
.Run();
160 // Handles responses of RegisterComponent method calls.
161 void OnExit(const ErrorCallback
& error_callback
,
162 dbus::Response
* response
) {
164 LOG(ERROR
) << "Response is NULL.";
165 error_callback
.Run();
170 // Handles error response of RegisterComponent method call.
171 void OnDBusMethodCallFail(const ErrorCallback
& error_callback
,
172 dbus::ErrorResponse
* response
) {
173 error_callback
.Run();
176 dbus::ObjectProxy
* proxy_
;
177 base::WeakPtrFactory
<IBusClientImpl
> weak_ptr_factory_
;
179 DISALLOW_COPY_AND_ASSIGN(IBusClientImpl
);
182 // An implementation of IBusClient without ibus-daemon interaction.
183 // Currently this class is used only on linux desktop.
184 // TODO(nona): Use this on ChromeOS device once crbug.com/171351 is fixed.
185 class IBusClientDaemonlessImpl
: public IBusClient
{
187 IBusClientDaemonlessImpl() {}
188 virtual ~IBusClientDaemonlessImpl() {}
190 virtual void CreateInputContext(
191 const std::string
& client_name
,
192 const CreateInputContextCallback
& callback
,
193 const ErrorCallback
& error_callback
) OVERRIDE
{
194 // TODO(nona): Remove this function once ibus-daemon is gone.
195 // We don't have to do anything for this function except for calling
196 // |callback| as the success of this function. The original spec of ibus
197 // supports multiple input contexts, but there is only one input context in
198 // Chrome OS. That is all IME events will be came from same input context
199 // and all engine action shuold be forwarded to same input context.
200 dbus::ObjectPath
path("dummpy path");
204 virtual void RegisterComponent(
205 const IBusComponent
& ibus_component
,
206 const RegisterComponentCallback
& callback
,
207 const ErrorCallback
& error_callback
) OVERRIDE
{
208 // TODO(nona): Remove this function once ibus-daemon is gone.
209 // The information about engine is stored in chromeos::InputMethodManager so
210 // IBusBridge doesn't do anything except for calling |callback| as success
215 virtual void SetGlobalEngine(const std::string
& engine_name
,
216 const ErrorCallback
& error_callback
) OVERRIDE
{
217 IBusEngineHandlerInterface
* previous_engine
=
218 IBusBridge::Get()->GetEngineHandler();
220 previous_engine
->Disable();
221 IBusBridge::Get()->CreateEngine(engine_name
);
222 IBusEngineHandlerInterface
* next_engine
=
223 IBusBridge::Get()->GetEngineHandler();
225 next_engine
->Enable();
228 virtual void Exit(ExitOption option
,
229 const ErrorCallback
& error_callback
) OVERRIDE
{
230 // Exit is not supported on daemon-less implementation.
234 DISALLOW_COPY_AND_ASSIGN(IBusClientDaemonlessImpl
);
239 ///////////////////////////////////////////////////////////////////////////////
242 IBusClient::IBusClient() {}
244 IBusClient::~IBusClient() {}
247 IBusClient
* IBusClient::Create(DBusClientImplementationType type
,
249 if (type
== REAL_DBUS_CLIENT_IMPLEMENTATION
) {
250 return new IBusClientImpl(bus
);
252 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION
, type
);
253 return new IBusClientDaemonlessImpl();
256 } // namespace chromeos