Output hex dumps in net-internals as two columns of 8.
[chromium-blink-merge.git] / device / nfc / nfc_ndef_record_utils_chromeos.cc
blob466cf38b97156bcec7a3655051b9dadb10c16428
1 // Copyright 2013 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/nfc/nfc_ndef_record_utils_chromeos.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "device/nfc/nfc_ndef_record.h"
10 #include "third_party/cros_system_api/dbus/service_constants.h"
12 using device::NfcNdefRecord;
14 namespace chromeos {
15 namespace nfc_ndef_record_utils {
17 namespace {
19 // Maps the NDEF type |type| as returned by neard to the corresponding
20 // device::NfcNdefRecord::Type value.
21 NfcNdefRecord::Type DBusRecordTypeValueToNfcNdefRecordType(
22 const std::string& type) {
23 if (type == nfc_record::kTypeSmartPoster)
24 return NfcNdefRecord::kTypeSmartPoster;
25 if (type == nfc_record::kTypeText)
26 return NfcNdefRecord::kTypeText;
27 if (type == nfc_record::kTypeUri)
28 return NfcNdefRecord::kTypeURI;
29 if (type == nfc_record::kTypeHandoverRequest)
30 return NfcNdefRecord::kTypeHandoverRequest;
31 if (type == nfc_record::kTypeHandoverSelect)
32 return NfcNdefRecord::kTypeHandoverSelect;
33 if (type == nfc_record::kTypeHandoverCarrier)
34 return NfcNdefRecord::kTypeHandoverCarrier;
35 return NfcNdefRecord::kTypeUnknown;
38 // Maps the NDEF type |type| given as a NFC C++ API enumeration to the
39 // corresponding string value defined by neard.
40 std::string NfcRecordTypeEnumToPropertyValue(NfcNdefRecord::Type type) {
41 switch (type) {
42 case NfcNdefRecord::kTypeSmartPoster:
43 return nfc_record::kTypeSmartPoster;
44 case NfcNdefRecord::kTypeText:
45 return nfc_record::kTypeText;
46 case NfcNdefRecord::kTypeURI:
47 return nfc_record::kTypeUri;
48 case NfcNdefRecord::kTypeHandoverRequest:
49 return nfc_record::kTypeHandoverRequest;
50 case NfcNdefRecord::kTypeHandoverSelect:
51 return nfc_record::kTypeHandoverSelect;
52 case NfcNdefRecord::kTypeHandoverCarrier:
53 return nfc_record::kTypeHandoverCarrier;
54 default:
55 return "";
59 // Maps the field name |field_name| given as defined in NfcNdefRecord to the
60 // Neard Record D-Bus property name. This handles all fields except for
61 // NfcNdefRecord::kFieldTitles and NfcNdefRecord::kFieldAction, which need
62 // special handling.
63 std::string NdefRecordFieldToDBusProperty(const std::string& field_name) {
64 if (field_name == NfcNdefRecord::kFieldEncoding)
65 return nfc_record::kEncodingProperty;
66 if (field_name == NfcNdefRecord::kFieldLanguageCode)
67 return nfc_record::kLanguageProperty;
68 if (field_name == NfcNdefRecord::kFieldText)
69 return nfc_record::kRepresentationProperty;
70 if (field_name == NfcNdefRecord::kFieldURI)
71 return nfc_record::kUriProperty;
72 if (field_name == NfcNdefRecord::kFieldMimeType)
73 return nfc_record::kMimeTypeProperty;
74 if (field_name == NfcNdefRecord::kFieldTargetSize)
75 return nfc_record::kSizeProperty;
76 return "";
79 std::string NfcNdefRecordActionValueToDBusActionValue(
80 const std::string& action) {
81 // TODO(armansito): Add bindings for values returned by neard to
82 // service_constants.h.
83 if (action == device::NfcNdefRecord::kSmartPosterActionDo)
84 return "Do";
85 if (action == device::NfcNdefRecord::kSmartPosterActionSave)
86 return "Save";
87 if (action == device::NfcNdefRecord::kSmartPosterActionOpen)
88 return "Edit";
89 return "";
92 std::string DBusActionValueToNfcNdefRecordActionValue(
93 const std::string& action) {
94 // TODO(armansito): Add bindings for values returned by neard to
95 // service_constants.h.
96 if (action == "Do")
97 return device::NfcNdefRecord::kSmartPosterActionDo;
98 if (action == "Save")
99 return device::NfcNdefRecord::kSmartPosterActionSave;
100 if (action == "Edit")
101 return device::NfcNdefRecord::kSmartPosterActionOpen;
102 return "";
106 // Translates the given dictionary of NDEF fields by recursively converting
107 // each key in |record_data| to its corresponding Record property name defined
108 // by the Neard D-Bus API. The output is stored in |out|. Returns false if an
109 // error occurs.
110 bool ConvertNdefFieldsToDBusAttributes(
111 const base::DictionaryValue& fields,
112 base::DictionaryValue* out) {
113 DCHECK(out);
114 for (base::DictionaryValue::Iterator iter(fields);
115 !iter.IsAtEnd(); iter.Advance()) {
116 // Special case the "titles" and "action" fields.
117 if (iter.key() == NfcNdefRecord::kFieldTitles) {
118 const base::ListValue* titles = NULL;
119 bool value_result = iter.value().GetAsList(&titles);
120 DCHECK(value_result);
121 DCHECK(titles->GetSize() != 0);
122 // TODO(armansito): For now, pick the first title in the list and write
123 // its contents directly to the top level of the field. This is due to an
124 // error in the Neard D-Bus API design. This code will need to be updated
125 // if the neard API changes to correct this.
126 const base::DictionaryValue* first_title = NULL;
127 value_result = titles->GetDictionary(0, &first_title);
128 DCHECK(value_result);
129 if (!ConvertNdefFieldsToDBusAttributes(*first_title, out)) {
130 LOG(ERROR) << "Invalid title field.";
131 return false;
133 } else if (iter.key() == NfcNdefRecord::kFieldAction) {
134 // The value of the action field needs to be translated.
135 std::string action_value;
136 bool value_result = iter.value().GetAsString(&action_value);
137 DCHECK(value_result);
138 std::string action =
139 NfcNdefRecordActionValueToDBusActionValue(action_value);
140 if (action.empty()) {
141 VLOG(1) << "Invalid action value: \"" << action_value << "\"";
142 return false;
144 out->SetString(nfc_record::kActionProperty, action);
145 } else {
146 std::string dbus_property = NdefRecordFieldToDBusProperty(iter.key());
147 if (dbus_property.empty()) {
148 LOG(ERROR) << "Invalid field: " << iter.key();
149 return false;
151 out->Set(dbus_property, iter.value().DeepCopy());
154 return true;
157 } // namespace
159 bool NfcNdefRecordToDBusAttributes(
160 const NfcNdefRecord* record,
161 base::DictionaryValue* out) {
162 DCHECK(record);
163 DCHECK(out);
164 if (!record->IsPopulated()) {
165 LOG(ERROR) << "Record is not populated.";
166 return false;
168 out->SetString(nfc_record::kTypeProperty,
169 NfcRecordTypeEnumToPropertyValue(record->type()));
170 return ConvertNdefFieldsToDBusAttributes(record->data(), out);
173 bool RecordPropertiesToNfcNdefRecord(
174 const NfcRecordClient::Properties* properties,
175 device::NfcNdefRecord* out) {
176 if (out->IsPopulated()) {
177 LOG(ERROR) << "Record is already populated!";
178 return false;
180 NfcNdefRecord::Type type =
181 DBusRecordTypeValueToNfcNdefRecordType(properties->type.value());
182 if (type == NfcNdefRecord::kTypeUnknown) {
183 LOG(ERROR) << "Record type is unknown.";
184 return false;
187 // Extract each property.
188 base::DictionaryValue attributes;
189 if (!properties->uri.value().empty())
190 attributes.SetString(NfcNdefRecord::kFieldURI, properties->uri.value());
191 if (!properties->mime_type.value().empty()) {
192 attributes.SetString(NfcNdefRecord::kFieldMimeType,
193 properties->mime_type.value());
195 if (properties->size.value() != 0) {
196 attributes.SetDouble(NfcNdefRecord::kFieldTargetSize,
197 static_cast<double>(properties->size.value()));
199 std::string action_value =
200 DBusActionValueToNfcNdefRecordActionValue(properties->action.value());
201 if (!action_value.empty())
202 attributes.SetString(NfcNdefRecord::kFieldAction, action_value);
204 // The "representation", "encoding", and "language" properties will be stored
205 // differently, depending on whether the record type is "SmartPoster" or
206 // "Text".
208 scoped_ptr<base::DictionaryValue> text_attributes(
209 new base::DictionaryValue());
210 if (!properties->representation.value().empty()) {
211 text_attributes->SetString(NfcNdefRecord::kFieldText,
212 properties->representation.value());
214 if (!properties->encoding.value().empty()) {
215 text_attributes->SetString(NfcNdefRecord::kFieldEncoding,
216 properties->encoding.value());
218 if (!properties->language.value().empty()) {
219 text_attributes->SetString(NfcNdefRecord::kFieldLanguageCode,
220 properties->language.value());
222 if (!text_attributes->empty()) {
223 if (type == NfcNdefRecord::kTypeSmartPoster) {
224 base::ListValue* titles = new base::ListValue();
225 titles->Append(text_attributes.release());
226 attributes.Set(NfcNdefRecord::kFieldTitles, titles);
227 } else {
228 attributes.MergeDictionary(text_attributes.get());
233 // Populate the given record.
234 return out->Populate(type, &attributes);
237 } // namespace nfc_ndef_record_utils
238 } // namespace chromeos