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