Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/arc/bluetooth/bluetooth_struct_traits.h" | 5 #include "components/arc/bluetooth/bluetooth_struct_traits.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| 11 #include "base/strings/stringprintf.h" | |
| 12 #include "device/bluetooth/bluetooth_advertisement.h" | |
| 11 #include "device/bluetooth/bluetooth_uuid.h" | 13 #include "device/bluetooth/bluetooth_uuid.h" |
| 12 | 14 |
| 13 namespace { | 15 namespace { |
| 14 | 16 |
| 17 // BluetoothUUID helpers. | |
| 15 constexpr size_t kUUIDSize = 16; | 18 constexpr size_t kUUIDSize = 16; |
| 16 | 19 |
| 17 bool IsNonHex(char c) { | 20 bool IsNonHex(char c) { |
| 18 return !isxdigit(c); | 21 return !isxdigit(c); |
| 19 } | 22 } |
| 20 | 23 |
| 21 std::string StripNonHex(const std::string& str) { | 24 std::string StripNonHex(const std::string& str) { |
| 22 std::string result = str; | 25 std::string result = str; |
| 23 result.erase(std::remove_if(result.begin(), result.end(), IsNonHex), | 26 result.erase(std::remove_if(result.begin(), result.end(), IsNonHex), |
| 24 result.end()); | 27 result.end()); |
| 25 | 28 |
| 26 return result; | 29 return result; |
| 27 } | 30 } |
| 28 | 31 |
| 32 // BluetoothAdvertisement helpers. | |
| 33 struct AdvertisementEntry { | |
| 34 virtual void AddTo(device::BluetoothAdvertisement::Data* data) {} | |
| 35 }; | |
| 36 | |
| 37 struct ServiceUUIDEntry : public AdvertisementEntry { | |
| 38 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
| |
| 39 | |
| 40 void AddTo(device::BluetoothAdvertisement::Data* data) override { | |
| 41 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
| |
| 42 for (const auto& uuid : service_uuids_) { | |
| 43 string_uuids.emplace_back(uuid.value()); | |
| 44 } | |
| 45 data->set_service_uuids( | |
| 46 base::MakeUnique<std::vector<std::string>>(string_uuids)); | |
| 47 } | |
| 48 }; | |
| 49 | |
| 50 struct ServiceDataEntry : public AdvertisementEntry { | |
| 51 uint16_t service_uuid_; | |
| 52 std::vector<uint8_t> service_data_; | |
| 53 | |
| 54 void AddTo(device::BluetoothAdvertisement::Data* data) override { | |
| 55 std::string string_uuid = base::StringPrintf("%04x", service_uuid_); | |
| 56 data->set_service_data( | |
| 57 base::WrapUnique(new std::map<std::string, std::vector<uint8_t>>{ | |
| 58 {string_uuid, service_data_}})); | |
| 59 } | |
| 60 }; | |
| 61 | |
| 62 struct ManufacturerDataEntry : public AdvertisementEntry { | |
| 63 uint16_t company_id_code_; | |
| 64 std::vector<uint8_t> blob_; | |
| 65 | |
| 66 void AddTo(device::BluetoothAdvertisement::Data* data) override { | |
| 67 data->set_manufacturer_data( | |
| 68 base::WrapUnique(new std::map<uint16_t, std::vector<uint8_t>>{ | |
| 69 {company_id_code_, blob_}})); | |
| 70 } | |
| 71 }; | |
| 72 | |
| 29 } // namespace | 73 } // namespace |
| 30 | 74 |
| 31 namespace mojo { | 75 namespace mojo { |
| 32 | 76 |
| 33 // static | 77 // static |
| 34 std::vector<uint8_t> | 78 std::vector<uint8_t> |
| 35 StructTraits<arc::mojom::BluetoothUUIDDataView, device::BluetoothUUID>::uuid( | 79 StructTraits<arc::mojom::BluetoothUUIDDataView, device::BluetoothUUID>::uuid( |
| 36 const device::BluetoothUUID& input) { | 80 const device::BluetoothUUID& input) { |
| 37 std::string uuid_str = StripNonHex(input.canonical_value()); | 81 std::string uuid_str = StripNonHex(input.canonical_value()); |
| 38 | 82 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 60 for (auto pos : uuid_dash_pos) | 104 for (auto pos : uuid_dash_pos) |
| 61 uuid_str = uuid_str.insert(pos, "-"); | 105 uuid_str = uuid_str.insert(pos, "-"); |
| 62 | 106 |
| 63 device::BluetoothUUID result(uuid_str); | 107 device::BluetoothUUID result(uuid_str); |
| 64 | 108 |
| 65 DCHECK(result.IsValid()); | 109 DCHECK(result.IsValid()); |
| 66 *output = result; | 110 *output = result; |
| 67 return true; | 111 return true; |
| 68 } | 112 } |
| 69 | 113 |
| 114 template <> | |
| 115 struct EnumTraits<arc::mojom::BluetoothAdvertisementType, | |
| 116 device::BluetoothAdvertisement::AdvertisementType> { | |
| 117 static bool FromMojom( | |
| 118 arc::mojom::BluetoothAdvertisementType mojom_type, | |
| 119 device::BluetoothAdvertisement::AdvertisementType* type) { | |
| 120 switch (mojom_type) { | |
| 121 case arc::mojom::BluetoothAdvertisementType::ADV_TYPE_CONNECTABLE: | |
| 122 case arc::mojom::BluetoothAdvertisementType::ADV_TYPE_SCANNABLE: | |
| 123 *type = device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_PERIPHERAL; | |
| 124 break; | |
| 125 case arc::mojom::BluetoothAdvertisementType::ADV_TYPE_NON_CONNECTABLE: | |
| 126 *type = device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_BROADCAST; | |
| 127 break; | |
| 128 default: | |
|
Luis Héctor Chávez
2016/09/12 19:53:00
since |mojom_type| is a strongly-typed enum and we
| |
| 129 NOTREACHED() << "Invalid type: " << static_cast<uint32_t>(mojom_type); | |
| 130 return false; | |
| 131 } | |
| 132 return true; | |
| 133 } | |
| 134 }; | |
| 135 | |
| 136 template <> | |
| 137 struct StructTraits<arc::mojom::BluetoothServiceDataDataView, | |
| 138 ServiceDataEntry> { | |
| 139 static bool Read(arc::mojom::BluetoothServiceDataDataView data, | |
| 140 ServiceDataEntry* output) { | |
| 141 output->service_uuid_ = data.uuid_16bit(); | |
| 142 data.ReadData(&output->service_data_); | |
| 143 return true; | |
| 144 } | |
| 145 }; | |
| 146 | |
| 147 template <> | |
| 148 struct UnionTraits<arc::mojom::BluetoothAdvertisingDataDataView, | |
| 149 std::unique_ptr<AdvertisementEntry>> { | |
| 150 static bool Read(arc::mojom::BluetoothAdvertisingDataDataView data, | |
| 151 std::unique_ptr<AdvertisementEntry>* output) { | |
| 152 switch (data.tag()) { | |
| 153 case arc::mojom::BluetoothAdvertisingDataDataView::Tag::SERVICE_UUIDS: { | |
| 154 std::unique_ptr<ServiceUUIDEntry> service_uuids = | |
| 155 base::MakeUnique<ServiceUUIDEntry>(); | |
| 156 data.ReadServiceUuids(&service_uuids->service_uuids_); | |
| 157 *output = std::move(service_uuids); | |
| 158 break; | |
| 159 } | |
| 160 case arc::mojom::BluetoothAdvertisingDataDataView::Tag::SERVICE_DATA: { | |
| 161 std::unique_ptr<ServiceDataEntry> service_data = | |
| 162 base::MakeUnique<ServiceDataEntry>(); | |
| 163 data.ReadServiceData(service_data.get()); | |
| 164 *output = std::move(service_data); | |
| 165 break; | |
| 166 } | |
| 167 case arc::mojom::BluetoothAdvertisingDataDataView::Tag:: | |
| 168 MANUFACTURER_DATA: { | |
| 169 std::unique_ptr<ManufacturerDataEntry> manufacturer_data = | |
| 170 base::MakeUnique<ManufacturerDataEntry>(); | |
| 171 // We get manufacturer data as a big blob. The first two bytes | |
| 172 // should be a company identifier code and the rest is manufacturer- | |
| 173 // specific. | |
| 174 std::vector<uint8_t> blob; | |
| 175 data.ReadManufacturerData(&blob); | |
| 176 if (blob.size() < sizeof(uint16_t)) { | |
| 177 LOG(WARNING) << "Advertisement had malformed manufacturer data"; | |
| 178 return false; | |
| 179 } | |
| 180 | |
| 181 // The company identifier code is in little-endian. | |
| 182 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
| |
| 183 blob.erase(blob.begin(), blob.begin() + sizeof(uint16_t)); | |
| 184 manufacturer_data->company_id_code_ = company_id_code; | |
| 185 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
| |
| 186 *output = std::move(manufacturer_data); | |
| 187 break; | |
| 188 } | |
| 189 default: { | |
| 190 LOG(WARNING) << "Bluetooth advertising data case not implemented"; | |
| 191 // Default AdvertisementEntry does nothing when added to the | |
| 192 // device::BluetoothAdvertisement::AdvertisementData, so data we | |
| 193 // don't know how to handle yet will be dropped but won't cause a | |
| 194 // failure to deserialize. | |
| 195 *output = base::MakeUnique<AdvertisementEntry>(); | |
| 196 break; | |
| 197 } | |
| 198 } | |
| 199 return true; | |
| 200 } | |
| 201 }; | |
| 202 | |
| 203 // static | |
| 204 bool StructTraits<arc::mojom::BluetoothAdvertisementDataView, | |
| 205 std::unique_ptr<device::BluetoothAdvertisement::Data>>:: | |
| 206 Read(arc::mojom::BluetoothAdvertisementDataView advertisement, | |
| 207 std::unique_ptr<device::BluetoothAdvertisement::Data>* output) { | |
| 208 device::BluetoothAdvertisement::AdvertisementType adv_type; | |
| 209 if (!advertisement.ReadType(&adv_type)) | |
| 210 return false; | |
| 211 auto data = base::MakeUnique<device::BluetoothAdvertisement::Data>(adv_type); | |
| 212 | |
| 213 std::vector<std::unique_ptr<AdvertisementEntry>> adv_entries; | |
| 214 if (!advertisement.ReadData(&adv_entries)) | |
| 215 return false; | |
| 216 for (const auto& adv_entry : adv_entries) | |
| 217 adv_entry->AddTo(data.get()); | |
| 218 | |
| 219 data->set_include_tx_power(advertisement.include_tx_power()); | |
| 220 | |
| 221 *output = std::move(data); | |
| 222 return true; | |
| 223 } | |
| 224 | |
| 70 } // namespace mojo | 225 } // namespace mojo |
| OLD | NEW |