bluetooth: Expose service data from BlueZ

BlueZ exposed Bluetooth device's ServiceData as a{sv} property[1]
where the dict value variant is an array of byte.

This CL exposes that to upper layer by
- Add support to map<string, vector<uint8_t>> in dbus::Property
- Add new service_data property in BluetoothDeviceClient
- Implement GetServiceDataUUIDs() and GetServiceDataForUUID()
  in BluetoothDeviceBlueZ
- Fix misc style issues in original code to make linter happy

[1] http://git.kernel.org/cgit/bluetooth/bluez.git/tree/src/device.c#n2551

BUG=618442,653310,b:28670943
TEST=Manually tested.

Review-Url: https://codereview.chromium.org/2369423003
Cr-Commit-Position: refs/heads/master@{#423434}


CrOS-Libchrome-Original-Commit: 0dd82b1c975662a10f34a53b3df56d98526b36d0
diff --git a/dbus/property.cc b/dbus/property.cc
index faca4a0..0ac65ef 100644
--- a/dbus/property.cc
+++ b/dbus/property.cc
@@ -6,6 +6,8 @@
 
 #include <stddef.h>
 
+#include <memory>
+
 #include "base/bind.h"
 #include "base/logging.h"
 
@@ -659,6 +661,70 @@
   writer->CloseContainer(&variant_writer);
 }
 
+//
+// Property<std::map<std::string, std::vector<uint8_t>>>
+// specialization.
+//
+
+template <>
+bool Property<std::unordered_map<std::string, std::vector<uint8_t>>>::
+    PopValueFromReader(MessageReader* reader) {
+  MessageReader variant_reader(nullptr);
+  MessageReader dict_reader(nullptr);
+  if (!reader->PopVariant(&variant_reader) ||
+      !variant_reader.PopArray(&dict_reader))
+    return false;
+
+  value_.clear();
+  while (dict_reader.HasMoreData()) {
+    MessageReader entry_reader(nullptr);
+    if (!dict_reader.PopDictEntry(&entry_reader))
+      return false;
+
+    std::string key;
+    MessageReader value_varient_reader(nullptr);
+    if (!entry_reader.PopString(&key) ||
+        !entry_reader.PopVariant(&value_varient_reader))
+      return false;
+
+    const uint8_t* bytes = nullptr;
+    size_t length = 0;
+    if (!value_varient_reader.PopArrayOfBytes(&bytes, &length))
+      return false;
+
+    value_[key].assign(bytes, bytes + length);
+  }
+  return true;
+}
+
+template <>
+void Property<std::unordered_map<std::string, std::vector<uint8_t>>>::
+    AppendSetValueToWriter(MessageWriter* writer) {
+  MessageWriter variant_writer(nullptr);
+  MessageWriter dict_writer(nullptr);
+
+  writer->OpenVariant("a{sv}", &variant_writer);
+  variant_writer.OpenArray("{sv}", &dict_writer);
+
+  for (const auto& pair : set_value_) {
+    MessageWriter entry_writer(nullptr);
+    dict_writer.OpenDictEntry(&entry_writer);
+
+    entry_writer.AppendString(pair.first);
+
+    MessageWriter value_varient_writer(nullptr);
+    entry_writer.OpenVariant("ay", &value_varient_writer);
+    value_varient_writer.AppendArrayOfBytes(pair.second.data(),
+                                            pair.second.size());
+    entry_writer.CloseContainer(&value_varient_writer);
+
+    dict_writer.CloseContainer(&entry_writer);
+  }
+
+  variant_writer.CloseContainer(&dict_writer);
+  writer->CloseContainer(&variant_writer);
+}
+
 template class Property<uint8_t>;
 template class Property<bool>;
 template class Property<int16_t>;
@@ -675,5 +741,6 @@
 template class Property<std::vector<uint8_t>>;
 template class Property<std::map<std::string, std::string>>;
 template class Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>;
+template class Property<std::unordered_map<std::string, std::vector<uint8_t>>>;
 
 }  // namespace dbus