OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 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 "device/bluetooth/dbus/bluetooth_gatt_service_service_provider_impl.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/logging.h" |
| 9 #include "third_party/cros_system_api/dbus/service_constants.h" |
| 10 |
| 11 namespace bluez { |
| 12 |
| 13 namespace { |
| 14 |
| 15 const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs"; |
| 16 const char kErrorPropertyReadOnly[] = |
| 17 "org.freedesktop.DBus.Error.PropertyReadOnly"; |
| 18 |
| 19 } // namespace |
| 20 |
| 21 BluetoothGattServiceServiceProviderImpl:: |
| 22 BluetoothGattServiceServiceProviderImpl( |
| 23 dbus::Bus* bus, |
| 24 const dbus::ObjectPath& object_path, |
| 25 const std::string& uuid, |
| 26 const std::vector<dbus::ObjectPath>& includes) |
| 27 : origin_thread_id_(base::PlatformThread::CurrentId()), |
| 28 uuid_(uuid), |
| 29 includes_(includes), |
| 30 bus_(bus), |
| 31 object_path_(object_path), |
| 32 weak_ptr_factory_(this) { |
| 33 VLOG(1) << "Creating Bluetooth GATT service: " << object_path_.value() |
| 34 << " UUID: " << uuid; |
| 35 DCHECK(!uuid_.empty()); |
| 36 DCHECK(object_path_.IsValid()); |
| 37 DCHECK(bus_); |
| 38 |
| 39 exported_object_ = bus_->GetExportedObject(object_path_); |
| 40 |
| 41 exported_object_->ExportMethod( |
| 42 dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet, |
| 43 base::Bind(&BluetoothGattServiceServiceProviderImpl::Get, |
| 44 weak_ptr_factory_.GetWeakPtr()), |
| 45 base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported, |
| 46 weak_ptr_factory_.GetWeakPtr())); |
| 47 |
| 48 exported_object_->ExportMethod( |
| 49 dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesSet, |
| 50 base::Bind(&BluetoothGattServiceServiceProviderImpl::Set, |
| 51 weak_ptr_factory_.GetWeakPtr()), |
| 52 base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported, |
| 53 weak_ptr_factory_.GetWeakPtr())); |
| 54 |
| 55 exported_object_->ExportMethod( |
| 56 dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll, |
| 57 base::Bind(&BluetoothGattServiceServiceProviderImpl::GetAll, |
| 58 weak_ptr_factory_.GetWeakPtr()), |
| 59 base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported, |
| 60 weak_ptr_factory_.GetWeakPtr())); |
| 61 } |
| 62 |
| 63 BluetoothGattServiceServiceProviderImpl:: |
| 64 ~BluetoothGattServiceServiceProviderImpl() { |
| 65 VLOG(1) << "Cleaning up Bluetooth GATT service: " << object_path_.value(); |
| 66 if (bus_) |
| 67 bus_->UnregisterExportedObject(object_path_); |
| 68 } |
| 69 |
| 70 BluetoothGattServiceServiceProviderImpl:: |
| 71 BluetoothGattServiceServiceProviderImpl(const dbus::ObjectPath& object_path, |
| 72 const std::string& uuid) |
| 73 : origin_thread_id_(base::PlatformThread::CurrentId()), |
| 74 uuid_(uuid), |
| 75 bus_(nullptr), |
| 76 object_path_(object_path), |
| 77 weak_ptr_factory_(this) {} |
| 78 |
| 79 bool BluetoothGattServiceServiceProviderImpl::OnOriginThread() { |
| 80 return base::PlatformThread::CurrentId() == origin_thread_id_; |
| 81 } |
| 82 |
| 83 void BluetoothGattServiceServiceProviderImpl::Get( |
| 84 dbus::MethodCall* method_call, |
| 85 dbus::ExportedObject::ResponseSender response_sender) { |
| 86 VLOG(2) << "BluetoothGattServiceServiceProvider::Get: " |
| 87 << object_path_.value(); |
| 88 DCHECK(OnOriginThread()); |
| 89 |
| 90 dbus::MessageReader reader(method_call); |
| 91 |
| 92 std::string interface_name; |
| 93 std::string property_name; |
| 94 if (!reader.PopString(&interface_name) || !reader.PopString(&property_name) || |
| 95 reader.HasMoreData()) { |
| 96 std::unique_ptr<dbus::ErrorResponse> error_response = |
| 97 dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, |
| 98 "Expected 'ss'."); |
| 99 response_sender.Run(std::move(error_response)); |
| 100 return; |
| 101 } |
| 102 |
| 103 // Only the GATT service interface is allowed. |
| 104 if (interface_name != |
| 105 bluetooth_gatt_service::kBluetoothGattServiceInterface) { |
| 106 std::unique_ptr<dbus::ErrorResponse> error_response = |
| 107 dbus::ErrorResponse::FromMethodCall( |
| 108 method_call, kErrorInvalidArgs, |
| 109 "No such interface: '" + interface_name + "'."); |
| 110 response_sender.Run(std::move(error_response)); |
| 111 return; |
| 112 } |
| 113 |
| 114 // Return error if |property_name| is unknown. |
| 115 if (property_name != bluetooth_gatt_service::kUUIDProperty && |
| 116 property_name != bluetooth_gatt_service::kIncludesProperty) { |
| 117 std::unique_ptr<dbus::ErrorResponse> error_response = |
| 118 dbus::ErrorResponse::FromMethodCall( |
| 119 method_call, kErrorInvalidArgs, |
| 120 "No such property: '" + property_name + "'."); |
| 121 response_sender.Run(std::move(error_response)); |
| 122 return; |
| 123 } |
| 124 |
| 125 std::unique_ptr<dbus::Response> response = |
| 126 dbus::Response::FromMethodCall(method_call); |
| 127 dbus::MessageWriter writer(response.get()); |
| 128 dbus::MessageWriter variant_writer(NULL); |
| 129 |
| 130 if (property_name == bluetooth_gatt_service::kUUIDProperty) { |
| 131 writer.OpenVariant("s", &variant_writer); |
| 132 variant_writer.AppendString(uuid_); |
| 133 writer.CloseContainer(&variant_writer); |
| 134 } else { |
| 135 writer.OpenVariant("ao", &variant_writer); |
| 136 variant_writer.AppendArrayOfObjectPaths(includes_); |
| 137 writer.CloseContainer(&variant_writer); |
| 138 } |
| 139 |
| 140 response_sender.Run(std::move(response)); |
| 141 } |
| 142 |
| 143 void BluetoothGattServiceServiceProviderImpl::Set( |
| 144 dbus::MethodCall* method_call, |
| 145 dbus::ExportedObject::ResponseSender response_sender) { |
| 146 VLOG(2) << "BluetoothGattServiceServiceProvider::Set: " |
| 147 << object_path_.value(); |
| 148 DCHECK(OnOriginThread()); |
| 149 |
| 150 // All of the properties on this interface are read-only, so just return |
| 151 // error. |
| 152 std::unique_ptr<dbus::ErrorResponse> error_response = |
| 153 dbus::ErrorResponse::FromMethodCall(method_call, kErrorPropertyReadOnly, |
| 154 "All properties are read-only."); |
| 155 response_sender.Run(std::move(error_response)); |
| 156 } |
| 157 |
| 158 void BluetoothGattServiceServiceProviderImpl::GetAll( |
| 159 dbus::MethodCall* method_call, |
| 160 dbus::ExportedObject::ResponseSender response_sender) { |
| 161 VLOG(2) << "BluetoothGattServiceServiceProvider::GetAll: " |
| 162 << object_path_.value(); |
| 163 DCHECK(OnOriginThread()); |
| 164 |
| 165 dbus::MessageReader reader(method_call); |
| 166 |
| 167 std::string interface_name; |
| 168 if (!reader.PopString(&interface_name) || reader.HasMoreData()) { |
| 169 std::unique_ptr<dbus::ErrorResponse> error_response = |
| 170 dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, |
| 171 "Expected 's'."); |
| 172 response_sender.Run(std::move(error_response)); |
| 173 return; |
| 174 } |
| 175 |
| 176 // Only the GATT service interface is allowed. |
| 177 if (interface_name != |
| 178 bluetooth_gatt_service::kBluetoothGattServiceInterface) { |
| 179 std::unique_ptr<dbus::ErrorResponse> error_response = |
| 180 dbus::ErrorResponse::FromMethodCall( |
| 181 method_call, kErrorInvalidArgs, |
| 182 "No such interface: '" + interface_name + "'."); |
| 183 response_sender.Run(std::move(error_response)); |
| 184 return; |
| 185 } |
| 186 |
| 187 std::unique_ptr<dbus::Response> response = |
| 188 dbus::Response::FromMethodCall(method_call); |
| 189 dbus::MessageWriter writer(response.get()); |
| 190 WriteProperties(&writer); |
| 191 response_sender.Run(std::move(response)); |
| 192 } |
| 193 |
| 194 void BluetoothGattServiceServiceProviderImpl::WriteProperties( |
| 195 dbus::MessageWriter* writer) { |
| 196 dbus::MessageWriter array_writer(NULL); |
| 197 dbus::MessageWriter dict_entry_writer(NULL); |
| 198 dbus::MessageWriter variant_writer(NULL); |
| 199 |
| 200 writer->OpenArray("{sv}", &array_writer); |
| 201 |
| 202 array_writer.OpenDictEntry(&dict_entry_writer); |
| 203 dict_entry_writer.AppendString(bluetooth_gatt_service::kUUIDProperty); |
| 204 dict_entry_writer.AppendVariantOfString(uuid_); |
| 205 array_writer.CloseContainer(&dict_entry_writer); |
| 206 |
| 207 array_writer.OpenDictEntry(&dict_entry_writer); |
| 208 dict_entry_writer.AppendString(bluetooth_gatt_service::kIncludesProperty); |
| 209 dict_entry_writer.OpenVariant("ao", &variant_writer); |
| 210 variant_writer.AppendArrayOfObjectPaths(includes_); |
| 211 dict_entry_writer.CloseContainer(&variant_writer); |
| 212 array_writer.CloseContainer(&dict_entry_writer); |
| 213 |
| 214 writer->CloseContainer(&array_writer); |
| 215 } |
| 216 |
| 217 void BluetoothGattServiceServiceProviderImpl::OnExported( |
| 218 const std::string& interface_name, |
| 219 const std::string& method_name, |
| 220 bool success) { |
| 221 LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "." |
| 222 << method_name; |
| 223 } |
| 224 |
| 225 const dbus::ObjectPath& BluetoothGattServiceServiceProviderImpl::object_path() |
| 226 const { |
| 227 return object_path_; |
| 228 } |
| 229 |
| 230 } // namespace bluez |
OLD | NEW |