[Session restore] Rename group name Enabled to Restore.
[chromium-blink-merge.git] / chromeos / dbus / bluetooth_gatt_descriptor_service_provider.cc
blob8c494597cf1fbfe54fe82b8b153da2f2b83d39cd
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.
5 #include "chromeos/dbus/bluetooth_gatt_descriptor_service_provider.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/memory/weak_ptr.h"
10 #include "base/strings/string_util.h"
11 #include "base/threading/platform_thread.h"
12 #include "chromeos/dbus/dbus_thread_manager.h"
13 #include "chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.h"
14 #include "dbus/exported_object.h"
15 #include "dbus/message.h"
16 #include "third_party/cros_system_api/dbus/service_constants.h"
18 namespace chromeos {
19 namespace {
20 const char kErrorInvalidArgs[] =
21 "org.freedesktop.DBus.Error.InvalidArgs";
22 const char kErrorPropertyReadOnly[] =
23 "org.freedesktop.DBus.Error.PropertyReadOnly";
24 const char kErrorFailed[] =
25 "org.freedesktop.DBus.Error.Failed";
26 } // namespace
28 // The BluetoothGattDescriptorServiceProvider implementation used in production.
29 class BluetoothGattDescriptorServiceProviderImpl
30 : public BluetoothGattDescriptorServiceProvider {
31 public:
32 BluetoothGattDescriptorServiceProviderImpl(
33 dbus::Bus* bus,
34 const dbus::ObjectPath& object_path,
35 Delegate* delegate,
36 const std::string& uuid,
37 const std::vector<std::string>& permissions,
38 const dbus::ObjectPath& characteristic_path)
39 : origin_thread_id_(base::PlatformThread::CurrentId()),
40 uuid_(uuid),
41 bus_(bus),
42 delegate_(delegate),
43 object_path_(object_path),
44 characteristic_path_(characteristic_path),
45 weak_ptr_factory_(this) {
46 VLOG(1) << "Created Bluetooth GATT characteristic descriptor: "
47 << object_path.value() << " UUID: " << uuid;
48 DCHECK(bus_);
49 DCHECK(delegate_);
50 DCHECK(!uuid_.empty());
51 DCHECK(object_path_.IsValid());
52 DCHECK(characteristic_path_.IsValid());
53 DCHECK(StartsWithASCII(
54 object_path_.value(), characteristic_path_.value() + "/", true));
56 exported_object_ = bus_->GetExportedObject(object_path_);
58 exported_object_->ExportMethod(
59 dbus::kDBusPropertiesInterface,
60 dbus::kDBusPropertiesGet,
61 base::Bind(&BluetoothGattDescriptorServiceProviderImpl::Get,
62 weak_ptr_factory_.GetWeakPtr()),
63 base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnExported,
64 weak_ptr_factory_.GetWeakPtr()));
66 exported_object_->ExportMethod(
67 dbus::kDBusPropertiesInterface,
68 dbus::kDBusPropertiesSet,
69 base::Bind(&BluetoothGattDescriptorServiceProviderImpl::Set,
70 weak_ptr_factory_.GetWeakPtr()),
71 base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnExported,
72 weak_ptr_factory_.GetWeakPtr()));
74 exported_object_->ExportMethod(
75 dbus::kDBusPropertiesInterface,
76 dbus::kDBusPropertiesGetAll,
77 base::Bind(&BluetoothGattDescriptorServiceProviderImpl::GetAll,
78 weak_ptr_factory_.GetWeakPtr()),
79 base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnExported,
80 weak_ptr_factory_.GetWeakPtr()));
83 ~BluetoothGattDescriptorServiceProviderImpl() override {
84 VLOG(1) << "Cleaning up Bluetooth GATT characteristic descriptor: "
85 << object_path_.value();
86 bus_->UnregisterExportedObject(object_path_);
89 // BluetoothGattDescriptorServiceProvider override.
90 void SendValueChanged(const std::vector<uint8>& value) override {
91 VLOG(2) << "Emitting a PropertiesChanged signal for descriptor value.";
92 dbus::Signal signal(
93 dbus::kDBusPropertiesInterface,
94 dbus::kDBusPropertiesChangedSignal);
95 dbus::MessageWriter writer(&signal);
96 dbus::MessageWriter array_writer(NULL);
97 dbus::MessageWriter dict_entry_writer(NULL);
98 dbus::MessageWriter variant_writer(NULL);
100 // interface_name
101 writer.AppendString(
102 bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface);
104 // changed_properties
105 writer.OpenArray("{sv}", &array_writer);
106 array_writer.OpenDictEntry(&dict_entry_writer);
107 dict_entry_writer.AppendString(bluetooth_gatt_descriptor::kValueProperty);
108 dict_entry_writer.OpenVariant("ay", &variant_writer);
109 variant_writer.AppendArrayOfBytes(value.data(), value.size());
110 dict_entry_writer.CloseContainer(&variant_writer);
111 array_writer.CloseContainer(&dict_entry_writer);
112 writer.CloseContainer(&array_writer);
114 // invalidated_properties.
115 writer.OpenArray("s", &array_writer);
116 writer.CloseContainer(&array_writer);
118 exported_object_->SendSignal(&signal);
121 private:
122 // Returns true if the current thread is on the origin thread.
123 bool OnOriginThread() {
124 return base::PlatformThread::CurrentId() == origin_thread_id_;
127 // Called by dbus:: when the Bluetooth daemon fetches a single property of
128 // the descriptor.
129 void Get(dbus::MethodCall* method_call,
130 dbus::ExportedObject::ResponseSender response_sender) {
131 VLOG(2) << "BluetoothGattDescriptorServiceProvider::Get: "
132 << object_path_.value();
133 DCHECK(OnOriginThread());
135 dbus::MessageReader reader(method_call);
137 std::string interface_name;
138 std::string property_name;
139 if (!reader.PopString(&interface_name) ||
140 !reader.PopString(&property_name) ||
141 reader.HasMoreData()) {
142 scoped_ptr<dbus::ErrorResponse> error_response =
143 dbus::ErrorResponse::FromMethodCall(
144 method_call, kErrorInvalidArgs, "Expected 'ss'.");
145 response_sender.Run(error_response.Pass());
146 return;
149 // Only the GATT descriptor interface is supported.
150 if (interface_name !=
151 bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface) {
152 scoped_ptr<dbus::ErrorResponse> error_response =
153 dbus::ErrorResponse::FromMethodCall(
154 method_call, kErrorInvalidArgs,
155 "No such interface: '" + interface_name + "'.");
156 response_sender.Run(error_response.Pass());
157 return;
160 // If getting the "Value" property, obtain the value from the delegate.
161 if (property_name == bluetooth_gatt_descriptor::kValueProperty) {
162 DCHECK(delegate_);
163 delegate_->GetDescriptorValue(
164 base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnGet,
165 weak_ptr_factory_.GetWeakPtr(),
166 method_call, response_sender),
167 base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnFailure,
168 weak_ptr_factory_.GetWeakPtr(),
169 method_call, response_sender));
170 return;
173 scoped_ptr<dbus::Response> response =
174 dbus::Response::FromMethodCall(method_call);
175 dbus::MessageWriter writer(response.get());
176 dbus::MessageWriter variant_writer(NULL);
178 // TODO(armansito): Process the "Permissions" property below.
179 if (property_name == bluetooth_gatt_descriptor::kUUIDProperty) {
180 writer.OpenVariant("s", &variant_writer);
181 variant_writer.AppendString(uuid_);
182 writer.CloseContainer(&variant_writer);
183 } else if (property_name ==
184 bluetooth_gatt_descriptor::kCharacteristicProperty) {
185 writer.OpenVariant("o", &variant_writer);
186 variant_writer.AppendObjectPath(characteristic_path_);
187 writer.CloseContainer(&variant_writer);
188 } else {
189 response = dbus::ErrorResponse::FromMethodCall(
190 method_call,
191 kErrorInvalidArgs,
192 "No such property: '" + property_name + "'.");
195 response_sender.Run(response.Pass());
198 // Called by dbus:: when the Bluetooth daemon sets a single property of the
199 // descriptor.
200 void Set(dbus::MethodCall* method_call,
201 dbus::ExportedObject::ResponseSender response_sender) {
202 VLOG(2) << "BluetoothGattDescriptorServiceProvider::Set: "
203 << object_path_.value();
204 DCHECK(OnOriginThread());
206 dbus::MessageReader reader(method_call);
208 std::string interface_name;
209 std::string property_name;
210 dbus::MessageReader variant_reader(NULL);
211 if (!reader.PopString(&interface_name) ||
212 !reader.PopString(&property_name) ||
213 !reader.PopVariant(&variant_reader) ||
214 reader.HasMoreData()) {
215 scoped_ptr<dbus::ErrorResponse> error_response =
216 dbus::ErrorResponse::FromMethodCall(
217 method_call, kErrorInvalidArgs, "Expected 'ssv'.");
218 response_sender.Run(error_response.Pass());
219 return;
222 // Only the GATT descriptor interface is allowed.
223 if (interface_name !=
224 bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface) {
225 scoped_ptr<dbus::ErrorResponse> error_response =
226 dbus::ErrorResponse::FromMethodCall(
227 method_call, kErrorInvalidArgs,
228 "No such interface: '" + interface_name + "'.");
229 response_sender.Run(error_response.Pass());
230 return;
233 // Only the "Value" property is writeable.
234 if (property_name != bluetooth_gatt_descriptor::kValueProperty) {
235 std::string error_name;
236 std::string error_message;
237 if (property_name == bluetooth_gatt_descriptor::kUUIDProperty ||
238 property_name == bluetooth_gatt_descriptor::kCharacteristicProperty) {
239 error_name = kErrorPropertyReadOnly;
240 error_message = "Read-only property: '" + property_name + "'.";
241 } else {
242 error_name = kErrorInvalidArgs;
243 error_message = "No such property: '" + property_name + "'.";
245 scoped_ptr<dbus::ErrorResponse> error_response =
246 dbus::ErrorResponse::FromMethodCall(
247 method_call, error_name, error_message);
248 response_sender.Run(error_response.Pass());
249 return;
252 // Obtain the value.
253 const uint8* bytes = NULL;
254 size_t length = 0;
255 if (!variant_reader.PopArrayOfBytes(&bytes, &length)) {
256 scoped_ptr<dbus::ErrorResponse> error_response =
257 dbus::ErrorResponse::FromMethodCall(
258 method_call, kErrorInvalidArgs,
259 "Property '" + property_name + "' has type 'ay'.");
260 response_sender.Run(error_response.Pass());
261 return;
264 // Pass the set request onto the delegate.
265 std::vector<uint8> value(bytes, bytes + length);
266 DCHECK(delegate_);
267 delegate_->SetDescriptorValue(
268 value,
269 base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnSet,
270 weak_ptr_factory_.GetWeakPtr(),
271 method_call, response_sender),
272 base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnFailure,
273 weak_ptr_factory_.GetWeakPtr(),
274 method_call, response_sender));
277 // Called by dbus:: when the Bluetooth daemon fetches all properties of the
278 // descriptor.
279 void GetAll(dbus::MethodCall* method_call,
280 dbus::ExportedObject::ResponseSender response_sender) {
281 VLOG(2) << "BluetoothGattDescriptorServiceProvider::GetAll: "
282 << object_path_.value();
283 DCHECK(OnOriginThread());
285 dbus::MessageReader reader(method_call);
287 std::string interface_name;
288 if (!reader.PopString(&interface_name) || reader.HasMoreData()) {
289 scoped_ptr<dbus::ErrorResponse> error_response =
290 dbus::ErrorResponse::FromMethodCall(
291 method_call, kErrorInvalidArgs, "Expected 's'.");
292 response_sender.Run(error_response.Pass());
293 return;
296 // Only the GATT descriptor interface is supported.
297 if (interface_name !=
298 bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface) {
299 scoped_ptr<dbus::ErrorResponse> error_response =
300 dbus::ErrorResponse::FromMethodCall(
301 method_call, kErrorInvalidArgs,
302 "No such interface: '" + interface_name + "'.");
303 response_sender.Run(error_response.Pass());
304 return;
307 // Try to obtain the value from the delegate. We will construct the
308 // response in the success callback.
309 DCHECK(delegate_);
310 delegate_->GetDescriptorValue(
311 base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnGetAll,
312 weak_ptr_factory_.GetWeakPtr(),
313 method_call, response_sender),
314 base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnFailure,
315 weak_ptr_factory_.GetWeakPtr(),
316 method_call, response_sender));
319 // Called by dbus:: when a method is exported.
320 void OnExported(const std::string& interface_name,
321 const std::string& method_name,
322 bool success) {
323 LOG_IF(WARNING, !success) << "Failed to export "
324 << interface_name << "." << method_name;
327 // Called by the Delegate in response to a method to call to get all
328 // properties, in which the delegate has successfully returned the
329 // descriptor value.
330 void OnGetAll(dbus::MethodCall* method_call,
331 dbus::ExportedObject::ResponseSender response_sender,
332 const std::vector<uint8>& value) {
333 VLOG(2) << "Descriptor value obtained from delegate. Responding to "
334 << "GetAll.";
336 scoped_ptr<dbus::Response> response =
337 dbus::Response::FromMethodCall(method_call);
338 dbus::MessageWriter writer(response.get());
339 dbus::MessageWriter array_writer(NULL);
340 dbus::MessageWriter dict_entry_writer(NULL);
341 dbus::MessageWriter variant_writer(NULL);
343 writer.OpenArray("{sv}", &array_writer);
345 array_writer.OpenDictEntry(&dict_entry_writer);
346 dict_entry_writer.AppendString(
347 bluetooth_gatt_descriptor::kUUIDProperty);
348 dict_entry_writer.AppendVariantOfString(uuid_);
349 array_writer.CloseContainer(&dict_entry_writer);
351 array_writer.OpenDictEntry(&dict_entry_writer);
352 dict_entry_writer.AppendString(
353 bluetooth_gatt_descriptor::kCharacteristicProperty);
354 dict_entry_writer.AppendVariantOfObjectPath(characteristic_path_);
355 array_writer.CloseContainer(&dict_entry_writer);
357 array_writer.OpenDictEntry(&dict_entry_writer);
358 dict_entry_writer.AppendString(
359 bluetooth_gatt_descriptor::kValueProperty);
360 dict_entry_writer.OpenVariant("ay", &variant_writer);
361 variant_writer.AppendArrayOfBytes(value.data(), value.size());
362 dict_entry_writer.CloseContainer(&variant_writer);
363 array_writer.CloseContainer(&dict_entry_writer);
365 // TODO(armansito): Process "Permissions" property.
367 writer.CloseContainer(&array_writer);
369 response_sender.Run(response.Pass());
372 // Called by the Delegate in response to a successful method call to get the
373 // descriptor value.
374 void OnGet(dbus::MethodCall* method_call,
375 dbus::ExportedObject::ResponseSender response_sender,
376 const std::vector<uint8>& value) {
377 VLOG(2) << "Returning descriptor value obtained from delegate.";
378 scoped_ptr<dbus::Response> response =
379 dbus::Response::FromMethodCall(method_call);
380 dbus::MessageWriter writer(response.get());
381 dbus::MessageWriter variant_writer(NULL);
383 writer.OpenVariant("ay", &variant_writer);
384 variant_writer.AppendArrayOfBytes(value.data(), value.size());
385 writer.CloseContainer(&variant_writer);
387 response_sender.Run(response.Pass());
390 // Called by the Delegate in response to a successful method call to set the
391 // descriptor value.
392 void OnSet(dbus::MethodCall* method_call,
393 dbus::ExportedObject::ResponseSender response_sender) {
394 VLOG(2) << "Successfully set descriptor value. Return success.";
395 response_sender.Run(dbus::Response::FromMethodCall(method_call));
398 // Called by the Delegate in response to a failed method call to get or set
399 // the descriptor value.
400 void OnFailure(dbus::MethodCall* method_call,
401 dbus::ExportedObject::ResponseSender response_sender) {
402 VLOG(2) << "Failed to get/set descriptor value. Report error.";
403 scoped_ptr<dbus::ErrorResponse> error_response =
404 dbus::ErrorResponse::FromMethodCall(
405 method_call, kErrorFailed,
406 "Failed to get/set descriptor value.");
407 response_sender.Run(error_response.Pass());
410 // Origin thread (i.e. the UI thread in production).
411 base::PlatformThreadId origin_thread_id_;
413 // 128-bit descriptor UUID of this object.
414 std::string uuid_;
416 // D-Bus bus object is exported on, not owned by this object and must
417 // outlive it.
418 dbus::Bus* bus_;
420 // Incoming methods to get and set the "Value" property are passed on to the
421 // delegate and callbacks passed to generate a reply. |delegate_| is generally
422 // the object that owns this one and must outlive it.
423 Delegate* delegate_;
425 // D-Bus object path of object we are exporting, kept so we can unregister
426 // again in our destructor.
427 dbus::ObjectPath object_path_;
429 // Object path of the GATT characteristic that the exported descriptor belongs
430 // to.
431 dbus::ObjectPath characteristic_path_;
433 // D-Bus object we are exporting, owned by this object.
434 scoped_refptr<dbus::ExportedObject> exported_object_;
436 // Weak pointer factory for generating 'this' pointers that might live longer
437 // than we do.
438 // Note: This should remain the last member so it'll be destroyed and
439 // invalidate its weak pointers before any other members are destroyed.
440 base::WeakPtrFactory<BluetoothGattDescriptorServiceProviderImpl>
441 weak_ptr_factory_;
443 DISALLOW_COPY_AND_ASSIGN(BluetoothGattDescriptorServiceProviderImpl);
446 BluetoothGattDescriptorServiceProvider::
447 BluetoothGattDescriptorServiceProvider() {
450 BluetoothGattDescriptorServiceProvider::
451 ~BluetoothGattDescriptorServiceProvider() {
454 // static
455 BluetoothGattDescriptorServiceProvider*
456 BluetoothGattDescriptorServiceProvider::Create(
457 dbus::Bus* bus,
458 const dbus::ObjectPath& object_path,
459 Delegate* delegate,
460 const std::string& uuid,
461 const std::vector<std::string>& permissions,
462 const dbus::ObjectPath& characteristic_path) {
463 if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) {
464 return new BluetoothGattDescriptorServiceProviderImpl(
465 bus, object_path, delegate, uuid, permissions, characteristic_path);
467 return new FakeBluetoothGattDescriptorServiceProvider(
468 object_path, delegate, uuid, permissions, characteristic_path);
471 } // namespace chromeos