nfc_adapter_client.cc revision f2477e01787aa58f445919b809d89e252beef54f
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    // Update the known adapters.
152    VLOG(1) << "NFC adapters changed.";
153    const std::vector<dbus::ObjectPath>& received_adapters =
154        manager_properties->adapters.value();
155    object_map_->UpdateObjects(received_adapters);
156  }
157
158  // nfc_client_helpers::DBusObjectMap::Delegate override.
159  virtual NfcPropertySet* CreateProperties(
160      dbus::ObjectProxy* object_proxy) OVERRIDE {
161    return new Properties(
162        object_proxy,
163        base::Bind(&NfcAdapterClientImpl::OnPropertyChanged,
164                   weak_ptr_factory_.GetWeakPtr(),
165                   object_proxy->object_path()));
166  }
167
168  // nfc_client_helpers::DBusObjectMap::Delegate override.
169  virtual void ObjectAdded(const dbus::ObjectPath& object_path) OVERRIDE {
170    FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_,
171                      AdapterAdded(object_path));
172  }
173
174  virtual void ObjectRemoved(const dbus::ObjectPath& object_path) OVERRIDE {
175    FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_,
176                      AdapterRemoved(object_path));
177  }
178
179  // Called by NfcPropertySet when a property value is changed, either by
180  // result of a signal or response to a GetAll() or Get() call.
181  void OnPropertyChanged(const dbus::ObjectPath& object_path,
182                         const std::string& property_name) {
183    VLOG(1) << "Adapter property changed; Path: " << object_path.value()
184            << " Property: " << property_name;
185    FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_,
186                      AdapterPropertyChanged(object_path, property_name));
187  }
188
189  // We maintain a pointer to the bus to be able to request proxies for
190  // new NFC adapters that appear.
191  dbus::Bus* bus_;
192
193  // List of observers interested in event notifications.
194  ObserverList<NfcAdapterClient::Observer> observers_;
195
196  // Mapping from object paths to object proxies and properties structures that
197  // were already created by us.
198  scoped_ptr<nfc_client_helpers::DBusObjectMap> object_map_;
199
200  // The manager client that we listen to events notifications from.
201  NfcManagerClient* manager_client_;
202
203  // Weak pointer factory for generating 'this' pointers that might live longer
204  // than we do.
205  // Note: This should remain the last member so it'll be destroyed and
206  // invalidate its weak pointers before any other members are destroyed.
207  base::WeakPtrFactory<NfcAdapterClientImpl> weak_ptr_factory_;
208
209  DISALLOW_COPY_AND_ASSIGN(NfcAdapterClientImpl);
210};
211
212NfcAdapterClient::NfcAdapterClient() {
213}
214
215NfcAdapterClient::~NfcAdapterClient() {
216}
217
218NfcAdapterClient* NfcAdapterClient::Create(DBusClientImplementationType type,
219                                           NfcManagerClient* manager_client) {
220  if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
221    return new NfcAdapterClientImpl(manager_client);
222  DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
223  return new FakeNfcAdapterClient();
224}
225
226}  // namespace chromeos
227