nfc_adapter_client.cc revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
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 "chromeos/dbus/nfc_adapter_client.h"
6
7#include <map>
8#include <utility>
9
10#include "base/bind.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/observer_list.h"
13#include "base/strings/stringprintf.h"
14#include "chromeos/dbus/fake_nfc_adapter_client.h"
15#include "chromeos/dbus/nfc_manager_client.h"
16#include "dbus/bus.h"
17#include "dbus/message.h"
18#include "third_party/cros_system_api/dbus/service_constants.h"
19
20namespace chromeos {
21
22NfcAdapterClient::Properties::Properties(
23    dbus::ObjectProxy* object_proxy,
24    const PropertyChangedCallback& callback)
25    : NfcPropertySet(object_proxy,
26                     nfc_adapter::kNfcAdapterInterface,
27                     callback) {
28  RegisterProperty(nfc_adapter::kModeProperty, &mode);
29  RegisterProperty(nfc_adapter::kPoweredProperty, &powered);
30  RegisterProperty(nfc_adapter::kPollingProperty, &polling);
31  RegisterProperty(nfc_adapter::kProtocolsProperty, &protocols);
32  RegisterProperty(nfc_adapter::kTagsProperty, &tags);
33  RegisterProperty(nfc_adapter::kDevicesProperty, &devices);
34}
35
36NfcAdapterClient::Properties::~Properties() {
37}
38
39// The NfcAdapterClient implementation used in production.
40class NfcAdapterClientImpl
41    : public NfcAdapterClient,
42      public NfcManagerClient::Observer,
43      public nfc_client_helpers::DBusObjectMap::Delegate {
44 public:
45  explicit NfcAdapterClientImpl(NfcManagerClient* manager_client)
46      : bus_(NULL),
47        manager_client_(manager_client),
48        weak_ptr_factory_(this) {
49    DCHECK(manager_client);
50  }
51
52  virtual ~NfcAdapterClientImpl() {
53    manager_client_->RemoveObserver(this);
54  }
55
56  // NfcAdapterClient override.
57  virtual void AddObserver(NfcAdapterClient::Observer* observer) OVERRIDE {
58    DCHECK(observer);
59    observers_.AddObserver(observer);
60  }
61
62  // NfcAdapterClient override.
63  virtual void RemoveObserver(NfcAdapterClient::Observer* observer) OVERRIDE {
64    DCHECK(observer);
65    observers_.RemoveObserver(observer);
66  }
67
68  // NfcAdapterClient override.
69  virtual Properties* GetProperties(const dbus::ObjectPath& object_path)
70      OVERRIDE {
71    return static_cast<Properties*>(
72        object_map_->GetObjectProperties(object_path));
73  }
74
75  // NfcAdapterClient override.
76  virtual void StartPollLoop(
77      const dbus::ObjectPath& object_path,
78      const std::string& mode,
79      const base::Closure& callback,
80      const nfc_client_helpers::ErrorCallback& error_callback) OVERRIDE {
81    dbus::ObjectProxy* object_proxy = object_map_->GetObjectProxy(object_path);
82    if (!object_proxy) {
83      std::string error_message =
84          base::StringPrintf("NFC adapter with object path \"%s\" does not "
85                             "exist.", object_path.value().c_str());
86      LOG(ERROR) << error_message;
87      error_callback.Run(nfc_client_helpers::kUnknownObjectError,
88                         error_message);
89      return;
90    }
91    dbus::MethodCall method_call(nfc_adapter::kNfcAdapterInterface,
92                                 nfc_adapter::kStartPollLoop);
93    dbus::MessageWriter writer(&method_call);
94    writer.AppendString(mode);
95    object_proxy->CallMethodWithErrorCallback(
96        &method_call,
97        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
98        base::Bind(&nfc_client_helpers::OnSuccess, callback),
99        base::Bind(&nfc_client_helpers::OnError, error_callback));
100  }
101
102  // NfcAdapterClient override.
103  virtual void StopPollLoop(
104      const dbus::ObjectPath& object_path,
105      const base::Closure& callback,
106      const nfc_client_helpers::ErrorCallback& error_callback) OVERRIDE {
107    dbus::ObjectProxy* object_proxy = object_map_->GetObjectProxy(object_path);
108    if (!object_proxy) {
109      std::string error_message =
110          base::StringPrintf("NFC adapter with object path \"%s\" does not "
111                             "exist.", object_path.value().c_str());
112      LOG(ERROR) << error_message;
113      error_callback.Run(nfc_client_helpers::kUnknownObjectError,
114                         error_message);
115      return;
116    }
117    dbus::MethodCall method_call(nfc_adapter::kNfcAdapterInterface,
118                                 nfc_adapter::kStopPollLoop);
119    object_proxy->CallMethodWithErrorCallback(
120        &method_call,
121        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
122        base::Bind(&nfc_client_helpers::OnSuccess, callback),
123        base::Bind(&nfc_client_helpers::OnError, error_callback));
124  }
125
126 protected:
127  // DBusClient override.
128  virtual void Init(dbus::Bus* bus) OVERRIDE {
129    VLOG(1) << "Creating NfcAdapterClientImpl";
130    DCHECK(bus);
131    bus_ = bus;
132    object_map_.reset(new nfc_client_helpers::DBusObjectMap(
133        nfc_adapter::kNfcAdapterServiceName, this, bus));
134    DCHECK(manager_client_);
135    manager_client_->AddObserver(this);
136  }
137
138 private:
139  // NfcManagerClient::Observer override.
140  virtual void ManagerPropertyChanged(
141      const std::string& property_name) OVERRIDE {
142    // Update the adapter proxies.
143    DCHECK(manager_client_);
144    NfcManagerClient::Properties* manager_properties =
145        manager_client_->GetProperties();
146
147    // Ignore changes to properties other than "Adapters".
148    if (property_name != manager_properties->adapters.name())
149      return;
150
151    VLOG(1) << "NFC adapters changed.";
152
153    // Update the known adapters.
154    const std::vector<dbus::ObjectPath>& received_adapters =
155        manager_properties->adapters.value();
156    object_map_->UpdateObjects(received_adapters);
157  }
158
159  // nfc_client_helpers::DBusObjectMap::Delegate override.
160  virtual NfcPropertySet* CreateProperties(
161      dbus::ObjectProxy* object_proxy) OVERRIDE {
162    return new Properties(
163        object_proxy,
164        base::Bind(&NfcAdapterClientImpl::OnPropertyChanged,
165                   weak_ptr_factory_.GetWeakPtr(),
166                   object_proxy->object_path()));
167  }
168
169  // nfc_client_helpers::DBusObjectMap::Delegate override.
170  virtual void ObjectAdded(const dbus::ObjectPath& object_path) OVERRIDE {
171    FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_,
172                      AdapterAdded(object_path));
173  }
174
175  virtual void ObjectRemoved(const dbus::ObjectPath& object_path) OVERRIDE {
176    FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_,
177                      AdapterRemoved(object_path));
178  }
179
180  // Called by NfcPropertySet when a property value is changed, either by
181  // result of a signal or response to a GetAll() or Get() call.
182  void OnPropertyChanged(const dbus::ObjectPath& object_path,
183                         const std::string& property_name) {
184    VLOG(1) << "Adapter property changed; Path: " << object_path.value()
185            << " Property: " << property_name;
186    FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_,
187                      AdapterPropertyChanged(object_path, property_name));
188  }
189
190  // We maintain a pointer to the bus to be able to request proxies for
191  // new NFC adapters that appear.
192  dbus::Bus* bus_;
193
194  // Mapping from object paths to object proxies and properties structures that
195  // were already created by us.
196  scoped_ptr<nfc_client_helpers::DBusObjectMap> object_map_;
197
198  // The manager client that we listen to events notifications from.
199  NfcManagerClient* manager_client_;
200
201  // List of observers interested in event notifications.
202  ObserverList<NfcAdapterClient::Observer> observers_;
203
204  // Weak pointer factory for generating 'this' pointers that might live longer
205  // than we do.
206  // Note: This should remain the last member so it'll be destroyed and
207  // invalidate its weak pointers before any other members are destroyed.
208  base::WeakPtrFactory<NfcAdapterClientImpl> weak_ptr_factory_;
209
210  DISALLOW_COPY_AND_ASSIGN(NfcAdapterClientImpl);
211};
212
213NfcAdapterClient::NfcAdapterClient() {
214}
215
216NfcAdapterClient::~NfcAdapterClient() {
217}
218
219NfcAdapterClient* NfcAdapterClient::Create(DBusClientImplementationType type,
220                                           NfcManagerClient* manager_client) {
221  if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
222    return new NfcAdapterClientImpl(manager_client);
223  DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
224  return new FakeNfcAdapterClient();
225}
226
227}  // namespace chromeos
228