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_device_client.h" 6 7#include "base/bind.h" 8#include "base/memory/weak_ptr.h" 9#include "base/observer_list.h" 10#include "base/strings/stringprintf.h" 11#include "chromeos/dbus/nfc_adapter_client.h" 12#include "dbus/bus.h" 13#include "dbus/message.h" 14#include "dbus/values_util.h" 15#include "third_party/cros_system_api/dbus/service_constants.h" 16 17using chromeos::nfc_client_helpers::DBusObjectMap; 18using chromeos::nfc_client_helpers::ObjectProxyTree; 19 20namespace chromeos { 21 22NfcDeviceClient::Properties::Properties( 23 dbus::ObjectProxy* object_proxy, 24 const PropertyChangedCallback& callback) 25 : NfcPropertySet(object_proxy, 26 nfc_device::kNfcDeviceInterface, 27 callback) { 28 RegisterProperty(nfc_device::kRecordsProperty, &records); 29} 30 31NfcDeviceClient::Properties::~Properties() { 32} 33 34// The NfcDeviceClient implementation used in production. 35class NfcDeviceClientImpl : public NfcDeviceClient, 36 public NfcAdapterClient::Observer, 37 public DBusObjectMap::Delegate { 38 public: 39 explicit NfcDeviceClientImpl(NfcAdapterClient* adapter_client) 40 : bus_(NULL), 41 adapter_client_(adapter_client), 42 weak_ptr_factory_(this) { 43 DCHECK(adapter_client); 44 } 45 46 virtual ~NfcDeviceClientImpl() { 47 DCHECK(adapter_client_); 48 adapter_client_->RemoveObserver(this); 49 } 50 51 // NfcDeviceClient override. 52 virtual void AddObserver(NfcDeviceClient::Observer* observer) OVERRIDE { 53 DCHECK(observer); 54 observers_.AddObserver(observer); 55 } 56 57 // NfcDeviceClient override. 58 virtual void RemoveObserver(NfcDeviceClient::Observer* observer) OVERRIDE { 59 DCHECK(observer); 60 observers_.RemoveObserver(observer); 61 } 62 63 // NfcDeviceClient override. 64 virtual std::vector<dbus::ObjectPath> GetDevicesForAdapter( 65 const dbus::ObjectPath& adapter_path) OVERRIDE { 66 DBusObjectMap* object_map = 67 adapters_to_object_maps_.GetObjectMap(adapter_path); 68 if (!object_map) 69 return std::vector<dbus::ObjectPath>(); 70 return object_map->GetObjectPaths(); 71 } 72 73 // NfcDeviceClient override. 74 virtual Properties* GetProperties( 75 const dbus::ObjectPath& object_path) OVERRIDE { 76 return static_cast<Properties*>( 77 adapters_to_object_maps_.FindObjectProperties(object_path)); 78 } 79 80 // NfcDeviceClient override. 81 virtual void Push( 82 const dbus::ObjectPath& object_path, 83 const base::DictionaryValue& attributes, 84 const base::Closure& callback, 85 const nfc_client_helpers::ErrorCallback& error_callback) OVERRIDE { 86 dbus::ObjectProxy* object_proxy = 87 adapters_to_object_maps_.FindObjectProxy(object_path); 88 if (!object_proxy) { 89 std::string error_message = 90 base::StringPrintf( 91 "NFC device with object path \"%s\" does not exist.", 92 object_path.value().c_str()); 93 LOG(ERROR) << error_message; 94 error_callback.Run(nfc_client_helpers::kUnknownObjectError, 95 error_message); 96 return; 97 } 98 99 // |attributes| should not be empty. 100 if (attributes.empty()) { 101 std::string error_message = 102 "Cannot push data to device with empty arguments."; 103 LOG(ERROR) << error_message; 104 error_callback.Run(nfc_error::kInvalidArguments, error_message); 105 return; 106 } 107 108 // Create the arguments. 109 dbus::MethodCall method_call(nfc_device::kNfcDeviceInterface, 110 nfc_device::kPush); 111 dbus::MessageWriter writer(&method_call); 112 dbus::AppendValueData(&writer, attributes); 113 114 object_proxy->CallMethodWithErrorCallback( 115 &method_call, 116 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 117 base::Bind(&nfc_client_helpers::OnSuccess, callback), 118 base::Bind(&nfc_client_helpers::OnError, error_callback)); 119 } 120 121 protected: 122 // DBusClient override. 123 virtual void Init(dbus::Bus* bus) OVERRIDE { 124 VLOG(1) << "Creating NfcDeviceClientImpl"; 125 DCHECK(bus); 126 bus_ = bus; 127 DCHECK(adapter_client_); 128 adapter_client_->AddObserver(this); 129 } 130 131 private: 132 // NfcAdapterClient::Observer override. 133 virtual void AdapterAdded(const dbus::ObjectPath& object_path) OVERRIDE { 134 VLOG(1) << "Adapter added. Creating map for device proxies belonging to " 135 << "adapter: " << object_path.value(); 136 adapters_to_object_maps_.CreateObjectMap( 137 object_path, nfc_device::kNfcDeviceServiceName, this, bus_); 138 } 139 140 // NfcAdapterClient::Observer override. 141 virtual void AdapterRemoved(const dbus::ObjectPath& object_path) OVERRIDE { 142 // Neard doesn't send out property changed signals for the devices that 143 // are removed when the adapter they belong to is removed. Clean up the 144 // object proxies for devices that are managed by the removed adapter. 145 // Note: DBusObjectMap guarantees that the Properties structure for the 146 // removed adapter will be valid before this method returns. 147 VLOG(1) << "Adapter removed. Cleaning up device proxies belonging to " 148 << "adapter: " << object_path.value(); 149 adapters_to_object_maps_.RemoveObjectMap(object_path); 150 } 151 152 // NfcAdapterClient::Observer override. 153 virtual void AdapterPropertyChanged( 154 const dbus::ObjectPath& object_path, 155 const std::string& property_name) OVERRIDE { 156 DCHECK(adapter_client_); 157 NfcAdapterClient::Properties *adapter_properties = 158 adapter_client_->GetProperties(object_path); 159 DCHECK(adapter_properties); 160 161 // Ignore changes to properties other than "Devices". 162 if (property_name != adapter_properties->devices.name()) 163 return; 164 165 // Update the known devices. 166 VLOG(1) << "NFC devices changed."; 167 const std::vector<dbus::ObjectPath>& received_devices = 168 adapter_properties->devices.value(); 169 DBusObjectMap* object_map = 170 adapters_to_object_maps_.GetObjectMap(object_path); 171 DCHECK(object_map); 172 object_map->UpdateObjects(received_devices); 173 } 174 175 // nfc_client_helpers::DBusObjectMap::Delegate override. 176 virtual NfcPropertySet* CreateProperties( 177 dbus::ObjectProxy* object_proxy) OVERRIDE { 178 return new Properties( 179 object_proxy, 180 base::Bind(&NfcDeviceClientImpl::OnPropertyChanged, 181 weak_ptr_factory_.GetWeakPtr(), 182 object_proxy->object_path())); 183 } 184 185 // nfc_client_helpers::DBusObjectMap::Delegate override. 186 virtual void ObjectAdded(const dbus::ObjectPath& object_path) OVERRIDE { 187 FOR_EACH_OBSERVER(NfcDeviceClient::Observer, observers_, 188 DeviceAdded(object_path)); 189 } 190 191 virtual void ObjectRemoved(const dbus::ObjectPath& object_path) OVERRIDE { 192 FOR_EACH_OBSERVER(NfcDeviceClient::Observer, observers_, 193 DeviceRemoved(object_path)); 194 } 195 196 // Called by NfcPropertySet when a property value is changed, either by 197 // result of a signal or response to a GetAll() or Get() call. 198 void OnPropertyChanged(const dbus::ObjectPath& object_path, 199 const std::string& property_name) { 200 VLOG(1) << "Device property changed; Path: " << object_path.value() 201 << " Property: " << property_name; 202 FOR_EACH_OBSERVER(NfcDeviceClient::Observer, observers_, 203 DevicePropertyChanged(object_path, property_name)); 204 } 205 206 // We maintain a pointer to the bus to be able to request proxies for 207 // new NFC devices that appear. 208 dbus::Bus* bus_; 209 210 // List of observers interested in event notifications. 211 ObserverList<NfcDeviceClient::Observer> observers_; 212 213 // Mapping from object paths to object proxies and properties structures that 214 // were already created by us. This stucture stores a different DBusObjectMap 215 // for each known NFC adapter object path. 216 ObjectProxyTree adapters_to_object_maps_; 217 218 // The adapter client that we listen to events notifications from. 219 NfcAdapterClient* adapter_client_; 220 221 // Weak pointer factory for generating 'this' pointers that might live longer 222 // than we do. 223 // Note: This should remain the last member so it'll be destroyed and 224 // invalidate its weak pointers before any other members are destroyed. 225 base::WeakPtrFactory<NfcDeviceClientImpl> weak_ptr_factory_; 226 227 DISALLOW_COPY_AND_ASSIGN(NfcDeviceClientImpl); 228}; 229 230NfcDeviceClient::NfcDeviceClient() { 231} 232 233NfcDeviceClient::~NfcDeviceClient() { 234} 235 236NfcDeviceClient* NfcDeviceClient::Create(NfcAdapterClient* adapter_client) { 237 return new NfcDeviceClientImpl(adapter_client); 238} 239 240} // namespace chromeos 241