Create a new-installs-only uniformity trial.
[chromium-blink-merge.git] / device / bluetooth / bluetooth_service_record.cc
blob0ea18d7dac697b52b196ae167b906243e99e2fd4
1 // Copyright (c) 2012 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.
5 #include "device/bluetooth/bluetooth_service_record.h"
7 #include <string>
8 #include <vector>
10 #include "base/logging.h"
11 #include "base/string_number_conversions.h"
12 #include "device/bluetooth/bluetooth_utils.h"
13 #include "third_party/libxml/chromium/libxml_utils.h"
15 namespace {
17 static const char* kAttributeNode = "attribute";
18 static const char* kIdAttribute = "id";
19 static const char* kProtocolDescriptorListId = "0x0004";
20 static const char* kRfcommUuid = "0x0003";
21 static const char* kSdpNameId = "0x0100";
22 static const char* kSequenceNode = "sequence";
23 static const char* kTextNode = "text";
24 static const char* kUint8Node = "uint8";
25 static const char* kUuidId = "0x0001";
26 static const char* kUuidNode = "uuid";
27 static const char* kValueAttribute = "value";
29 bool AdvanceToTag(XmlReader* reader, const char* node_type) {
30 do {
31 if (!reader->Read())
32 return false;
33 } while (reader->NodeName() != node_type);
34 return true;
37 bool ExtractTextValue(XmlReader* reader, std::string* value_out) {
38 if (AdvanceToTag(reader, kTextNode)) {
39 reader->NodeAttribute(kValueAttribute, value_out);
40 return true;
42 return false;
45 } // namespace
47 namespace device {
49 BluetoothServiceRecord::BluetoothServiceRecord(
50 const std::string& address,
51 const std::string& xml_data)
52 : address_(address),
53 supports_rfcomm_(false) {
55 XmlReader reader;
56 if (!reader.Load(xml_data))
57 return;
59 while (AdvanceToTag(&reader, kAttributeNode)) {
60 std::string id;
61 if (reader.NodeAttribute(kIdAttribute, &id)) {
62 if (id == kSdpNameId) {
63 ExtractTextValue(&reader, &name_);
64 } else if (id == kProtocolDescriptorListId) {
65 if (AdvanceToTag(&reader, kSequenceNode)) {
66 ExtractChannels(&reader);
68 } else if (id == kUuidId) {
69 if (AdvanceToTag(&reader, kSequenceNode)) {
70 ExtractUuid(&reader);
74 // We don't care about anything else here, so find the closing tag
75 AdvanceToTag(&reader, kAttributeNode);
79 void BluetoothServiceRecord::ExtractChannels(XmlReader* reader) {
80 const int start_depth = reader->Depth();
81 do {
82 if (reader->NodeName() == kSequenceNode) {
83 if (AdvanceToTag(reader, kUuidNode)) {
84 std::string type;
85 if (reader->NodeAttribute(kValueAttribute, &type) &&
86 type == kRfcommUuid) {
87 if (AdvanceToTag(reader, kUint8Node)) {
88 std::string channel_string;
89 if (reader->NodeAttribute(kValueAttribute, &channel_string)) {
90 std::vector<uint8> channel_bytes;
91 if (base::HexStringToBytes(channel_string.substr(2),
92 &channel_bytes)) {
93 if (channel_bytes.size() == 1) {
94 rfcomm_channel_ = channel_bytes[0];
95 supports_rfcomm_ = true;
103 } while (AdvanceToTag(reader, kSequenceNode) &&
104 reader->Depth() != start_depth);
107 void BluetoothServiceRecord::ExtractUuid(XmlReader* reader) {
108 const int start_depth = reader->Depth();
109 do {
110 if (reader->NodeName() == kSequenceNode) {
111 if (AdvanceToTag(reader, kUuidNode)) {
112 if (!reader->NodeAttribute(kValueAttribute, &uuid_))
113 uuid_.clear();
116 } while (AdvanceToTag(reader, kSequenceNode) &&
117 reader->Depth() != start_depth);
119 uuid_ = device::bluetooth_utils::CanonicalUuid(uuid_);
122 } // namespace device