1// Copyright 2013 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_adapter_client.h"
6
7#include "base/bind.h"
8#include "base/logging.h"
9#include "dbus/bus.h"
10#include "dbus/message.h"
11#include "dbus/object_manager.h"
12#include "dbus/object_path.h"
13#include "dbus/object_proxy.h"
14#include "third_party/cros_system_api/dbus/service_constants.h"
15
16namespace chromeos {
17
18const char BluetoothAdapterClient::kNoResponseError[] =
19    "org.chromium.Error.NoResponse";
20const char BluetoothAdapterClient::kUnknownAdapterError[] =
21    "org.chromium.Error.UnknownAdapter";
22
23BluetoothAdapterClient::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_adapter::kAddressProperty, &address);
29  RegisterProperty(bluetooth_adapter::kNameProperty, &name);
30  RegisterProperty(bluetooth_adapter::kAliasProperty, &alias);
31  RegisterProperty(bluetooth_adapter::kClassProperty, &bluetooth_class);
32  RegisterProperty(bluetooth_adapter::kPoweredProperty, &powered);
33  RegisterProperty(bluetooth_adapter::kDiscoverableProperty, &discoverable);
34  RegisterProperty(bluetooth_adapter::kPairableProperty, &pairable);
35  RegisterProperty(bluetooth_adapter::kPairableTimeoutProperty,
36                   &pairable_timeout);
37  RegisterProperty(bluetooth_adapter::kDiscoverableTimeoutProperty,
38                   &discoverable_timeout);
39  RegisterProperty(bluetooth_adapter::kDiscoveringProperty, &discovering);
40  RegisterProperty(bluetooth_adapter::kUUIDsProperty, &uuids);
41  RegisterProperty(bluetooth_adapter::kModaliasProperty, &modalias);
42}
43
44BluetoothAdapterClient::Properties::~Properties() {
45}
46
47
48// The BluetoothAdapterClient implementation used in production.
49class BluetoothAdapterClientImpl
50    : public BluetoothAdapterClient,
51      public dbus::ObjectManager::Interface {
52 public:
53  BluetoothAdapterClientImpl()
54      : object_manager_(NULL), weak_ptr_factory_(this) {}
55
56  virtual ~BluetoothAdapterClientImpl() {
57    object_manager_->UnregisterInterface(
58        bluetooth_adapter::kBluetoothAdapterInterface);
59  }
60
61  // BluetoothAdapterClient override.
62  virtual void AddObserver(BluetoothAdapterClient::Observer* observer)
63      OVERRIDE {
64    DCHECK(observer);
65    observers_.AddObserver(observer);
66  }
67
68  // BluetoothAdapterClient override.
69  virtual void RemoveObserver(BluetoothAdapterClient::Observer* observer)
70      OVERRIDE {
71    DCHECK(observer);
72    observers_.RemoveObserver(observer);
73  }
74
75  // Returns the list of adapter object paths known to the system.
76  virtual std::vector<dbus::ObjectPath> GetAdapters() OVERRIDE {
77    return object_manager_->GetObjectsWithInterface(
78        bluetooth_adapter::kBluetoothAdapterInterface);
79  }
80
81  // dbus::ObjectManager::Interface override.
82  virtual dbus::PropertySet* CreateProperties(
83      dbus::ObjectProxy* object_proxy,
84      const dbus::ObjectPath& object_path,
85      const std::string& interface_name) OVERRIDE {
86    Properties* properties = new Properties(
87        object_proxy,
88        interface_name,
89        base::Bind(&BluetoothAdapterClientImpl::OnPropertyChanged,
90                   weak_ptr_factory_.GetWeakPtr(),
91                   object_path));
92    return static_cast<dbus::PropertySet*>(properties);
93  }
94
95  // BluetoothAdapterClient override.
96  virtual Properties* GetProperties(const dbus::ObjectPath& object_path)
97      OVERRIDE {
98    return static_cast<Properties*>(
99        object_manager_->GetProperties(
100            object_path,
101            bluetooth_adapter::kBluetoothAdapterInterface));
102  }
103
104  // BluetoothAdapterClient override.
105  virtual void StartDiscovery(const dbus::ObjectPath& object_path,
106                              const base::Closure& callback,
107                              const ErrorCallback& error_callback) OVERRIDE {
108    dbus::MethodCall method_call(
109        bluetooth_adapter::kBluetoothAdapterInterface,
110        bluetooth_adapter::kStartDiscovery);
111
112    dbus::ObjectProxy* object_proxy =
113        object_manager_->GetObjectProxy(object_path);
114    if (!object_proxy) {
115      error_callback.Run(kUnknownAdapterError, "");
116      return;
117    }
118
119    object_proxy->CallMethodWithErrorCallback(
120        &method_call,
121        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
122        base::Bind(&BluetoothAdapterClientImpl::OnSuccess,
123                   weak_ptr_factory_.GetWeakPtr(), callback),
124        base::Bind(&BluetoothAdapterClientImpl::OnError,
125                   weak_ptr_factory_.GetWeakPtr(), error_callback));
126  }
127
128  // BluetoothAdapterClient override.
129  virtual void StopDiscovery(const dbus::ObjectPath& object_path,
130                             const base::Closure& callback,
131                             const ErrorCallback& error_callback) OVERRIDE {
132    dbus::MethodCall method_call(
133        bluetooth_adapter::kBluetoothAdapterInterface,
134        bluetooth_adapter::kStopDiscovery);
135
136    dbus::ObjectProxy* object_proxy =
137        object_manager_->GetObjectProxy(object_path);
138    if (!object_proxy) {
139      error_callback.Run(kUnknownAdapterError, "");
140      return;
141    }
142
143    object_proxy->CallMethodWithErrorCallback(
144        &method_call,
145        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
146        base::Bind(&BluetoothAdapterClientImpl::OnSuccess,
147                   weak_ptr_factory_.GetWeakPtr(), callback),
148        base::Bind(&BluetoothAdapterClientImpl::OnError,
149                   weak_ptr_factory_.GetWeakPtr(), error_callback));
150  }
151
152  // BluetoothAdapterClient override.
153  virtual void RemoveDevice(const dbus::ObjectPath& object_path,
154                            const dbus::ObjectPath& device_path,
155                            const base::Closure& callback,
156                            const ErrorCallback& error_callback) OVERRIDE {
157    dbus::MethodCall method_call(
158        bluetooth_adapter::kBluetoothAdapterInterface,
159        bluetooth_adapter::kRemoveDevice);
160
161    dbus::MessageWriter writer(&method_call);
162    writer.AppendObjectPath(device_path);
163
164    dbus::ObjectProxy* object_proxy =
165        object_manager_->GetObjectProxy(object_path);
166    if (!object_proxy) {
167      error_callback.Run(kUnknownAdapterError, "");
168      return;
169    }
170
171    object_proxy->CallMethodWithErrorCallback(
172        &method_call,
173        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
174        base::Bind(&BluetoothAdapterClientImpl::OnSuccess,
175                   weak_ptr_factory_.GetWeakPtr(), callback),
176        base::Bind(&BluetoothAdapterClientImpl::OnError,
177                   weak_ptr_factory_.GetWeakPtr(), error_callback));
178  }
179
180 protected:
181  virtual void Init(dbus::Bus* bus) OVERRIDE {
182    object_manager_ = bus->GetObjectManager(
183        bluetooth_object_manager::kBluetoothObjectManagerServiceName,
184        dbus::ObjectPath(
185            bluetooth_object_manager::kBluetoothObjectManagerServicePath));
186    object_manager_->RegisterInterface(
187        bluetooth_adapter::kBluetoothAdapterInterface, this);
188  }
189
190 private:
191  // Called by dbus::ObjectManager when an object with the adapter interface
192  // is created. Informs observers.
193  virtual void ObjectAdded(const dbus::ObjectPath& object_path,
194                           const std::string& interface_name) OVERRIDE {
195    FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_,
196                      AdapterAdded(object_path));
197  }
198
199  // Called by dbus::ObjectManager when an object with the adapter interface
200  // is removed. Informs observers.
201  virtual void ObjectRemoved(const dbus::ObjectPath& object_path,
202                             const std::string& interface_name) OVERRIDE {
203    FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_,
204                      AdapterRemoved(object_path));
205  }
206
207  // Called by dbus::PropertySet when a property value is changed,
208  // either by result of a signal or response to a GetAll() or Get()
209  // call. Informs observers.
210  void OnPropertyChanged(const dbus::ObjectPath& object_path,
211                         const std::string& property_name) {
212    FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_,
213                      AdapterPropertyChanged(object_path, property_name));
214  }
215
216  // Called when a response for successful method call is received.
217  void OnSuccess(const base::Closure& callback,
218                 dbus::Response* response) {
219    DCHECK(response);
220    callback.Run();
221  }
222
223  // Called when a response for a failed method call is received.
224  void OnError(const ErrorCallback& error_callback,
225               dbus::ErrorResponse* response) {
226    // Error response has optional error message argument.
227    std::string error_name;
228    std::string error_message;
229    if (response) {
230      dbus::MessageReader reader(response);
231      error_name = response->GetErrorName();
232      reader.PopString(&error_message);
233    } else {
234      error_name = kNoResponseError;
235      error_message = "";
236    }
237    error_callback.Run(error_name, error_message);
238  }
239
240  dbus::ObjectManager* object_manager_;
241
242  // List of observers interested in event notifications from us.
243  ObserverList<BluetoothAdapterClient::Observer> observers_;
244
245  // Weak pointer factory for generating 'this' pointers that might live longer
246  // than we do.
247  // Note: This should remain the last member so it'll be destroyed and
248  // invalidate its weak pointers before any other members are destroyed.
249  base::WeakPtrFactory<BluetoothAdapterClientImpl>
250      weak_ptr_factory_;
251
252  DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterClientImpl);
253};
254
255BluetoothAdapterClient::BluetoothAdapterClient() {
256}
257
258BluetoothAdapterClient::~BluetoothAdapterClient() {
259}
260
261BluetoothAdapterClient* BluetoothAdapterClient::Create() {
262  return new BluetoothAdapterClientImpl;
263}
264
265}  // namespace chromeos
266