1// Copyright 2014 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.
4
5#include "chromeos/dbus/bluetooth_gatt_descriptor_client.h"
6
7#include "base/bind.h"
8#include "base/memory/weak_ptr.h"
9#include "base/observer_list.h"
10#include "dbus/bus.h"
11#include "dbus/object_manager.h"
12#include "third_party/cros_system_api/dbus/service_constants.h"
13
14namespace chromeos {
15
16// static
17const char BluetoothGattDescriptorClient::kNoResponseError[] =
18    "org.chromium.Error.NoResponse";
19// static
20const char BluetoothGattDescriptorClient::kUnknownDescriptorError[] =
21    "org.chromium.Error.UnknownDescriptor";
22
23BluetoothGattDescriptorClient::Properties::Properties(
24    dbus::ObjectProxy* object_proxy,
25    const std::string& interface_name,
26    const PropertyChangedCallback&callback)
27    : dbus::PropertySet(object_proxy, interface_name, callback) {
28  RegisterProperty(bluetooth_gatt_descriptor::kUUIDProperty, &uuid);
29  RegisterProperty(bluetooth_gatt_descriptor::kCharacteristicProperty,
30                   &characteristic);
31}
32
33BluetoothGattDescriptorClient::Properties::~Properties() {
34}
35
36// The BluetoothGattDescriptorClient implementation used in production.
37class BluetoothGattDescriptorClientImpl
38    : public BluetoothGattDescriptorClient,
39      public dbus::ObjectManager::Interface {
40 public:
41  BluetoothGattDescriptorClientImpl()
42      : object_manager_(NULL),
43        weak_ptr_factory_(this) {
44  }
45
46  virtual ~BluetoothGattDescriptorClientImpl() {
47    object_manager_->UnregisterInterface(
48        bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface);
49  }
50
51  // BluetoothGattDescriptorClientImpl override.
52  virtual void AddObserver(
53      BluetoothGattDescriptorClient::Observer* observer) OVERRIDE {
54    DCHECK(observer);
55    observers_.AddObserver(observer);
56  }
57
58  // BluetoothGattDescriptorClientImpl override.
59  virtual void RemoveObserver(
60      BluetoothGattDescriptorClient::Observer* observer) OVERRIDE {
61    DCHECK(observer);
62    observers_.RemoveObserver(observer);
63  }
64
65  // BluetoothGattDescriptorClientImpl override.
66  virtual std::vector<dbus::ObjectPath> GetDescriptors() OVERRIDE {
67    DCHECK(object_manager_);
68    return object_manager_->GetObjectsWithInterface(
69        bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface);
70  }
71
72  // BluetoothGattDescriptorClientImpl override.
73  virtual Properties* GetProperties(
74      const dbus::ObjectPath& object_path) OVERRIDE {
75    DCHECK(object_manager_);
76    return static_cast<Properties*>(
77        object_manager_->GetProperties(
78            object_path,
79            bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface));
80  }
81
82  // BluetoothGattDescriptorClientImpl override.
83  virtual void ReadValue(const dbus::ObjectPath& object_path,
84                         const ValueCallback& callback,
85                         const ErrorCallback& error_callback) OVERRIDE {
86    dbus::ObjectProxy* object_proxy =
87        object_manager_->GetObjectProxy(object_path);
88    if (!object_proxy) {
89      error_callback.Run(kUnknownDescriptorError, "");
90      return;
91    }
92
93    dbus::MethodCall method_call(
94        bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface,
95        bluetooth_gatt_descriptor::kReadValue);
96
97    object_proxy->CallMethodWithErrorCallback(
98        &method_call,
99        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
100        base::Bind(&BluetoothGattDescriptorClientImpl::OnValueSuccess,
101                   weak_ptr_factory_.GetWeakPtr(),
102                   callback),
103        base::Bind(&BluetoothGattDescriptorClientImpl::OnError,
104                   weak_ptr_factory_.GetWeakPtr(),
105                   error_callback));
106  }
107
108  // BluetoothGattDescriptorClientImpl override.
109  virtual void WriteValue(const dbus::ObjectPath& object_path,
110                          const std::vector<uint8>& value,
111                          const base::Closure& callback,
112                          const ErrorCallback& error_callback) OVERRIDE {
113    dbus::ObjectProxy* object_proxy =
114        object_manager_->GetObjectProxy(object_path);
115    if (!object_proxy) {
116      error_callback.Run(kUnknownDescriptorError, "");
117      return;
118    }
119
120    dbus::MethodCall method_call(
121        bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface,
122        bluetooth_gatt_descriptor::kWriteValue);
123    dbus::MessageWriter writer(&method_call);
124    writer.AppendArrayOfBytes(value.data(), value.size());
125
126    object_proxy->CallMethodWithErrorCallback(
127        &method_call,
128        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
129        base::Bind(&BluetoothGattDescriptorClientImpl::OnSuccess,
130                   weak_ptr_factory_.GetWeakPtr(),
131                   callback),
132        base::Bind(&BluetoothGattDescriptorClientImpl::OnError,
133                   weak_ptr_factory_.GetWeakPtr(),
134                   error_callback));
135  }
136
137  // dbus::ObjectManager::Interface override.
138  virtual dbus::PropertySet* CreateProperties(
139      dbus::ObjectProxy *object_proxy,
140      const dbus::ObjectPath& object_path,
141      const std::string& interface_name) OVERRIDE {
142    Properties* properties = new Properties(
143        object_proxy,
144        interface_name,
145        base::Bind(&BluetoothGattDescriptorClientImpl::OnPropertyChanged,
146                   weak_ptr_factory_.GetWeakPtr(),
147                   object_path));
148    return static_cast<dbus::PropertySet*>(properties);
149  }
150
151  // dbus::ObjectManager::Interface override.
152  virtual void ObjectAdded(const dbus::ObjectPath& object_path,
153                           const std::string& interface_name) OVERRIDE {
154    VLOG(2) << "Remote GATT descriptor added: " << object_path.value();
155    FOR_EACH_OBSERVER(BluetoothGattDescriptorClient::Observer, observers_,
156                      GattDescriptorAdded(object_path));
157  }
158
159  // dbus::ObjectManager::Interface override.
160  virtual void ObjectRemoved(const dbus::ObjectPath& object_path,
161                             const std::string& interface_name) OVERRIDE {
162    VLOG(2) << "Remote GATT descriptor removed: " << object_path.value();
163    FOR_EACH_OBSERVER(BluetoothGattDescriptorClient::Observer, observers_,
164                      GattDescriptorRemoved(object_path));
165  }
166
167 protected:
168  // chromeos::DBusClient override.
169  virtual void Init(dbus::Bus* bus) OVERRIDE {
170    object_manager_ = bus->GetObjectManager(
171        bluetooth_object_manager::kBluetoothObjectManagerServiceName,
172        dbus::ObjectPath(
173            bluetooth_object_manager::kBluetoothObjectManagerServicePath));
174    object_manager_->RegisterInterface(
175        bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface,
176        this);
177  }
178
179 private:
180  // Called by dbus::PropertySet when a property value is changed, either by
181  // result of a signal or response to a GetAll() or Get() call. Informs
182  // observers.
183  virtual void OnPropertyChanged(const dbus::ObjectPath& object_path,
184                                 const std::string& property_name) {
185    VLOG(2) << "Remote GATT descriptor property changed: "
186            << object_path.value() << ": " << property_name;
187    FOR_EACH_OBSERVER(BluetoothGattDescriptorClient::Observer, observers_,
188                      GattDescriptorPropertyChanged(object_path,
189                                                    property_name));
190  }
191
192  // Called when a response for a successful method call is received.
193  void OnSuccess(const base::Closure& callback, dbus::Response* response) {
194    DCHECK(response);
195    callback.Run();
196  }
197
198  // Called when a descriptor value response for a successful method call is
199  // received.
200  void OnValueSuccess(const ValueCallback& callback, dbus::Response* response) {
201    DCHECK(response);
202    dbus::MessageReader reader(response);
203
204    const uint8* bytes = NULL;
205    size_t length = 0;
206
207    if (!reader.PopArrayOfBytes(&bytes, &length))
208      VLOG(2) << "Error reading array of bytes in ValueCallback";
209
210    std::vector<uint8> value;
211
212    if (bytes)
213      value.assign(bytes, bytes + length);
214
215    callback.Run(value);
216  }
217
218  // Called when a response for a failed method call is received.
219  void OnError(const ErrorCallback& error_callback,
220               dbus::ErrorResponse* response) {
221    // Error response has optional error message argument.
222    std::string error_name;
223    std::string error_message;
224    if (response) {
225      dbus::MessageReader reader(response);
226      error_name = response->GetErrorName();
227      reader.PopString(&error_message);
228    } else {
229      error_name = kNoResponseError;
230      error_message = "";
231    }
232    error_callback.Run(error_name, error_message);
233  }
234
235  dbus::ObjectManager* object_manager_;
236
237  // List of observers interested in event notifications from us.
238  ObserverList<BluetoothGattDescriptorClient::Observer> observers_;
239
240  // Weak pointer factory for generating 'this' pointers that might live longer
241  // than we do.
242  // Note: This should remain the last member so it'll be destroyed and
243  // invalidate its weak pointers before any other members are destroyed.
244  base::WeakPtrFactory<BluetoothGattDescriptorClientImpl> weak_ptr_factory_;
245
246  DISALLOW_COPY_AND_ASSIGN(BluetoothGattDescriptorClientImpl);
247};
248
249BluetoothGattDescriptorClient::BluetoothGattDescriptorClient() {
250}
251
252BluetoothGattDescriptorClient::~BluetoothGattDescriptorClient() {
253}
254
255// static
256BluetoothGattDescriptorClient* BluetoothGattDescriptorClient::Create() {
257  return new BluetoothGattDescriptorClientImpl();
258}
259
260}  // namespace chromeos
261