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_record_client.h" 6 7#include "base/bind.h" 8#include "base/memory/weak_ptr.h" 9#include "base/observer_list.h" 10#include "chromeos/dbus/nfc_device_client.h" 11#include "chromeos/dbus/nfc_tag_client.h" 12#include "dbus/bus.h" 13#include "third_party/cros_system_api/dbus/service_constants.h" 14 15using chromeos::nfc_client_helpers::DBusObjectMap; 16using chromeos::nfc_client_helpers::ObjectProxyTree; 17 18namespace chromeos { 19 20NfcRecordClient::Properties::Properties( 21 dbus::ObjectProxy* object_proxy, 22 const PropertyChangedCallback& callback) 23 : NfcPropertySet(object_proxy, 24 nfc_record::kNfcRecordInterface, 25 callback) { 26 RegisterProperty(nfc_record::kTypeProperty, &type); 27 RegisterProperty(nfc_record::kLanguageProperty, &language); 28 RegisterProperty(nfc_record::kEncodingProperty, &encoding); 29 RegisterProperty(nfc_record::kRepresentationProperty, &representation); 30 RegisterProperty(nfc_record::kUriProperty, &uri); 31 RegisterProperty(nfc_record::kMimeTypeProperty, &mime_type); 32 RegisterProperty(nfc_record::kSizeProperty, &size); 33 RegisterProperty(nfc_record::kActionProperty, &action); 34} 35 36NfcRecordClient::Properties::~Properties() { 37} 38 39// The NfcRecordClient implementation used in production. 40class NfcRecordClientImpl : public NfcRecordClient, 41 public NfcDeviceClient::Observer, 42 public NfcTagClient::Observer, 43 public DBusObjectMap::Delegate { 44 public: 45 explicit NfcRecordClientImpl(NfcDeviceClient* device_client, 46 NfcTagClient* tag_client) 47 : bus_(NULL), 48 device_client_(device_client), 49 tag_client_(tag_client), 50 weak_ptr_factory_(this) { 51 DCHECK(device_client); 52 DCHECK(tag_client); 53 } 54 55 virtual ~NfcRecordClientImpl() { 56 DCHECK(device_client_); 57 DCHECK(tag_client_); 58 device_client_->RemoveObserver(this); 59 tag_client_->RemoveObserver(this); 60 } 61 62 // NfcRecordClient override. 63 virtual void AddObserver(NfcRecordClient::Observer* observer) OVERRIDE { 64 DCHECK(observer); 65 observers_.AddObserver(observer); 66 } 67 68 // NfcRecordClient override. 69 virtual void RemoveObserver(NfcRecordClient::Observer* observer) OVERRIDE { 70 DCHECK(observer); 71 observers_.RemoveObserver(observer); 72 } 73 74 // NfcRecordClient override. 75 virtual Properties* GetProperties( 76 const dbus::ObjectPath& object_path) OVERRIDE { 77 return static_cast<Properties*>( 78 devices_and_tags_to_object_maps_.FindObjectProperties(object_path)); 79 } 80 81 protected: 82 // DBusClient override. 83 virtual void Init(dbus::Bus* bus) OVERRIDE { 84 VLOG(1) << "Creating NfcRecordClient impl"; 85 DCHECK(bus); 86 bus_ = bus; 87 DCHECK(device_client_); 88 DCHECK(tag_client_); 89 device_client_->AddObserver(this); 90 tag_client_->AddObserver(this); 91 } 92 93 private: 94 // NfcDeviceClient::Observer override. 95 virtual void DeviceAdded(const dbus::ObjectPath& object_path) OVERRIDE { 96 VLOG(1) << "Device added. Creating map for record proxies belonging to " 97 << "device: " << object_path.value(); 98 devices_and_tags_to_object_maps_.CreateObjectMap( 99 object_path, nfc_record::kNfcRecordServiceName, this, bus_); 100 } 101 102 // NfcDeviceClient::Observer override. 103 virtual void DeviceRemoved(const dbus::ObjectPath& object_path) OVERRIDE { 104 // Neard doesn't send out property changed signals for the records that 105 // are removed when the device they belong to is removed. Clean up the 106 // object proxies for records that belong to the removed device. 107 // Note: DBusObjectMap guarantees that the Properties structure for the 108 // removed adapter will be valid before this method returns. 109 VLOG(1) << "Device removed. Cleaning up record proxies belonging to " 110 << "device: " << object_path.value(); 111 devices_and_tags_to_object_maps_.RemoveObjectMap(object_path); 112 } 113 114 // NfcDeviceClient::Observer override. 115 virtual void DevicePropertyChanged( 116 const dbus::ObjectPath& object_path, 117 const std::string& property_name) OVERRIDE { 118 // Update the record proxies using records from the device. 119 DCHECK(device_client_); 120 NfcDeviceClient::Properties* device_properties = 121 device_client_->GetProperties(object_path); 122 123 // Ignore changes to properties other than "Records". 124 if (property_name != device_properties->records.name()) 125 return; 126 127 // Update known records. 128 VLOG(1) << "NFC records changed."; 129 const std::vector<dbus::ObjectPath>& received_records = 130 device_properties->records.value(); 131 DBusObjectMap* object_map = 132 devices_and_tags_to_object_maps_.GetObjectMap(object_path); 133 DCHECK(object_map); 134 object_map->UpdateObjects(received_records); 135 } 136 137 // NfcTagClient::Observer override. 138 virtual void TagAdded(const dbus::ObjectPath& object_path) OVERRIDE { 139 VLOG(1) << "Tag added. Creating map for record proxies belonging to " 140 << "tag: " << object_path.value(); 141 devices_and_tags_to_object_maps_.CreateObjectMap( 142 object_path, nfc_record::kNfcRecordServiceName, this, bus_); 143 } 144 145 // NfcTagClient::Observer override. 146 virtual void TagRemoved(const dbus::ObjectPath& object_path) OVERRIDE { 147 // Neard doesn't send out property changed signals for the records that 148 // are removed when the tag they belong to is removed. Clean up the 149 // object proxies for records that belong to the removed tag. 150 // Note: DBusObjectMap guarantees that the Properties structure for the 151 // removed adapter will be valid before this method returns. 152 VLOG(1) << "Tag removed. Cleaning up record proxies belonging to " 153 << "tag: " << object_path.value(); 154 devices_and_tags_to_object_maps_.RemoveObjectMap(object_path); 155 } 156 157 // NfcTagClient::Observer override. 158 virtual void TagPropertyChanged(const dbus::ObjectPath& object_path, 159 const std::string& property_name) OVERRIDE { 160 // Update the record proxies using records from the tag. 161 DCHECK(device_client_); 162 NfcTagClient::Properties* tag_properties = 163 tag_client_->GetProperties(object_path); 164 165 // Ignore changes to properties other than "Records". 166 if (property_name != tag_properties->records.name()) 167 return; 168 169 // Update known records. 170 VLOG(1) << "NFC records changed."; 171 const std::vector<dbus::ObjectPath>& received_records = 172 tag_properties->records.value(); 173 DBusObjectMap* object_map = 174 devices_and_tags_to_object_maps_.GetObjectMap(object_path); 175 DCHECK(object_map); 176 object_map->UpdateObjects(received_records); 177 178 // When rewriting the record to a tag, neard fires a property changed 179 // signal for the tags "Records" property, without creating a new object 180 // path. Sync the properties of all records here, in case Update objects 181 // doesn't do it. 182 VLOG(1) << "Fetch properties for all records."; 183 object_map->RefreshAllProperties(); 184 } 185 186 // nfc_client_helpers::DBusObjectMap::Delegate override. 187 virtual NfcPropertySet* CreateProperties( 188 dbus::ObjectProxy* object_proxy) OVERRIDE { 189 Properties* properties = new Properties( 190 object_proxy, 191 base::Bind(&NfcRecordClientImpl::OnPropertyChanged, 192 weak_ptr_factory_.GetWeakPtr(), 193 object_proxy->object_path())); 194 properties->SetAllPropertiesReceivedCallback( 195 base::Bind(&NfcRecordClientImpl::OnPropertiesReceived, 196 weak_ptr_factory_.GetWeakPtr(), 197 object_proxy->object_path())); 198 return properties; 199 } 200 201 // nfc_client_helpers::DBusObjectMap::Delegate override. 202 virtual void ObjectAdded(const dbus::ObjectPath& object_path) OVERRIDE { 203 FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, 204 RecordAdded(object_path)); 205 } 206 207 // nfc_client_helpers::DBusObjectMap::Delegate override. 208 virtual void ObjectRemoved(const dbus::ObjectPath& object_path) OVERRIDE { 209 FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, 210 RecordRemoved(object_path)); 211 } 212 213 // Called by NfcPropertySet when a property value is changed, either by 214 // result of a signal or response to a GetAll() or Get() call. 215 void OnPropertyChanged(const dbus::ObjectPath& object_path, 216 const std::string& property_name) { 217 VLOG(1) << "Record property changed; Path: " << object_path.value() 218 << " Property: " << property_name; 219 FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, 220 RecordPropertyChanged(object_path, property_name)); 221 } 222 223 // Called by NfcPropertySet when all properties have been processed as a 224 // result of a call to GetAll. 225 void OnPropertiesReceived(const dbus::ObjectPath& object_path) { 226 VLOG(1) << "All record properties received; Path: " << object_path.value(); 227 FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, 228 RecordPropertiesReceived(object_path)); 229 } 230 231 // We maintain a pointer to the bus to be able to request proxies for 232 // new NFC records that appear. 233 dbus::Bus* bus_; 234 235 // List of observers interested in event notifications. 236 ObserverList<NfcRecordClient::Observer> observers_; 237 238 // Mapping from object paths to object proxies and properties structures that 239 // were already created by us. Record objects belong to either Tag or Device 240 // objects. This structure stores a different DBusObjectMap for each known 241 // device and tag. 242 ObjectProxyTree devices_and_tags_to_object_maps_; 243 244 // The device and tag clients that we listen to events notifications from. 245 NfcDeviceClient* device_client_; 246 NfcTagClient* tag_client_; 247 // Weak pointer factory for generating 'this' pointers that might live longer 248 // than we do. 249 // Note: This should remain the last member so it'll be destroyed and 250 // invalidate its weak pointers before any other members are destroyed. 251 base::WeakPtrFactory<NfcRecordClientImpl> weak_ptr_factory_; 252 253 DISALLOW_COPY_AND_ASSIGN(NfcRecordClientImpl); 254}; 255 256NfcRecordClient::NfcRecordClient() { 257} 258 259NfcRecordClient::~NfcRecordClient() { 260} 261 262NfcRecordClient* NfcRecordClient::Create(NfcDeviceClient* device_client, 263 NfcTagClient* tag_client) { 264 return new NfcRecordClientImpl(device_client, tag_client); 265} 266 267} // namespace chromeos 268