root/device/nfc/nfc_peer_chromeos.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. weak_ptr_factory_
  2. AddObserver
  3. RemoveObserver
  4. GetIdentifier
  5. GetNdefMessage
  6. PushNdef
  7. StartHandover
  8. RecordAdded
  9. RecordRemoved
  10. RecordPropertiesReceived
  11. OnPushNdef
  12. OnPushNdefError
  13. AddRecord

// 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_peer_chromeos.h"

#include <string>
#include <vector>

#include "base/logging.h"
#include "base/stl_util.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/nfc_device_client.h"
#include "device/nfc/nfc_ndef_record_utils_chromeos.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

using device::NfcNdefMessage;
using device::NfcNdefRecord;

namespace chromeos {

namespace {

typedef std::vector<dbus::ObjectPath> ObjectPathVector;

}  // namespace

NfcPeerChromeOS::NfcPeerChromeOS(const dbus::ObjectPath& object_path)
    : object_path_(object_path),
      weak_ptr_factory_(this) {
  // Create record objects for all records that were received before.
  const ObjectPathVector& records =
      DBusThreadManager::Get()->GetNfcRecordClient()->
          GetRecordsForDevice(object_path_);
  for (ObjectPathVector::const_iterator iter = records.begin();
       iter != records.end(); ++iter) {
    AddRecord(*iter);
  }
  DBusThreadManager::Get()->GetNfcRecordClient()->AddObserver(this);
}

NfcPeerChromeOS::~NfcPeerChromeOS() {
  DBusThreadManager::Get()->GetNfcRecordClient()->RemoveObserver(this);
  STLDeleteValues(&records_);
}

void NfcPeerChromeOS::AddObserver(device::NfcPeer::Observer* observer) {
  DCHECK(observer);
  observers_.AddObserver(observer);
}

void NfcPeerChromeOS::RemoveObserver(device::NfcPeer::Observer* observer) {
  DCHECK(observer);
  observers_.RemoveObserver(observer);
}

std::string NfcPeerChromeOS::GetIdentifier() const {
  return object_path_.value();
}

const NfcNdefMessage& NfcPeerChromeOS::GetNdefMessage() const {
  return message_;
}

void NfcPeerChromeOS::PushNdef(const NfcNdefMessage& message,
                               const base::Closure& callback,
                               const ErrorCallback& error_callback) {
  if (message.records().empty()) {
    LOG(ERROR) << "Given NDEF message is empty. Cannot push it.";
    error_callback.Run();
    return;
  }
  // TODO(armansito): neard currently supports pushing only one NDEF record
  // to a remote device and won't support multiple records until 0.15. Until
  // then, report failure if |message| contains more than one record.
  if (message.records().size() > 1) {
    LOG(ERROR) << "Currently, pushing only 1 NDEF record is supported.";
    error_callback.Run();
    return;
  }
  const NfcNdefRecord* record = message.records()[0];
  base::DictionaryValue attributes;
  if (!nfc_ndef_record_utils::NfcNdefRecordToDBusAttributes(
          record, &attributes)) {
    LOG(ERROR) << "Failed to extract NDEF record fields for NDEF push.";
    error_callback.Run();
    return;
  }
  DBusThreadManager::Get()->GetNfcDeviceClient()->Push(
      object_path_,
      attributes,
      base::Bind(&NfcPeerChromeOS::OnPushNdef,
                 weak_ptr_factory_.GetWeakPtr(),
                 callback),
      base::Bind(&NfcPeerChromeOS::OnPushNdefError,
                 weak_ptr_factory_.GetWeakPtr(),
                 error_callback));
}

void NfcPeerChromeOS::StartHandover(HandoverType handover_type,
                                    const base::Closure& callback,
                                    const ErrorCallback& error_callback) {
  // TODO(armansito): Initiating handover with a peer is currently not
  // supported. For now, return an error immediately.
  LOG(ERROR) << "NFC Handover currently not supported.";
  error_callback.Run();
}

void NfcPeerChromeOS::RecordAdded(const dbus::ObjectPath& object_path) {
  // Don't create the record object yet. Instead, wait until all record
  // properties have been received and contruct the object and notify observers
  // then.
  VLOG(1) << "Record added: " << object_path.value() << ". Waiting until "
          << "all properties have been fetched to create record object.";
}

void NfcPeerChromeOS::RecordRemoved(const dbus::ObjectPath& object_path) {
  NdefRecordMap::iterator iter = records_.find(object_path);
  if (iter == records_.end())
    return;
  VLOG(1) << "Lost remote NDEF record object: " << object_path.value()
          << ", removing record.";
  NfcNdefRecord* record = iter->second;
  message_.RemoveRecord(record);
  delete record;
  records_.erase(iter);
}

void NfcPeerChromeOS::RecordPropertiesReceived(
    const dbus::ObjectPath& object_path) {
  VLOG(1) << "Record properties received for: " << object_path.value();

  // Check if the found record belongs to this device.
  bool record_found = false;
  const ObjectPathVector& records =
      DBusThreadManager::Get()->GetNfcRecordClient()->
          GetRecordsForDevice(object_path_);
  for (ObjectPathVector::const_iterator iter = records.begin();
       iter != records.end(); ++iter) {
    if (*iter == object_path) {
      record_found = true;
      break;
    }
  }
  if (!record_found) {
    VLOG(1) << "Record \"" << object_path.value() << "\" doesn't belong to this"
            << " device. Ignoring.";
    return;
  }

  AddRecord(object_path);
}

void NfcPeerChromeOS::OnPushNdef(const base::Closure& callback) {
  callback.Run();
}

void NfcPeerChromeOS::OnPushNdefError(const ErrorCallback& error_callback,
                                      const std::string& error_name,
                                      const std::string& error_message) {
  LOG(ERROR) << object_path_.value() << ": Failed to Push NDEF message: "
             << error_name << ": " << error_message;
  error_callback.Run();
}

void NfcPeerChromeOS::AddRecord(const dbus::ObjectPath& object_path) {
  // Ignore this call if an entry for this record already exists.
  if (records_.find(object_path) != records_.end()) {
    VLOG(1) << "Record object for remote \"" << object_path.value()
            << "\" already exists.";
    return;
  }

  NfcRecordClient::Properties* record_properties =
      DBusThreadManager::Get()->GetNfcRecordClient()->
          GetProperties(object_path);
  DCHECK(record_properties);

  NfcNdefRecord* record = new NfcNdefRecord();
  if (!nfc_ndef_record_utils::RecordPropertiesToNfcNdefRecord(
          record_properties, record)) {
    LOG(ERROR) << "Failed to create record object for record with object "
               << "path \"" << object_path.value() << "\"";
    delete record;
    return;
  }

  message_.AddRecord(record);
  records_[object_path] = record;
  FOR_EACH_OBSERVER(NfcPeer::Observer, observers_,
                    RecordReceived(this, record));
}

}  // namespace chromeos

/* [<][>][^][v][top][bottom][index][help] */