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/bluetooth_input_client.h"
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "base/stl_util.h"
13 #include "chromeos/dbus/bluetooth_adapter_client.h"
14 #include "chromeos/dbus/bluetooth_property.h"
16 #include "dbus/message.h"
17 #include "dbus/object_path.h"
18 #include "dbus/object_proxy.h"
19 #include "third_party/cros_system_api/dbus/service_constants.h"
23 const char BluetoothInputClient::kNoResponseError
[] =
24 "org.chromium.Error.NoResponse";
26 BluetoothInputClient::Properties::Properties(
27 dbus::ObjectProxy
* object_proxy
,
28 const PropertyChangedCallback
& callback
)
29 : BluetoothPropertySet(object_proxy
,
30 bluetooth_input::kBluetoothInputInterface
,
32 RegisterProperty(bluetooth_input::kConnectedProperty
, &connected
);
35 BluetoothInputClient::Properties::~Properties() {
39 // The BluetoothInputClient implementation used in production.
40 class BluetoothInputClientImpl
: public BluetoothInputClient
,
41 private BluetoothAdapterClient::Observer
{
43 BluetoothInputClientImpl(dbus::Bus
* bus
,
44 BluetoothAdapterClient
* adapter_client
)
46 weak_ptr_factory_(this) {
47 DVLOG(1) << "Creating BluetoothInputClientImpl";
49 DCHECK(adapter_client
);
50 adapter_client
->AddObserver(this);
53 virtual ~BluetoothInputClientImpl() {
54 // Clean up Properties structures
55 for (ObjectMap::iterator iter
= object_map_
.begin();
56 iter
!= object_map_
.end(); ++iter
) {
57 Object object
= iter
->second
;
58 Properties
* properties
= object
.second
;
63 // BluetoothInputClient override.
64 virtual void AddObserver(BluetoothInputClient::Observer
* observer
)
67 observers_
.AddObserver(observer
);
70 // BluetoothInputClient override.
71 virtual void RemoveObserver(BluetoothInputClient::Observer
* observer
)
74 observers_
.RemoveObserver(observer
);
77 // BluetoothInputClient override.
78 virtual Properties
* GetProperties(const dbus::ObjectPath
& object_path
)
80 return GetObject(object_path
).second
;
83 // BluetoothInputClient override.
84 virtual void Connect(const dbus::ObjectPath
& object_path
,
85 const ConnectCallback
& callback
,
86 const ConnectErrorCallback
& error_callback
) OVERRIDE
{
87 dbus::MethodCall
method_call(
88 bluetooth_input::kBluetoothInputInterface
,
89 bluetooth_input::kConnect
);
91 dbus::ObjectProxy
* object_proxy
= GetObjectProxy(object_path
);
93 object_proxy
->CallMethodWithErrorCallback(
95 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
96 base::Bind(&BluetoothInputClientImpl::OnConnect
,
97 weak_ptr_factory_
.GetWeakPtr(), object_path
,
99 base::Bind(&BluetoothInputClientImpl::OnConnectError
,
100 weak_ptr_factory_
.GetWeakPtr(), object_path
,
104 // BluetoothInputClient override.
105 virtual void Disconnect(const dbus::ObjectPath
& object_path
,
106 const InputCallback
& callback
) OVERRIDE
{
107 dbus::MethodCall
method_call(
108 bluetooth_input::kBluetoothInputInterface
,
109 bluetooth_input::kDisconnect
);
111 dbus::ObjectProxy
* object_proxy
= GetObjectProxy(object_path
);
113 object_proxy
->CallMethod(
115 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
116 base::Bind(&BluetoothInputClientImpl::OnDisconnect
,
117 weak_ptr_factory_
.GetWeakPtr(), object_path
, callback
));
121 // We maintain a collection of dbus object proxies and properties structures
122 // for each input device.
123 typedef std::pair
<dbus::ObjectProxy
*, Properties
*> Object
;
124 typedef std::map
<const dbus::ObjectPath
, Object
> ObjectMap
;
125 ObjectMap object_map_
;
127 // BluetoothAdapterClient::Observer override.
128 virtual void DeviceCreated(const dbus::ObjectPath
& adapter_path
,
129 const dbus::ObjectPath
& object_path
) OVERRIDE
{
132 // BluetoothAdapterClient::Observer override.
133 virtual void DeviceRemoved(const dbus::ObjectPath
& adapter_path
,
134 const dbus::ObjectPath
& object_path
) OVERRIDE
{
135 RemoveObject(object_path
);
138 // Ensures that we have an object proxy and properties structure for
139 // an input device with object path |object_path|, creating it if not and
140 // storing it in our |object_map_| map.
141 Object
GetObject(const dbus::ObjectPath
& object_path
) {
142 ObjectMap::iterator iter
= object_map_
.find(object_path
);
143 if (iter
!= object_map_
.end())
146 // Create the object proxy.
148 dbus::ObjectProxy
* object_proxy
= bus_
->GetObjectProxy(
149 bluetooth_input::kBluetoothInputServiceName
, object_path
);
151 // Create the properties structure.
152 Properties
* properties
= new Properties(
154 base::Bind(&BluetoothInputClientImpl::OnPropertyChanged
,
155 weak_ptr_factory_
.GetWeakPtr(), object_path
));
157 properties
->ConnectSignals();
158 properties
->GetAll();
160 Object object
= std::make_pair(object_proxy
, properties
);
161 object_map_
[object_path
] = object
;
165 // Removes the dbus object proxy and properties for the input device with
166 // dbus object path |object_path| from our |object_map_| map.
167 void RemoveObject(const dbus::ObjectPath
& object_path
) {
168 ObjectMap::iterator iter
= object_map_
.find(object_path
);
169 if (iter
!= object_map_
.end()) {
170 // Clean up the Properties structure.
171 Object object
= iter
->second
;
172 Properties
* properties
= object
.second
;
175 object_map_
.erase(iter
);
179 // Returns a pointer to the object proxy for |object_path|, creating
181 dbus::ObjectProxy
* GetObjectProxy(const dbus::ObjectPath
& object_path
) {
182 return GetObject(object_path
).first
;
185 // Called by BluetoothPropertySet when a property value is changed,
186 // either by result of a signal or response to a GetAll() or Get()
187 // call. Informs observers.
188 void OnPropertyChanged(const dbus::ObjectPath
& object_path
,
189 const std::string
& property_name
) {
190 FOR_EACH_OBSERVER(BluetoothInputClient::Observer
, observers_
,
191 InputPropertyChanged(object_path
, property_name
));
194 // Called when a response for Connect() is received.
195 void OnConnect(const dbus::ObjectPath
& object_path
,
196 const ConnectCallback
& callback
,
197 dbus::Response
* response
) {
199 callback
.Run(object_path
);
202 // Called when an error for Connect() is received.
203 void OnConnectError(const dbus::ObjectPath
& object_path
,
204 const ConnectErrorCallback
& error_callback
,
205 dbus::ErrorResponse
* response
) {
206 // Error response has optional error message argument.
207 std::string error_name
;
208 std::string error_message
;
210 dbus::MessageReader
reader(response
);
211 error_name
= response
->GetErrorName();
212 error_message
= reader
.PopString(&error_message
);
214 error_name
= kNoResponseError
;
217 error_callback
.Run(object_path
, error_name
, error_message
);
220 // Called when a response for Disconnect() is received.
221 void OnDisconnect(const dbus::ObjectPath
& object_path
,
222 const InputCallback
& callback
,
223 dbus::Response
* response
) {
224 LOG_IF(WARNING
, !response
) << object_path
.value()
225 << ": OnDisconnect: failed.";
226 callback
.Run(object_path
, response
);
231 // List of observers interested in event notifications from us.
232 ObserverList
<BluetoothInputClient::Observer
> observers_
;
234 // Weak pointer factory for generating 'this' pointers that might live longer
236 // Note: This should remain the last member so it'll be destroyed and
237 // invalidate its weak pointers before any other members are destroyed.
238 base::WeakPtrFactory
<BluetoothInputClientImpl
> weak_ptr_factory_
;
240 DISALLOW_COPY_AND_ASSIGN(BluetoothInputClientImpl
);
243 // The BluetoothInputClient implementation used on Linux desktop, which does
245 class BluetoothInputClientStubImpl
: public BluetoothInputClient
{
247 // BluetoothInputClient override.
248 virtual void AddObserver(Observer
* observer
) OVERRIDE
{
251 // BluetoothInputClient override.
252 virtual void RemoveObserver(Observer
* observer
) OVERRIDE
{
255 // BluetoothInputClient override.
256 virtual Properties
* GetProperties(const dbus::ObjectPath
& object_path
)
258 VLOG(1) << "GetProperties: " << object_path
.value();
262 // BluetoothInputClient override.
263 virtual void Connect(const dbus::ObjectPath
& object_path
,
264 const ConnectCallback
& callback
,
265 const ConnectErrorCallback
& error_callback
) OVERRIDE
{
266 VLOG(1) << "Connect: " << object_path
.value();
267 error_callback
.Run(object_path
, "", "");
270 // BluetoothInputClient override.
271 virtual void Disconnect(const dbus::ObjectPath
& object_path
,
272 const InputCallback
& callback
) OVERRIDE
{
273 VLOG(1) << "Disconnect: " << object_path
.value();
274 callback
.Run(object_path
, false);
278 BluetoothInputClient::BluetoothInputClient() {
281 BluetoothInputClient::~BluetoothInputClient() {
284 BluetoothInputClient
* BluetoothInputClient::Create(
285 DBusClientImplementationType type
,
287 BluetoothAdapterClient
* adapter_client
) {
288 if (type
== REAL_DBUS_CLIENT_IMPLEMENTATION
)
289 return new BluetoothInputClientImpl(bus
, adapter_client
);
290 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION
, type
);
291 return new BluetoothInputClientStubImpl();
294 } // namespace chromeos