1e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// found in the LICENSE file.
4e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
5e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chromeos/dbus/bluetooth_gatt_characteristic_service_provider.h"
6e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
7e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/bind.h"
8e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/logging.h"
9e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/memory/weak_ptr.h"
10e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/strings/string_util.h"
11e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/threading/platform_thread.h"
126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
13e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h"
14e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "dbus/exported_object.h"
15e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "dbus/message.h"
16e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "third_party/cros_system_api/dbus/service_constants.h"
17e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochnamespace chromeos {
19e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochnamespace {
20e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kErrorInvalidArgs[] =
21e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    "org.freedesktop.DBus.Error.InvalidArgs";
22e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kErrorPropertyReadOnly[] =
23e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    "org.freedesktop.DBus.Error.PropertyReadOnly";
24e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kErrorFailed[] =
25e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    "org.freedesktop.DBus.Error.Failed";
26e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}  // namespace
27e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
28e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// The BluetoothGattCharacteristicServiceProvider implementation used in
29e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// production.
30e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochclass BluetoothGattCharacteristicServiceProviderImpl
31e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    : public BluetoothGattCharacteristicServiceProvider {
32e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch public:
33e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  BluetoothGattCharacteristicServiceProviderImpl(
34e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      dbus::Bus* bus,
35e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      const dbus::ObjectPath& object_path,
36e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      Delegate* delegate,
37e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      const std::string& uuid,
38e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      const std::vector<std::string>& flags,
39e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      const std::vector<std::string>& permissions,
40e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      const dbus::ObjectPath& service_path)
41e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      : origin_thread_id_(base::PlatformThread::CurrentId()),
42e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        uuid_(uuid),
43e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        bus_(bus),
44e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        delegate_(delegate),
45e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        object_path_(object_path),
46e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        service_path_(service_path),
47e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        weak_ptr_factory_(this) {
48e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    VLOG(1) << "Created Bluetooth GATT characteristic: " << object_path.value()
49e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            << " UUID: " << uuid;
50e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(bus_);
51e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(delegate_);
52e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(!uuid_.empty());
53e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(object_path_.IsValid());
54e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(service_path_.IsValid());
55e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(StartsWithASCII(
56e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        object_path_.value(), service_path_.value() + "/", true));
57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
58e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    exported_object_ = bus_->GetExportedObject(object_path_);
59e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
60e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    exported_object_->ExportMethod(
61e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        dbus::kDBusPropertiesInterface,
62e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        dbus::kDBusPropertiesGet,
63e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::Get,
64e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   weak_ptr_factory_.GetWeakPtr()),
65e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported,
66e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   weak_ptr_factory_.GetWeakPtr()));
67e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
68e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    exported_object_->ExportMethod(
69e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        dbus::kDBusPropertiesInterface,
70e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        dbus::kDBusPropertiesSet,
71e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::Set,
72e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   weak_ptr_factory_.GetWeakPtr()),
73e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported,
74e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   weak_ptr_factory_.GetWeakPtr()));
75e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
76e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    exported_object_->ExportMethod(
77e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        dbus::kDBusPropertiesInterface,
78e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        dbus::kDBusPropertiesGetAll,
79e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::GetAll,
80e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   weak_ptr_factory_.GetWeakPtr()),
81e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported,
82e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   weak_ptr_factory_.GetWeakPtr()));
83e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
84e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
85e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  virtual ~BluetoothGattCharacteristicServiceProviderImpl() {
86e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    VLOG(1) << "Cleaning up Bluetooth GATT characteristic: "
87e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            << object_path_.value();
88e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    bus_->UnregisterExportedObject(object_path_);
89e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // BluetoothGattCharacteristicServiceProvider override.
92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  virtual void SendValueChanged(const std::vector<uint8>& value) OVERRIDE {
93e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    VLOG(2) << "Emitting a PropertiesChanged signal for characteristic value.";
94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::Signal signal(
95e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        dbus::kDBusPropertiesInterface,
96e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        dbus::kDBusPropertiesChangedSignal);
97e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageWriter writer(&signal);
98e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageWriter array_writer(NULL);
99e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageWriter dict_entry_writer(NULL);
100e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageWriter variant_writer(NULL);
101e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
102e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // interface_name
103e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    writer.AppendString(
104e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface);
105e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
106e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // changed_properties
107e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    writer.OpenArray("{sv}", &array_writer);
108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    array_writer.OpenDictEntry(&dict_entry_writer);
109e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dict_entry_writer.AppendString(
110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        bluetooth_gatt_characteristic::kValueProperty);
111e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dict_entry_writer.OpenVariant("ay", &variant_writer);
112e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    variant_writer.AppendArrayOfBytes(value.data(), value.size());
113e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dict_entry_writer.CloseContainer(&variant_writer);
114e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    array_writer.CloseContainer(&dict_entry_writer);
115e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    writer.CloseContainer(&array_writer);
116e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
117e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // invalidated_properties.
118e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    writer.OpenArray("s", &array_writer);
119e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    writer.CloseContainer(&array_writer);
120e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
121e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    exported_object_->SendSignal(&signal);
122e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
123e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
124e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch private:
125e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Returns true if the current thread is on the origin thread.
126e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  bool OnOriginThread() {
127e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return base::PlatformThread::CurrentId() == origin_thread_id_;
128e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
129e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
130e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Called by dbus:: when the Bluetooth daemon fetches a single property of
131e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // the characteristic.
132e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void Get(dbus::MethodCall* method_call,
133e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch           dbus::ExportedObject::ResponseSender response_sender) {
134e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    VLOG(2) << "BluetoothGattCharacteristicServiceProvider::Get: "
135e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            << object_path_.value();
136e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(OnOriginThread());
137e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
138e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageReader reader(method_call);
139e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
140e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    std::string interface_name;
141e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    std::string property_name;
142e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (!reader.PopString(&interface_name) ||
143e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        !reader.PopString(&property_name) ||
144e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        reader.HasMoreData()) {
145e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      scoped_ptr<dbus::ErrorResponse> error_response =
146e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          dbus::ErrorResponse::FromMethodCall(
147e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch              method_call, kErrorInvalidArgs, "Expected 'ss'.");
148e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      response_sender.Run(error_response.PassAs<dbus::Response>());
149e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      return;
150e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
151e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
152e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // Only the GATT characteristic interface is supported.
153e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (interface_name !=
154e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface) {
155e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      scoped_ptr<dbus::ErrorResponse> error_response =
156e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          dbus::ErrorResponse::FromMethodCall(
157e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch              method_call, kErrorInvalidArgs,
158e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch              "No such interface: '" + interface_name + "'.");
159e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      response_sender.Run(error_response.PassAs<dbus::Response>());
160e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      return;
161e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
162e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
163e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // If getting the "Value" property, obtain the value from the delegate.
164e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (property_name == bluetooth_gatt_characteristic::kValueProperty) {
165e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      DCHECK(delegate_);
166e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      delegate_->GetCharacteristicValue(
167e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnGet,
168e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                     weak_ptr_factory_.GetWeakPtr(),
169e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                     method_call, response_sender),
170e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure,
171e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                     weak_ptr_factory_.GetWeakPtr(),
172e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                     method_call, response_sender));
173e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      return;
174e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
175e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
176e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    scoped_ptr<dbus::Response> response =
177e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        dbus::Response::FromMethodCall(method_call);
178e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageWriter writer(response.get());
179e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageWriter variant_writer(NULL);
180e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
181e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // TODO(armansito): Process the "Flags" and "Permissions" properties below.
182e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (property_name == bluetooth_gatt_characteristic::kUUIDProperty) {
183e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      writer.OpenVariant("s", &variant_writer);
184e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      variant_writer.AppendString(uuid_);
185e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      writer.CloseContainer(&variant_writer);
186e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    } else if (property_name ==
187e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch               bluetooth_gatt_characteristic::kServiceProperty) {
188e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      writer.OpenVariant("o", &variant_writer);
189e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      variant_writer.AppendObjectPath(service_path_);
190e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      writer.CloseContainer(&variant_writer);
191e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    } else {
192e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      response = dbus::ErrorResponse::FromMethodCall(
193e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          method_call, kErrorInvalidArgs,
194e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          "No such property: '" + property_name + "'.")
195e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          .PassAs<dbus::Response>();
196e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
197e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
198e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    response_sender.Run(response.Pass());
199e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
200e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
201e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Called by dbus:: when the Bluetooth daemon sets a single property of the
202e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // characteristic.
203e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void Set(dbus::MethodCall* method_call,
204e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch           dbus::ExportedObject::ResponseSender response_sender) {
205e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    VLOG(2) << "BluetoothGattCharacteristicServiceProvider::Set: "
206e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            << object_path_.value();
207e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(OnOriginThread());
208e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
209e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageReader reader(method_call);
210e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
211e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    std::string interface_name;
212e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    std::string property_name;
213e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageReader variant_reader(NULL);
214e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (!reader.PopString(&interface_name) ||
215e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        !reader.PopString(&property_name) ||
216e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        !reader.PopVariant(&variant_reader) ||
217e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        reader.HasMoreData()) {
218e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      scoped_ptr<dbus::ErrorResponse> error_response =
219e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          dbus::ErrorResponse::FromMethodCall(
220e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch              method_call, kErrorInvalidArgs, "Expected 'ssv'.");
221e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      response_sender.Run(error_response.PassAs<dbus::Response>());
222e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      return;
223e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
224e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
225e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // Only the GATT characteristic interface is allowed.
226e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (interface_name !=
227e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface) {
228e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      scoped_ptr<dbus::ErrorResponse> error_response =
229e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          dbus::ErrorResponse::FromMethodCall(
230e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch              method_call, kErrorInvalidArgs,
231e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch              "No such interface: '" + interface_name + "'.");
232e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      response_sender.Run(error_response.PassAs<dbus::Response>());
233e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      return;
234e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
235e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
236e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // Only the "Value" property is writeable.
237e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (property_name != bluetooth_gatt_characteristic::kValueProperty) {
238e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      std::string error_name;
239e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      std::string error_message;
240e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      if (property_name == bluetooth_gatt_characteristic::kUUIDProperty ||
241e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          property_name == bluetooth_gatt_characteristic::kServiceProperty) {
242e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        error_name = kErrorPropertyReadOnly;
243e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        error_message = "Read-only property: '" + property_name + "'.";
244e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      } else {
245e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        error_name = kErrorInvalidArgs;
246e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        error_message = "No such property: '" + property_name + "'.";
247e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      }
248e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      scoped_ptr<dbus::ErrorResponse> error_response =
249e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          dbus::ErrorResponse::FromMethodCall(
250e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch              method_call, error_name, error_message);
251e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      response_sender.Run(error_response.PassAs<dbus::Response>());
252e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      return;
253e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
254e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
255e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // Obtain the value.
256e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const uint8* bytes = NULL;
257e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    size_t length = 0;
258e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (!variant_reader.PopArrayOfBytes(&bytes, &length)) {
259e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      scoped_ptr<dbus::ErrorResponse> error_response =
260e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          dbus::ErrorResponse::FromMethodCall(
261e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch              method_call, kErrorInvalidArgs,
262e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch              "Property '" + property_name + "' has type 'ay'.");
263e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      response_sender.Run(error_response.PassAs<dbus::Response>());
264e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      return;
265e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
266e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
267e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // Pass the set request onto the delegate.
268e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    std::vector<uint8> value(bytes, bytes + length);
269e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(delegate_);
270e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    delegate_->SetCharacteristicValue(
271e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        value,
272e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnSet,
273e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   weak_ptr_factory_.GetWeakPtr(),
274e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   method_call, response_sender),
275e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure,
276e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   weak_ptr_factory_.GetWeakPtr(),
277e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   method_call, response_sender));
278e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
279e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
280e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Called by dbus:: when the Bluetooth daemon fetches all properties of the
281e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // characteristic.
282e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void GetAll(dbus::MethodCall* method_call,
283e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch              dbus::ExportedObject::ResponseSender response_sender) {
284e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    VLOG(2) << "BluetoothGattCharacteristicServiceProvider::GetAll: "
285e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            << object_path_.value();
286e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(OnOriginThread());
287e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
288e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageReader reader(method_call);
289e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
290e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    std::string interface_name;
291e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (!reader.PopString(&interface_name) || reader.HasMoreData()) {
292e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      scoped_ptr<dbus::ErrorResponse> error_response =
293e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          dbus::ErrorResponse::FromMethodCall(
294e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch              method_call, kErrorInvalidArgs, "Expected 's'.");
295e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      response_sender.Run(error_response.PassAs<dbus::Response>());
296e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      return;
297e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
298e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
299e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // Only the GATT characteristic interface is supported.
300e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (interface_name !=
301e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface) {
302e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      scoped_ptr<dbus::ErrorResponse> error_response =
303e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          dbus::ErrorResponse::FromMethodCall(
304e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch              method_call, kErrorInvalidArgs,
305e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch              "No such interface: '" + interface_name + "'.");
306e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      response_sender.Run(error_response.PassAs<dbus::Response>());
307e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      return;
308e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
309e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
310e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // Try to obtain the value from the delegate. We will construct the
311e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // response in the success callback.
312e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(delegate_);
313e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    delegate_->GetCharacteristicValue(
314e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnGetAll,
315e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   weak_ptr_factory_.GetWeakPtr(),
316e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   method_call, response_sender),
317e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure,
318e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   weak_ptr_factory_.GetWeakPtr(),
319e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   method_call, response_sender));
320e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
321e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
322e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Called by dbus:: when a method is exported.
323e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void OnExported(const std::string& interface_name,
324e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                  const std::string& method_name,
325e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                  bool success) {
326e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    LOG_IF(WARNING, !success) << "Failed to export "
327e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                              << interface_name << "." << method_name;
328e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
329e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
330e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Called by the Delegate in response to a method to call to get all
331e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // properties, in which the delegate has successfully returned the
332e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // characteristic value.
333e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void OnGetAll(dbus::MethodCall* method_call,
334e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                dbus::ExportedObject::ResponseSender response_sender,
335e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                const std::vector<uint8>& value) {
336e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    VLOG(2) << "Characteristic value obtained from delegate. Responding to "
337e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            << "GetAll.";
338e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
339e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    scoped_ptr<dbus::Response> response =
340e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        dbus::Response::FromMethodCall(method_call);
341e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageWriter writer(response.get());
342e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageWriter array_writer(NULL);
343e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageWriter dict_entry_writer(NULL);
344e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageWriter variant_writer(NULL);
345e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
346e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    writer.OpenArray("{sv}", &array_writer);
347e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
348e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    array_writer.OpenDictEntry(&dict_entry_writer);
349e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dict_entry_writer.AppendString(
350e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        bluetooth_gatt_characteristic::kUUIDProperty);
351e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dict_entry_writer.AppendVariantOfString(uuid_);
352e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    array_writer.CloseContainer(&dict_entry_writer);
353e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
354e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    array_writer.OpenDictEntry(&dict_entry_writer);
355e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dict_entry_writer.AppendString(
356e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        bluetooth_gatt_characteristic::kServiceProperty);
357e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dict_entry_writer.AppendVariantOfObjectPath(service_path_);
358e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    array_writer.CloseContainer(&dict_entry_writer);
359e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
360e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    array_writer.OpenDictEntry(&dict_entry_writer);
361e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dict_entry_writer.AppendString(
362e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        bluetooth_gatt_characteristic::kValueProperty);
363e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dict_entry_writer.OpenVariant("ay", &variant_writer);
364e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    variant_writer.AppendArrayOfBytes(value.data(), value.size());
365e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dict_entry_writer.CloseContainer(&variant_writer);
366e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    array_writer.CloseContainer(&dict_entry_writer);
367e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
368e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // TODO(armansito): Process Flags & Permissions properties.
369e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
370e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    writer.CloseContainer(&array_writer);
371e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
372e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    response_sender.Run(response.Pass());
373e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
374e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
375e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Called by the Delegate in response to a successful method call to get the
376e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // characteristic value.
377e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void OnGet(dbus::MethodCall* method_call,
378e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch             dbus::ExportedObject::ResponseSender response_sender,
379e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch             const std::vector<uint8>& value) {
380e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    VLOG(2) << "Returning characteristic value obtained from delegate.";
381e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    scoped_ptr<dbus::Response> response =
382e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        dbus::Response::FromMethodCall(method_call);
383e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageWriter writer(response.get());
384e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageWriter variant_writer(NULL);
385e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
386e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    writer.OpenVariant("ay", &variant_writer);
387e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    variant_writer.AppendArrayOfBytes(value.data(), value.size());
388e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    writer.CloseContainer(&variant_writer);
389e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
390e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    response_sender.Run(response.Pass());
391e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
392e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
393e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Called by the Delegate in response to a successful method call to set the
394e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // characteristic value.
395e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void OnSet(dbus::MethodCall* method_call,
396e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch             dbus::ExportedObject::ResponseSender response_sender) {
397e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    VLOG(2) << "Successfully set characteristic value. Return success.";
398e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    response_sender.Run(dbus::Response::FromMethodCall(method_call));
399e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
400e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
401e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Called by the Delegate in response to a failed method call to get or set
402e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // the characteristic value.
403e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void OnFailure(dbus::MethodCall* method_call,
404e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                 dbus::ExportedObject::ResponseSender response_sender) {
405e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    VLOG(2) << "Failed to get/set characteristic value. Report error.";
406e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    scoped_ptr<dbus::ErrorResponse> error_response =
407e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        dbus::ErrorResponse::FromMethodCall(
408e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            method_call, kErrorFailed,
409e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            "Failed to get/set characteristic value.");
410e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    response_sender.Run(error_response.PassAs<dbus::Response>());
411e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
412e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
413e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Origin thread (i.e. the UI thread in production).
414e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  base::PlatformThreadId origin_thread_id_;
415e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
416e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // 128-bit characteristic UUID of this object.
417e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  std::string uuid_;
418e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
419e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // D-Bus bus object is exported on, not owned by this object and must
420e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // outlive it.
421e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  dbus::Bus* bus_;
422e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
423e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Incoming methods to get and set the "Value" property are passed on to the
424e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // delegate and callbacks passed to generate a reply. |delegate_| is generally
425e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // the object that owns this one and must outlive it.
426e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  Delegate* delegate_;
427e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
428e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // D-Bus object path of object we are exporting, kept so we can unregister
429e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // again in our destructor.
430e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  dbus::ObjectPath object_path_;
431e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
432e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Object path of the GATT service that the exported characteristic belongs
433e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // to.
434e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  dbus::ObjectPath service_path_;
435e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
436e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // D-Bus object we are exporting, owned by this object.
437e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  scoped_refptr<dbus::ExportedObject> exported_object_;
438e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
439e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Weak pointer factory for generating 'this' pointers that might live longer
440e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // than we do.
441e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Note: This should remain the last member so it'll be destroyed and
442e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // invalidate its weak pointers before any other members are destroyed.
443e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  base::WeakPtrFactory<BluetoothGattCharacteristicServiceProviderImpl>
444e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      weak_ptr_factory_;
445e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
446e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DISALLOW_COPY_AND_ASSIGN(BluetoothGattCharacteristicServiceProviderImpl);
447e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch};
448e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
449e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBluetoothGattCharacteristicServiceProvider::
450e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    BluetoothGattCharacteristicServiceProvider() {
451e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
452e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
453e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBluetoothGattCharacteristicServiceProvider::
454e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    ~BluetoothGattCharacteristicServiceProvider() {
455e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
456e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
457e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// static
458e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBluetoothGattCharacteristicServiceProvider*
459e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBluetoothGattCharacteristicServiceProvider::Create(
460e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      dbus::Bus* bus,
461e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      const dbus::ObjectPath& object_path,
462e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      Delegate* delegate,
463e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      const std::string& uuid,
464e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      const std::vector<std::string>& flags,
465e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      const std::vector<std::string>& permissions,
466e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      const dbus::ObjectPath& service_path) {
4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) {
468e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return new BluetoothGattCharacteristicServiceProviderImpl(
469e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        bus, object_path, delegate, uuid, flags, permissions, service_path);
470e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
471e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return new FakeBluetoothGattCharacteristicServiceProvider(
472e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      object_path, delegate, uuid, flags, permissions, service_path);
473e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
474e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
475e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}  // namespace chromeos
476