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