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_peer_chromeos.h"
10 #include "base/logging.h"
11 #include "base/stl_util.h"
12 #include "chromeos/dbus/dbus_thread_manager.h"
13 #include "chromeos/dbus/nfc_device_client.h"
14 #include "device/nfc/nfc_ndef_record_utils_chromeos.h"
15 #include "third_party/cros_system_api/dbus/service_constants.h"
17 using device::NfcNdefMessage
;
18 using device::NfcNdefRecord
;
24 typedef std::vector
<dbus::ObjectPath
> ObjectPathVector
;
28 NfcPeerChromeOS::NfcPeerChromeOS(const dbus::ObjectPath
& object_path
)
29 : object_path_(object_path
),
30 weak_ptr_factory_(this) {
31 // Create record objects for all records that were received before.
32 const ObjectPathVector
& records
=
33 DBusThreadManager::Get()->GetNfcRecordClient()->
34 GetRecordsForDevice(object_path_
);
35 for (ObjectPathVector::const_iterator iter
= records
.begin();
36 iter
!= records
.end(); ++iter
) {
39 DBusThreadManager::Get()->GetNfcRecordClient()->AddObserver(this);
42 NfcPeerChromeOS::~NfcPeerChromeOS() {
43 DBusThreadManager::Get()->GetNfcRecordClient()->RemoveObserver(this);
44 STLDeleteValues(&records_
);
47 void NfcPeerChromeOS::AddObserver(device::NfcPeer::Observer
* observer
) {
49 observers_
.AddObserver(observer
);
52 void NfcPeerChromeOS::RemoveObserver(device::NfcPeer::Observer
* observer
) {
54 observers_
.RemoveObserver(observer
);
57 std::string
NfcPeerChromeOS::GetIdentifier() const {
58 return object_path_
.value();
61 const NfcNdefMessage
& NfcPeerChromeOS::GetNdefMessage() const {
65 void NfcPeerChromeOS::PushNdef(const NfcNdefMessage
& message
,
66 const base::Closure
& callback
,
67 const ErrorCallback
& error_callback
) {
68 if (message
.records().empty()) {
69 LOG(ERROR
) << "Given NDEF message is empty. Cannot push it.";
73 // TODO(armansito): neard currently supports pushing only one NDEF record
74 // to a remote device and won't support multiple records until 0.15. Until
75 // then, report failure if |message| contains more than one record.
76 if (message
.records().size() > 1) {
77 LOG(ERROR
) << "Currently, pushing only 1 NDEF record is supported.";
81 const NfcNdefRecord
* record
= message
.records()[0];
82 base::DictionaryValue attributes
;
83 if (!nfc_ndef_record_utils::NfcNdefRecordToDBusAttributes(
84 record
, &attributes
)) {
85 LOG(ERROR
) << "Failed to extract NDEF record fields for NDEF push.";
89 DBusThreadManager::Get()->GetNfcDeviceClient()->Push(
92 base::Bind(&NfcPeerChromeOS::OnPushNdef
,
93 weak_ptr_factory_
.GetWeakPtr(),
95 base::Bind(&NfcPeerChromeOS::OnPushNdefError
,
96 weak_ptr_factory_
.GetWeakPtr(),
100 void NfcPeerChromeOS::StartHandover(HandoverType handover_type
,
101 const base::Closure
& callback
,
102 const ErrorCallback
& error_callback
) {
103 // TODO(armansito): Initiating handover with a peer is currently not
104 // supported. For now, return an error immediately.
105 LOG(ERROR
) << "NFC Handover currently not supported.";
106 error_callback
.Run();
109 void NfcPeerChromeOS::RecordAdded(const dbus::ObjectPath
& object_path
) {
110 // Don't create the record object yet. Instead, wait until all record
111 // properties have been received and contruct the object and notify observers
113 VLOG(1) << "Record added: " << object_path
.value() << ". Waiting until "
114 << "all properties have been fetched to create record object.";
117 void NfcPeerChromeOS::RecordRemoved(const dbus::ObjectPath
& object_path
) {
118 NdefRecordMap::iterator iter
= records_
.find(object_path
);
119 if (iter
== records_
.end())
121 VLOG(1) << "Lost remote NDEF record object: " << object_path
.value()
122 << ", removing record.";
123 NfcNdefRecord
* record
= iter
->second
;
124 message_
.RemoveRecord(record
);
126 records_
.erase(iter
);
129 void NfcPeerChromeOS::RecordPropertiesReceived(
130 const dbus::ObjectPath
& object_path
) {
131 VLOG(1) << "Record properties received for: " << object_path
.value();
133 // Check if the found record belongs to this device.
134 bool record_found
= false;
135 const ObjectPathVector
& records
=
136 DBusThreadManager::Get()->GetNfcRecordClient()->
137 GetRecordsForDevice(object_path_
);
138 for (ObjectPathVector::const_iterator iter
= records
.begin();
139 iter
!= records
.end(); ++iter
) {
140 if (*iter
== object_path
) {
146 VLOG(1) << "Record \"" << object_path
.value() << "\" doesn't belong to this"
147 << " device. Ignoring.";
151 AddRecord(object_path
);
154 void NfcPeerChromeOS::OnPushNdef(const base::Closure
& callback
) {
158 void NfcPeerChromeOS::OnPushNdefError(const ErrorCallback
& error_callback
,
159 const std::string
& error_name
,
160 const std::string
& error_message
) {
161 LOG(ERROR
) << object_path_
.value() << ": Failed to Push NDEF message: "
162 << error_name
<< ": " << error_message
;
163 error_callback
.Run();
166 void NfcPeerChromeOS::AddRecord(const dbus::ObjectPath
& object_path
) {
167 // Ignore this call if an entry for this record already exists.
168 if (records_
.find(object_path
) != records_
.end()) {
169 VLOG(1) << "Record object for remote \"" << object_path
.value()
170 << "\" already exists.";
174 NfcRecordClient::Properties
* record_properties
=
175 DBusThreadManager::Get()->GetNfcRecordClient()->
176 GetProperties(object_path
);
177 DCHECK(record_properties
);
179 NfcNdefRecord
* record
= new NfcNdefRecord();
180 if (!nfc_ndef_record_utils::RecordPropertiesToNfcNdefRecord(
181 record_properties
, record
)) {
182 LOG(ERROR
) << "Failed to create record object for record with object "
183 << "path \"" << object_path
.value() << "\"";
188 message_
.AddRecord(record
);
189 records_
[object_path
] = record
;
190 FOR_EACH_OBSERVER(NfcPeer::Observer
, observers_
,
191 RecordReceived(this, record
));
194 } // namespace chromeos