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 85c5ae2ba6872c5c247c2694ef97c071632446af..716feca08fddc90270acedb9fa6c281d2d62fedf 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,59 @@ std::string StripNonHex(const std::string& str) { |
return result; |
} |
+// BluetoothAdvertisement helpers. |
+struct AdvertisementEntry { |
+ virtual ~AdvertisementEntry() {} |
Eric Caruso
2016/10/06 19:00:50
This line and the other virtual destructors are th
Luis Héctor Chávez
2016/10/06 19:23:53
The next time you reland something, can you please
|
+ virtual void AddTo(device::BluetoothAdvertisement::Data* data) {} |
+}; |
+ |
+struct ServiceUUIDEntry : public AdvertisementEntry { |
+ std::vector<device::BluetoothUUID> service_uuids; |
+ |
+ ~ServiceUUIDEntry() override {} |
+ |
+ void AddTo(device::BluetoothAdvertisement::Data* data) override { |
+ auto string_uuids = base::MakeUnique<std::vector<std::string>>(); |
+ for (const auto& uuid : service_uuids) { |
+ string_uuids->emplace_back(uuid.value()); |
+ } |
+ data->set_service_uuids(std::move(string_uuids)); |
+ } |
+}; |
+ |
+struct ServiceDataEntry : public AdvertisementEntry { |
+ uint16_t service_uuid; |
+ std::vector<uint8_t> service_data; |
+ |
+ ~ServiceDataEntry() override {} |
+ |
+ 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; |
+ |
+ ~ManufacturerDataEntry() override {} |
+ |
+ 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}})); |
+ } |
+}; |
+ |
+uint16_t ExtractCompanyIdentifierCode(std::vector<uint8_t>* blob) { |
+ // The company identifier code is in little-endian. |
+ uint16_t company_id_code = (*blob)[1] << 8 | (*blob)[0]; |
+ blob->erase(blob->begin(), blob->begin() + sizeof(uint16_t)); |
+ return company_id_code; |
+} |
+ |
} // namespace |
namespace mojo { |
@@ -70,4 +126,113 @@ 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; |
+ return true; |
+ case arc::mojom::BluetoothAdvertisementType::ADV_TYPE_NON_CONNECTABLE: |
+ *type = device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_BROADCAST; |
+ return true; |
+ } |
+ NOTREACHED() << "Invalid type: " << static_cast<uint32_t>(mojom_type); |
+ return false; |
+ } |
+}; |
+ |
+template <> |
+struct StructTraits<arc::mojom::BluetoothServiceDataDataView, |
+ ServiceDataEntry> { |
+ static bool Read(arc::mojom::BluetoothServiceDataDataView data, |
+ ServiceDataEntry* output) { |
+ output->service_uuid = data.uuid_16bit(); |
+ return data.ReadData(&output->service_data); |
+ } |
+}; |
+ |
+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>(); |
+ if (!data.ReadServiceUuids(&service_uuids->service_uuids)) |
+ return false; |
+ *output = std::move(service_uuids); |
+ break; |
+ } |
+ case arc::mojom::BluetoothAdvertisingDataDataView::Tag::SERVICE_DATA: { |
+ std::unique_ptr<ServiceDataEntry> service_data = |
+ base::MakeUnique<ServiceDataEntry>(); |
+ if (!data.ReadServiceData(service_data.get())) |
+ return false; |
+ *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; |
+ if (!data.ReadManufacturerData(&blob)) |
+ return false; |
+ if (blob.size() < sizeof(uint16_t)) { |
+ LOG(WARNING) << "Advertisement had malformed manufacturer data"; |
+ return false; |
+ } |
+ |
+ manufacturer_data->company_id_code = |
+ ExtractCompanyIdentifierCode(&blob); |
+ manufacturer_data->blob = std::move(blob); |
+ *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 |