summaryrefslogtreecommitdiffstats
path: root/chromium/device/nfc/nfc_ndef_record_utils_chromeos.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/device/nfc/nfc_ndef_record_utils_chromeos.cc')
-rw-r--r--chromium/device/nfc/nfc_ndef_record_utils_chromeos.cc238
1 files changed, 238 insertions, 0 deletions
diff --git a/chromium/device/nfc/nfc_ndef_record_utils_chromeos.cc b/chromium/device/nfc/nfc_ndef_record_utils_chromeos.cc
new file mode 100644
index 00000000000..466cf38b971
--- /dev/null
+++ b/chromium/device/nfc/nfc_ndef_record_utils_chromeos.cc
@@ -0,0 +1,238 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/nfc/nfc_ndef_record_utils_chromeos.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "device/nfc/nfc_ndef_record.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+using device::NfcNdefRecord;
+
+namespace chromeos {
+namespace nfc_ndef_record_utils {
+
+namespace {
+
+// Maps the NDEF type |type| as returned by neard to the corresponding
+// device::NfcNdefRecord::Type value.
+NfcNdefRecord::Type DBusRecordTypeValueToNfcNdefRecordType(
+ const std::string& type) {
+ if (type == nfc_record::kTypeSmartPoster)
+ return NfcNdefRecord::kTypeSmartPoster;
+ if (type == nfc_record::kTypeText)
+ return NfcNdefRecord::kTypeText;
+ if (type == nfc_record::kTypeUri)
+ return NfcNdefRecord::kTypeURI;
+ if (type == nfc_record::kTypeHandoverRequest)
+ return NfcNdefRecord::kTypeHandoverRequest;
+ if (type == nfc_record::kTypeHandoverSelect)
+ return NfcNdefRecord::kTypeHandoverSelect;
+ if (type == nfc_record::kTypeHandoverCarrier)
+ return NfcNdefRecord::kTypeHandoverCarrier;
+ return NfcNdefRecord::kTypeUnknown;
+}
+
+// Maps the NDEF type |type| given as a NFC C++ API enumeration to the
+// corresponding string value defined by neard.
+std::string NfcRecordTypeEnumToPropertyValue(NfcNdefRecord::Type type) {
+ switch (type) {
+ case NfcNdefRecord::kTypeSmartPoster:
+ return nfc_record::kTypeSmartPoster;
+ case NfcNdefRecord::kTypeText:
+ return nfc_record::kTypeText;
+ case NfcNdefRecord::kTypeURI:
+ return nfc_record::kTypeUri;
+ case NfcNdefRecord::kTypeHandoverRequest:
+ return nfc_record::kTypeHandoverRequest;
+ case NfcNdefRecord::kTypeHandoverSelect:
+ return nfc_record::kTypeHandoverSelect;
+ case NfcNdefRecord::kTypeHandoverCarrier:
+ return nfc_record::kTypeHandoverCarrier;
+ default:
+ return "";
+ }
+}
+
+// Maps the field name |field_name| given as defined in NfcNdefRecord to the
+// Neard Record D-Bus property name. This handles all fields except for
+// NfcNdefRecord::kFieldTitles and NfcNdefRecord::kFieldAction, which need
+// special handling.
+std::string NdefRecordFieldToDBusProperty(const std::string& field_name) {
+ if (field_name == NfcNdefRecord::kFieldEncoding)
+ return nfc_record::kEncodingProperty;
+ if (field_name == NfcNdefRecord::kFieldLanguageCode)
+ return nfc_record::kLanguageProperty;
+ if (field_name == NfcNdefRecord::kFieldText)
+ return nfc_record::kRepresentationProperty;
+ if (field_name == NfcNdefRecord::kFieldURI)
+ return nfc_record::kUriProperty;
+ if (field_name == NfcNdefRecord::kFieldMimeType)
+ return nfc_record::kMimeTypeProperty;
+ if (field_name == NfcNdefRecord::kFieldTargetSize)
+ return nfc_record::kSizeProperty;
+ return "";
+}
+
+std::string NfcNdefRecordActionValueToDBusActionValue(
+ const std::string& action) {
+ // TODO(armansito): Add bindings for values returned by neard to
+ // service_constants.h.
+ if (action == device::NfcNdefRecord::kSmartPosterActionDo)
+ return "Do";
+ if (action == device::NfcNdefRecord::kSmartPosterActionSave)
+ return "Save";
+ if (action == device::NfcNdefRecord::kSmartPosterActionOpen)
+ return "Edit";
+ return "";
+}
+
+std::string DBusActionValueToNfcNdefRecordActionValue(
+ const std::string& action) {
+ // TODO(armansito): Add bindings for values returned by neard to
+ // service_constants.h.
+ if (action == "Do")
+ return device::NfcNdefRecord::kSmartPosterActionDo;
+ if (action == "Save")
+ return device::NfcNdefRecord::kSmartPosterActionSave;
+ if (action == "Edit")
+ return device::NfcNdefRecord::kSmartPosterActionOpen;
+ return "";
+}
+
+
+// Translates the given dictionary of NDEF fields by recursively converting
+// each key in |record_data| to its corresponding Record property name defined
+// by the Neard D-Bus API. The output is stored in |out|. Returns false if an
+// error occurs.
+bool ConvertNdefFieldsToDBusAttributes(
+ const base::DictionaryValue& fields,
+ base::DictionaryValue* out) {
+ DCHECK(out);
+ for (base::DictionaryValue::Iterator iter(fields);
+ !iter.IsAtEnd(); iter.Advance()) {
+ // Special case the "titles" and "action" fields.
+ if (iter.key() == NfcNdefRecord::kFieldTitles) {
+ const base::ListValue* titles = NULL;
+ bool value_result = iter.value().GetAsList(&titles);
+ DCHECK(value_result);
+ DCHECK(titles->GetSize() != 0);
+ // TODO(armansito): For now, pick the first title in the list and write
+ // its contents directly to the top level of the field. This is due to an
+ // error in the Neard D-Bus API design. This code will need to be updated
+ // if the neard API changes to correct this.
+ const base::DictionaryValue* first_title = NULL;
+ value_result = titles->GetDictionary(0, &first_title);
+ DCHECK(value_result);
+ if (!ConvertNdefFieldsToDBusAttributes(*first_title, out)) {
+ LOG(ERROR) << "Invalid title field.";
+ return false;
+ }
+ } else if (iter.key() == NfcNdefRecord::kFieldAction) {
+ // The value of the action field needs to be translated.
+ std::string action_value;
+ bool value_result = iter.value().GetAsString(&action_value);
+ DCHECK(value_result);
+ std::string action =
+ NfcNdefRecordActionValueToDBusActionValue(action_value);
+ if (action.empty()) {
+ VLOG(1) << "Invalid action value: \"" << action_value << "\"";
+ return false;
+ }
+ out->SetString(nfc_record::kActionProperty, action);
+ } else {
+ std::string dbus_property = NdefRecordFieldToDBusProperty(iter.key());
+ if (dbus_property.empty()) {
+ LOG(ERROR) << "Invalid field: " << iter.key();
+ return false;
+ }
+ out->Set(dbus_property, iter.value().DeepCopy());
+ }
+ }
+ return true;
+}
+
+} // namespace
+
+bool NfcNdefRecordToDBusAttributes(
+ const NfcNdefRecord* record,
+ base::DictionaryValue* out) {
+ DCHECK(record);
+ DCHECK(out);
+ if (!record->IsPopulated()) {
+ LOG(ERROR) << "Record is not populated.";
+ return false;
+ }
+ out->SetString(nfc_record::kTypeProperty,
+ NfcRecordTypeEnumToPropertyValue(record->type()));
+ return ConvertNdefFieldsToDBusAttributes(record->data(), out);
+}
+
+bool RecordPropertiesToNfcNdefRecord(
+ const NfcRecordClient::Properties* properties,
+ device::NfcNdefRecord* out) {
+ if (out->IsPopulated()) {
+ LOG(ERROR) << "Record is already populated!";
+ return false;
+ }
+ NfcNdefRecord::Type type =
+ DBusRecordTypeValueToNfcNdefRecordType(properties->type.value());
+ if (type == NfcNdefRecord::kTypeUnknown) {
+ LOG(ERROR) << "Record type is unknown.";
+ return false;
+ }
+
+ // Extract each property.
+ base::DictionaryValue attributes;
+ if (!properties->uri.value().empty())
+ attributes.SetString(NfcNdefRecord::kFieldURI, properties->uri.value());
+ if (!properties->mime_type.value().empty()) {
+ attributes.SetString(NfcNdefRecord::kFieldMimeType,
+ properties->mime_type.value());
+ }
+ if (properties->size.value() != 0) {
+ attributes.SetDouble(NfcNdefRecord::kFieldTargetSize,
+ static_cast<double>(properties->size.value()));
+ }
+ std::string action_value =
+ DBusActionValueToNfcNdefRecordActionValue(properties->action.value());
+ if (!action_value.empty())
+ attributes.SetString(NfcNdefRecord::kFieldAction, action_value);
+
+ // The "representation", "encoding", and "language" properties will be stored
+ // differently, depending on whether the record type is "SmartPoster" or
+ // "Text".
+ {
+ scoped_ptr<base::DictionaryValue> text_attributes(
+ new base::DictionaryValue());
+ if (!properties->representation.value().empty()) {
+ text_attributes->SetString(NfcNdefRecord::kFieldText,
+ properties->representation.value());
+ }
+ if (!properties->encoding.value().empty()) {
+ text_attributes->SetString(NfcNdefRecord::kFieldEncoding,
+ properties->encoding.value());
+ }
+ if (!properties->language.value().empty()) {
+ text_attributes->SetString(NfcNdefRecord::kFieldLanguageCode,
+ properties->language.value());
+ }
+ if (!text_attributes->empty()) {
+ if (type == NfcNdefRecord::kTypeSmartPoster) {
+ base::ListValue* titles = new base::ListValue();
+ titles->Append(text_attributes.release());
+ attributes.Set(NfcNdefRecord::kFieldTitles, titles);
+ } else {
+ attributes.MergeDictionary(text_attributes.get());
+ }
+ }
+ }
+
+ // Populate the given record.
+ return out->Populate(type, &attributes);
+}
+
+} // namespace nfc_ndef_record_utils
+} // namespace chromeos