Home | History | Annotate | Download | only in dbus
      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