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