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