Chromium Code Reviews| Index: components/arc/bluetooth/bluetooth_struct_traits.cc |
| diff --git a/components/arc/bluetooth/bluetooth_struct_traits.cc b/components/arc/bluetooth/bluetooth_struct_traits.cc |
| index 66691935a6e4cc67bc00e4436a687ed92f2960c1..7b8024f900e03bd4843c119c9f59a4f303066244 100644 |
| --- a/components/arc/bluetooth/bluetooth_struct_traits.cc |
| +++ b/components/arc/bluetooth/bluetooth_struct_traits.cc |
| @@ -8,10 +8,13 @@ |
| #include <vector> |
| #include "base/strings/string_number_conversions.h" |
| +#include "base/strings/stringprintf.h" |
| +#include "device/bluetooth/bluetooth_advertisement.h" |
| #include "device/bluetooth/bluetooth_uuid.h" |
| namespace { |
| +// BluetoothUUID helpers. |
| constexpr size_t kUUIDSize = 16; |
| bool IsNonHex(char c) { |
| @@ -26,6 +29,47 @@ std::string StripNonHex(const std::string& str) { |
| return result; |
| } |
| +// BluetoothAdvertisement helpers. |
| +struct AdvertisementEntry { |
| + virtual void AddTo(device::BluetoothAdvertisement::Data* data) {} |
| +}; |
| + |
| +struct ServiceUUIDEntry : public AdvertisementEntry { |
| + std::vector<device::BluetoothUUID> service_uuids_; |
|
Luis Héctor Chávez
2016/09/12 19:53:00
struct data members don't have trailing underscore
|
| + |
| + void AddTo(device::BluetoothAdvertisement::Data* data) override { |
| + std::vector<std::string> string_uuids; |
|
Luis Héctor Chávez
2016/09/12 19:53:00
Can you avoid one copy (in L45) by declaring |stri
|
| + for (const auto& uuid : service_uuids_) { |
| + string_uuids.emplace_back(uuid.value()); |
| + } |
| + data->set_service_uuids( |
| + base::MakeUnique<std::vector<std::string>>(string_uuids)); |
| + } |
| +}; |
| + |
| +struct ServiceDataEntry : public AdvertisementEntry { |
| + uint16_t service_uuid_; |
| + std::vector<uint8_t> service_data_; |
| + |
| + void AddTo(device::BluetoothAdvertisement::Data* data) override { |
| + std::string string_uuid = base::StringPrintf("%04x", service_uuid_); |
| + data->set_service_data( |
| + base::WrapUnique(new std::map<std::string, std::vector<uint8_t>>{ |
| + {string_uuid, service_data_}})); |
| + } |
| +}; |
| + |
| +struct ManufacturerDataEntry : public AdvertisementEntry { |
| + uint16_t company_id_code_; |
| + std::vector<uint8_t> blob_; |
| + |
| + void AddTo(device::BluetoothAdvertisement::Data* data) override { |
| + data->set_manufacturer_data( |
| + base::WrapUnique(new std::map<uint16_t, std::vector<uint8_t>>{ |
| + {company_id_code_, blob_}})); |
| + } |
| +}; |
| + |
| } // namespace |
| namespace mojo { |
| @@ -67,4 +111,115 @@ bool StructTraits<arc::mojom::BluetoothUUIDDataView, |
| return true; |
| } |
| +template <> |
| +struct EnumTraits<arc::mojom::BluetoothAdvertisementType, |
| + device::BluetoothAdvertisement::AdvertisementType> { |
| + static bool FromMojom( |
| + arc::mojom::BluetoothAdvertisementType mojom_type, |
| + device::BluetoothAdvertisement::AdvertisementType* type) { |
| + switch (mojom_type) { |
| + case arc::mojom::BluetoothAdvertisementType::ADV_TYPE_CONNECTABLE: |
| + case arc::mojom::BluetoothAdvertisementType::ADV_TYPE_SCANNABLE: |
| + *type = device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_PERIPHERAL; |
| + break; |
| + case arc::mojom::BluetoothAdvertisementType::ADV_TYPE_NON_CONNECTABLE: |
| + *type = device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_BROADCAST; |
| + break; |
| + default: |
|
Luis Héctor Chávez
2016/09/12 19:53:00
since |mojom_type| is a strongly-typed enum and we
|
| + NOTREACHED() << "Invalid type: " << static_cast<uint32_t>(mojom_type); |
| + return false; |
| + } |
| + return true; |
| + } |
| +}; |
| + |
| +template <> |
| +struct StructTraits<arc::mojom::BluetoothServiceDataDataView, |
| + ServiceDataEntry> { |
| + static bool Read(arc::mojom::BluetoothServiceDataDataView data, |
| + ServiceDataEntry* output) { |
| + output->service_uuid_ = data.uuid_16bit(); |
| + data.ReadData(&output->service_data_); |
| + return true; |
| + } |
| +}; |
| + |
| +template <> |
| +struct UnionTraits<arc::mojom::BluetoothAdvertisingDataDataView, |
| + std::unique_ptr<AdvertisementEntry>> { |
| + static bool Read(arc::mojom::BluetoothAdvertisingDataDataView data, |
| + std::unique_ptr<AdvertisementEntry>* output) { |
| + switch (data.tag()) { |
| + case arc::mojom::BluetoothAdvertisingDataDataView::Tag::SERVICE_UUIDS: { |
| + std::unique_ptr<ServiceUUIDEntry> service_uuids = |
| + base::MakeUnique<ServiceUUIDEntry>(); |
| + data.ReadServiceUuids(&service_uuids->service_uuids_); |
| + *output = std::move(service_uuids); |
| + break; |
| + } |
| + case arc::mojom::BluetoothAdvertisingDataDataView::Tag::SERVICE_DATA: { |
| + std::unique_ptr<ServiceDataEntry> service_data = |
| + base::MakeUnique<ServiceDataEntry>(); |
| + data.ReadServiceData(service_data.get()); |
| + *output = std::move(service_data); |
| + break; |
| + } |
| + case arc::mojom::BluetoothAdvertisingDataDataView::Tag:: |
| + MANUFACTURER_DATA: { |
| + std::unique_ptr<ManufacturerDataEntry> manufacturer_data = |
| + base::MakeUnique<ManufacturerDataEntry>(); |
| + // We get manufacturer data as a big blob. The first two bytes |
| + // should be a company identifier code and the rest is manufacturer- |
| + // specific. |
| + std::vector<uint8_t> blob; |
| + data.ReadManufacturerData(&blob); |
| + if (blob.size() < sizeof(uint16_t)) { |
| + LOG(WARNING) << "Advertisement had malformed manufacturer data"; |
| + return false; |
| + } |
| + |
| + // The company identifier code is in little-endian. |
| + uint16_t company_id_code = blob[1] << 8 | blob[0]; |
|
Luis Héctor Chávez
2016/09/12 19:53:00
I've seen this snippet lots of times. Can you plea
Eric Caruso
2016/09/13 23:36:48
Where else does this occur in the Chrome codebase
Luis Héctor Chávez
2016/09/16 00:39:53
You're right, I was probably remembering the Andro
|
| + blob.erase(blob.begin(), blob.begin() + sizeof(uint16_t)); |
| + manufacturer_data->company_id_code_ = company_id_code; |
| + manufacturer_data->blob_ = blob; |
|
Luis Héctor Chávez
2016/09/12 19:53:00
Can you avoid a copy by using std::swap?
Eric Caruso
2016/09/13 23:36:48
operator=(std::vector<uint8_t>&&) should also work
|
| + *output = std::move(manufacturer_data); |
| + break; |
| + } |
| + default: { |
| + LOG(WARNING) << "Bluetooth advertising data case not implemented"; |
| + // Default AdvertisementEntry does nothing when added to the |
| + // device::BluetoothAdvertisement::AdvertisementData, so data we |
| + // don't know how to handle yet will be dropped but won't cause a |
| + // failure to deserialize. |
| + *output = base::MakeUnique<AdvertisementEntry>(); |
| + break; |
| + } |
| + } |
| + return true; |
| + } |
| +}; |
| + |
| +// static |
| +bool StructTraits<arc::mojom::BluetoothAdvertisementDataView, |
| + std::unique_ptr<device::BluetoothAdvertisement::Data>>:: |
| + Read(arc::mojom::BluetoothAdvertisementDataView advertisement, |
| + std::unique_ptr<device::BluetoothAdvertisement::Data>* output) { |
| + device::BluetoothAdvertisement::AdvertisementType adv_type; |
| + if (!advertisement.ReadType(&adv_type)) |
| + return false; |
| + auto data = base::MakeUnique<device::BluetoothAdvertisement::Data>(adv_type); |
| + |
| + std::vector<std::unique_ptr<AdvertisementEntry>> adv_entries; |
| + if (!advertisement.ReadData(&adv_entries)) |
| + return false; |
| + for (const auto& adv_entry : adv_entries) |
| + adv_entry->AddTo(data.get()); |
| + |
| + data->set_include_tx_power(advertisement.include_tx_power()); |
| + |
| + *output = std::move(data); |
| + return true; |
| +} |
| + |
| } // namespace mojo |