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