• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_adapter_chromeos.h"
6 
7 #include <vector>
8 
9 #include "base/callback.h"
10 #include "base/logging.h"
11 #include "chromeos/dbus/dbus_thread_manager.h"
12 #include "device/nfc/nfc_peer.h"
13 #include "device/nfc/nfc_tag.h"
14 #include "third_party/cros_system_api/dbus/service_constants.h"
15 
16 namespace chromeos {
17 
NfcAdapterChromeOS()18 NfcAdapterChromeOS::NfcAdapterChromeOS()
19     : weak_ptr_factory_(this) {
20   DBusThreadManager::Get()->GetNfcAdapterClient()->AddObserver(this);
21   DBusThreadManager::Get()->GetNfcDeviceClient()->AddObserver(this);
22   DBusThreadManager::Get()->GetNfcTagClient()->AddObserver(this);
23 
24   const std::vector<dbus::ObjectPath>& object_paths =
25       DBusThreadManager::Get()->GetNfcAdapterClient()->GetAdapters();
26   if (!object_paths.empty()) {
27     VLOG(1) << object_paths.size() << " NFC adapter(s) available.";
28     SetAdapter(object_paths[0]);
29   }
30 }
31 
~NfcAdapterChromeOS()32 NfcAdapterChromeOS::~NfcAdapterChromeOS() {
33   DBusThreadManager::Get()->GetNfcAdapterClient()->RemoveObserver(this);
34   DBusThreadManager::Get()->GetNfcDeviceClient()->RemoveObserver(this);
35   DBusThreadManager::Get()->GetNfcTagClient()->RemoveObserver(this);
36 }
37 
AddObserver(NfcAdapter::Observer * observer)38 void NfcAdapterChromeOS::AddObserver(NfcAdapter::Observer* observer) {
39   DCHECK(observer);
40   observers_.AddObserver(observer);
41 }
42 
RemoveObserver(NfcAdapter::Observer * observer)43 void NfcAdapterChromeOS::RemoveObserver(NfcAdapter::Observer* observer) {
44   DCHECK(observer);
45   observers_.RemoveObserver(observer);
46 }
47 
IsPresent() const48 bool NfcAdapterChromeOS::IsPresent() const {
49   return !object_path_.value().empty();
50 }
51 
IsPowered() const52 bool NfcAdapterChromeOS::IsPowered() const {
53   if (!IsPresent())
54     return false;
55   return DBusThreadManager::Get()->GetNfcAdapterClient()->
56       GetProperties(object_path_)->powered.value();
57 }
58 
IsPolling() const59 bool NfcAdapterChromeOS::IsPolling() const {
60   if (!IsPresent())
61     return false;
62   return DBusThreadManager::Get()->GetNfcAdapterClient()->
63       GetProperties(object_path_)->polling.value();
64 }
65 
IsInitialized() const66 bool NfcAdapterChromeOS::IsInitialized() const {
67   return true;
68 }
69 
SetPowered(bool powered,const base::Closure & callback,const ErrorCallback & error_callback)70 void NfcAdapterChromeOS::SetPowered(bool powered,
71                                     const base::Closure& callback,
72                                     const ErrorCallback& error_callback) {
73   if (!IsPresent()) {
74     LOG(WARNING) << "Adapter not present. Cannot power up the antenna.";
75     error_callback.Run();
76     return;
77   }
78   DBusThreadManager::Get()->GetNfcAdapterClient()->
79       GetProperties(object_path_)->powered.Set(
80           powered,
81           base::Bind(&NfcAdapterChromeOS::OnSetPowered,
82                      weak_ptr_factory_.GetWeakPtr(),
83                      callback,
84                      error_callback));
85 }
86 
StartPolling(const base::Closure & callback,const ErrorCallback & error_callback)87 void NfcAdapterChromeOS::StartPolling(const base::Closure& callback,
88                                       const ErrorCallback& error_callback) {
89   // Always poll in "Initiator" mode.
90   DBusThreadManager::Get()->GetNfcAdapterClient()->
91       StartPollLoop(object_path_,
92                     nfc_adapter::kModeInitiator,
93                     base::Bind(&NfcAdapterChromeOS::OnStartPolling,
94                                weak_ptr_factory_.GetWeakPtr(),
95                                callback),
96                     base::Bind(&NfcAdapterChromeOS::OnStartPollingError,
97                                weak_ptr_factory_.GetWeakPtr(),
98                                error_callback));
99 }
100 
StopPolling(const base::Closure & callback,const ErrorCallback & error_callback)101 void NfcAdapterChromeOS::StopPolling(const base::Closure& callback,
102                                      const ErrorCallback& error_callback) {
103   DBusThreadManager::Get()->GetNfcAdapterClient()->
104       StopPollLoop(object_path_,
105                    base::Bind(&NfcAdapterChromeOS::OnStopPolling,
106                               weak_ptr_factory_.GetWeakPtr(),
107                               callback),
108                    base::Bind(&NfcAdapterChromeOS::OnStopPollingError,
109                               weak_ptr_factory_.GetWeakPtr(),
110                               error_callback));
111 }
112 
AdapterAdded(const dbus::ObjectPath & object_path)113 void NfcAdapterChromeOS::AdapterAdded(const dbus::ObjectPath& object_path) {
114   // Set the adapter to the newly added adapter only if no adapter is present.
115   if (!IsPresent())
116     SetAdapter(object_path);
117 }
118 
AdapterRemoved(const dbus::ObjectPath & object_path)119 void NfcAdapterChromeOS::AdapterRemoved(const dbus::ObjectPath& object_path) {
120   if (object_path != object_path_)
121     return;
122 
123   // The current adapter was removed, so mark us as not present and clean up
124   // peers and tags.
125   RemoveAdapter();
126 
127   // There may still be other adapters present on the system. Set the next
128   // available adapter as the current one.
129   const std::vector<dbus::ObjectPath>& object_paths =
130       DBusThreadManager::Get()->GetNfcAdapterClient()->GetAdapters();
131   for (std::vector<dbus::ObjectPath>::const_iterator iter =
132           object_paths.begin();
133        iter != object_paths.end(); ++iter) {
134     // The removed object will still be available until the call to
135     // AdapterRemoved returns. Make sure that we are not re-adding the
136     // removed adapter.
137     if (*iter == object_path)
138       continue;
139     SetAdapter(*iter);
140   }
141 }
142 
AdapterPropertyChanged(const dbus::ObjectPath & object_path,const std::string & property_name)143 void NfcAdapterChromeOS::AdapterPropertyChanged(
144     const dbus::ObjectPath& object_path,
145     const std::string& property_name) {
146   if (object_path != object_path_)
147     return;
148   NfcAdapterClient::Properties* properties =
149       DBusThreadManager::Get()->GetNfcAdapterClient()->
150           GetProperties(object_path_);
151   if (property_name == properties->powered.name())
152     PoweredChanged(properties->powered.value());
153   else if (property_name == properties->polling.name())
154     PollingChanged(properties->polling.value());
155 }
156 
DeviceAdded(const dbus::ObjectPath & object_path)157 void NfcAdapterChromeOS::DeviceAdded(const dbus::ObjectPath& object_path) {
158   VLOG(1) << "NFC device found: " << object_path.value();
159   // TODO(armansito): Implement device logic.
160 }
161 
DeviceRemoved(const dbus::ObjectPath & object_path)162 void NfcAdapterChromeOS::DeviceRemoved(const dbus::ObjectPath& object_path) {
163   VLOG(1) << "NFC device lost: " << object_path.value();
164   // TODO(armansito): Implement device logic.
165 }
166 
DevicePropertyChanged(const dbus::ObjectPath & object_path,const std::string & property_name)167 void NfcAdapterChromeOS::DevicePropertyChanged(
168     const dbus::ObjectPath& object_path,
169     const std::string& property_name) {
170   // TODO(armansito): Implement device logic.
171 }
172 
TagAdded(const dbus::ObjectPath & object_path)173 void NfcAdapterChromeOS::TagAdded(const dbus::ObjectPath& object_path) {
174   VLOG(1) << "NFC tag found: " << object_path.value();
175   // TODO(armansito): Implement tag logic.
176 }
177 
TagRemoved(const dbus::ObjectPath & object_path)178 void NfcAdapterChromeOS::TagRemoved(const dbus::ObjectPath& object_path) {
179   VLOG(1) << "NFC tag found: " << object_path.value();
180   // TODO(armansito): Implement tag logic.
181 }
182 
TagPropertyChanged(const dbus::ObjectPath & object_path,const std::string & property_name)183 void NfcAdapterChromeOS::TagPropertyChanged(
184     const dbus::ObjectPath& object_path,
185     const std::string& property_name) {
186   // TODO(armansito): Implement tag logic.
187 }
188 
SetAdapter(const dbus::ObjectPath & object_path)189 void NfcAdapterChromeOS::SetAdapter(const dbus::ObjectPath& object_path) {
190   DCHECK(!IsPresent());
191   object_path_ = object_path;
192   VLOG(1) << "Using NFC adapter: " << object_path.value();
193 
194   NfcAdapterClient::Properties* properties =
195       DBusThreadManager::Get()->GetNfcAdapterClient()->
196           GetProperties(object_path_);
197   PresentChanged(true);
198   if (properties->powered.value())
199     PoweredChanged(true);
200   if (properties->polling.value())
201     PollingChanged(true);
202 
203   // TODO(armansito): Create device::NfcPeer and device::NfcTag instances for
204   // all peers and tags that exist, once they have been implemented for
205   // ChromeOS.
206 }
207 
RemoveAdapter()208 void NfcAdapterChromeOS::RemoveAdapter() {
209   DCHECK(IsPresent());
210   VLOG(1) << "NFC adapter removed: " << object_path_.value();
211 
212   NfcAdapterClient::Properties* properties =
213       DBusThreadManager::Get()->GetNfcAdapterClient()->
214           GetProperties(object_path_);
215   if (properties->powered.value())
216     PoweredChanged(false);
217   if (properties->polling.value())
218     PollingChanged(false);
219 
220   // Copy the tags and peers here and clear the original containers so that
221   // GetPeers and GetTags return no values during the *Removed observer calls.
222   PeersMap peers = peers_;
223   TagsMap tags = tags_;
224   peers_.clear();
225   tags_.clear();
226 
227   for (PeersMap::iterator iter = peers_.begin();
228        iter != peers_.end(); ++iter) {
229     FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_,
230                       PeerLost(this, iter->second));
231     delete iter->second;
232   }
233   for (TagsMap::iterator iter = tags_.begin();
234        iter != tags_.end(); ++iter) {
235     FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_,
236                       TagLost(this, iter->second));
237     delete iter->second;
238   }
239 
240   object_path_ = dbus::ObjectPath("");
241   PresentChanged(false);
242 }
243 
PoweredChanged(bool powered)244 void NfcAdapterChromeOS::PoweredChanged(bool powered) {
245   FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_,
246                     AdapterPoweredChanged(this, powered));
247 }
248 
PollingChanged(bool polling)249 void NfcAdapterChromeOS::PollingChanged(bool polling) {
250   FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_,
251                     AdapterPollingChanged(this, polling));
252 }
253 
PresentChanged(bool present)254 void NfcAdapterChromeOS::PresentChanged(bool present) {
255   FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_,
256                     AdapterPresentChanged(this, present));
257 }
258 
OnSetPowered(const base::Closure & callback,const ErrorCallback & error_callback,bool success)259 void NfcAdapterChromeOS::OnSetPowered(const base::Closure& callback,
260                                       const ErrorCallback& error_callback,
261                                       bool success) {
262   VLOG(1) << "NfcAdapterChromeOS::OnSetPowered result: " << success;
263   if (success) {
264     // TODO(armansito): There is a bug in neard 0.13 that causes it not to emit
265     // a signal when the "Powered" property changes. Sync the properties here,
266     // but remove it in neard 0.14.
267     if (IsPresent()) {
268       DBusThreadManager::Get()->GetNfcAdapterClient()->
269           GetProperties(object_path_)->GetAll();
270     }
271     callback.Run();
272   } else {
273     LOG(WARNING) << "Failed to power up the NFC antenna radio.";
274     error_callback.Run();
275   }
276 }
277 
OnStartPolling(const base::Closure & callback)278 void NfcAdapterChromeOS::OnStartPolling(const base::Closure& callback) {
279   callback.Run();
280 }
281 
OnStartPollingError(const ErrorCallback & error_callback,const std::string & error_name,const std::string & error_message)282 void NfcAdapterChromeOS::OnStartPollingError(
283     const ErrorCallback& error_callback,
284     const std::string& error_name,
285     const std::string& error_message) {
286   LOG(WARNING) << object_path_.value() << ": Failed to start polling: "
287                << error_name << ": " << error_message;
288   error_callback.Run();
289 }
290 
OnStopPolling(const base::Closure & callback)291 void NfcAdapterChromeOS::OnStopPolling(const base::Closure& callback) {
292   callback.Run();
293 }
294 
OnStopPollingError(const ErrorCallback & error_callback,const std::string & error_name,const std::string & error_message)295 void NfcAdapterChromeOS::OnStopPollingError(
296     const ErrorCallback& error_callback,
297     const std::string& error_name,
298     const std::string& error_message) {
299   LOG(WARNING) << object_path_.value() << ": Failed to stop polling: "
300                << error_name << ": " << error_message;
301   error_callback.Run();
302 }
303 
304 }  // namespace chromeos
305