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_adapter_client.h"
      6 
      7 #include <map>
      8 #include <utility>
      9 
     10 #include "base/bind.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/observer_list.h"
     13 #include "base/strings/stringprintf.h"
     14 #include "chromeos/dbus/nfc_manager_client.h"
     15 #include "dbus/bus.h"
     16 #include "dbus/message.h"
     17 #include "third_party/cros_system_api/dbus/service_constants.h"
     18 
     19 namespace chromeos {
     20 
     21 NfcAdapterClient::Properties::Properties(
     22     dbus::ObjectProxy* object_proxy,
     23     const PropertyChangedCallback& callback)
     24     : NfcPropertySet(object_proxy,
     25                      nfc_adapter::kNfcAdapterInterface,
     26                      callback) {
     27   RegisterProperty(nfc_adapter::kModeProperty, &mode);
     28   RegisterProperty(nfc_adapter::kPoweredProperty, &powered);
     29   RegisterProperty(nfc_adapter::kPollingProperty, &polling);
     30   RegisterProperty(nfc_adapter::kProtocolsProperty, &protocols);
     31   RegisterProperty(nfc_adapter::kTagsProperty, &tags);
     32   RegisterProperty(nfc_adapter::kDevicesProperty, &devices);
     33 }
     34 
     35 NfcAdapterClient::Properties::~Properties() {
     36 }
     37 
     38 // The NfcAdapterClient implementation used in production.
     39 class NfcAdapterClientImpl
     40     : public NfcAdapterClient,
     41       public NfcManagerClient::Observer,
     42       public nfc_client_helpers::DBusObjectMap::Delegate {
     43  public:
     44   explicit NfcAdapterClientImpl(NfcManagerClient* manager_client)
     45       : bus_(NULL),
     46         manager_client_(manager_client),
     47         weak_ptr_factory_(this) {
     48     DCHECK(manager_client);
     49   }
     50 
     51   virtual ~NfcAdapterClientImpl() {
     52     manager_client_->RemoveObserver(this);
     53   }
     54 
     55   // NfcAdapterClient override.
     56   virtual void AddObserver(NfcAdapterClient::Observer* observer) OVERRIDE {
     57     DCHECK(observer);
     58     observers_.AddObserver(observer);
     59   }
     60 
     61   // NfcAdapterClient override.
     62   virtual void RemoveObserver(NfcAdapterClient::Observer* observer) OVERRIDE {
     63     DCHECK(observer);
     64     observers_.RemoveObserver(observer);
     65   }
     66 
     67   // NfcAdapterClient override.
     68   virtual std::vector<dbus::ObjectPath> GetAdapters() OVERRIDE {
     69     return object_map_->GetObjectPaths();
     70   }
     71 
     72   // NfcAdapterClient override.
     73   virtual Properties* GetProperties(const dbus::ObjectPath& object_path)
     74       OVERRIDE {
     75     return static_cast<Properties*>(
     76         object_map_->GetObjectProperties(object_path));
     77   }
     78 
     79   // NfcAdapterClient override.
     80   virtual void StartPollLoop(
     81       const dbus::ObjectPath& object_path,
     82       const std::string& mode,
     83       const base::Closure& callback,
     84       const nfc_client_helpers::ErrorCallback& error_callback) OVERRIDE {
     85     dbus::ObjectProxy* object_proxy = object_map_->GetObjectProxy(object_path);
     86     if (!object_proxy) {
     87       std::string error_message =
     88           base::StringPrintf("NFC adapter with object path \"%s\" does not "
     89                              "exist.", object_path.value().c_str());
     90       LOG(ERROR) << error_message;
     91       error_callback.Run(nfc_client_helpers::kUnknownObjectError,
     92                          error_message);
     93       return;
     94     }
     95     dbus::MethodCall method_call(nfc_adapter::kNfcAdapterInterface,
     96                                  nfc_adapter::kStartPollLoop);
     97     dbus::MessageWriter writer(&method_call);
     98     writer.AppendString(mode);
     99     object_proxy->CallMethodWithErrorCallback(
    100         &method_call,
    101         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    102         base::Bind(&nfc_client_helpers::OnSuccess, callback),
    103         base::Bind(&nfc_client_helpers::OnError, error_callback));
    104   }
    105 
    106   // NfcAdapterClient override.
    107   virtual void StopPollLoop(
    108       const dbus::ObjectPath& object_path,
    109       const base::Closure& callback,
    110       const nfc_client_helpers::ErrorCallback& error_callback) OVERRIDE {
    111     dbus::ObjectProxy* object_proxy = object_map_->GetObjectProxy(object_path);
    112     if (!object_proxy) {
    113       std::string error_message =
    114           base::StringPrintf("NFC adapter with object path \"%s\" does not "
    115                              "exist.", object_path.value().c_str());
    116       LOG(ERROR) << error_message;
    117       error_callback.Run(nfc_client_helpers::kUnknownObjectError,
    118                          error_message);
    119       return;
    120     }
    121     dbus::MethodCall method_call(nfc_adapter::kNfcAdapterInterface,
    122                                  nfc_adapter::kStopPollLoop);
    123     object_proxy->CallMethodWithErrorCallback(
    124         &method_call,
    125         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    126         base::Bind(&nfc_client_helpers::OnSuccess, callback),
    127         base::Bind(&nfc_client_helpers::OnError, error_callback));
    128   }
    129 
    130  protected:
    131   // DBusClient override.
    132   virtual void Init(dbus::Bus* bus) OVERRIDE {
    133     VLOG(1) << "Creating NfcAdapterClientImpl";
    134     DCHECK(bus);
    135     bus_ = bus;
    136     object_map_.reset(new nfc_client_helpers::DBusObjectMap(
    137         nfc_adapter::kNfcAdapterServiceName, this, bus));
    138     DCHECK(manager_client_);
    139     manager_client_->AddObserver(this);
    140   }
    141 
    142  private:
    143   // NfcManagerClient::Observer override.
    144   virtual void ManagerPropertyChanged(
    145       const std::string& property_name) OVERRIDE {
    146     // Update the adapter proxies.
    147     DCHECK(manager_client_);
    148     NfcManagerClient::Properties* manager_properties =
    149         manager_client_->GetProperties();
    150 
    151     // Ignore changes to properties other than "Adapters".
    152     if (property_name != manager_properties->adapters.name())
    153       return;
    154 
    155     // Update the known adapters.
    156     VLOG(1) << "NFC adapters changed.";
    157     const std::vector<dbus::ObjectPath>& received_adapters =
    158         manager_properties->adapters.value();
    159     object_map_->UpdateObjects(received_adapters);
    160   }
    161 
    162   // nfc_client_helpers::DBusObjectMap::Delegate override.
    163   virtual NfcPropertySet* CreateProperties(
    164       dbus::ObjectProxy* object_proxy) OVERRIDE {
    165     return new Properties(
    166         object_proxy,
    167         base::Bind(&NfcAdapterClientImpl::OnPropertyChanged,
    168                    weak_ptr_factory_.GetWeakPtr(),
    169                    object_proxy->object_path()));
    170   }
    171 
    172   // nfc_client_helpers::DBusObjectMap::Delegate override.
    173   virtual void ObjectAdded(const dbus::ObjectPath& object_path) OVERRIDE {
    174     FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_,
    175                       AdapterAdded(object_path));
    176   }
    177 
    178   // nfc_client_helpers::DBusObjectMap::Delegate override.
    179   virtual void ObjectRemoved(const dbus::ObjectPath& object_path) OVERRIDE {
    180     FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_,
    181                       AdapterRemoved(object_path));
    182   }
    183 
    184   // Called by NfcPropertySet when a property value is changed, either by
    185   // result of a signal or response to a GetAll() or Get() call.
    186   void OnPropertyChanged(const dbus::ObjectPath& object_path,
    187                          const std::string& property_name) {
    188     VLOG(1) << "Adapter property changed; Path: " << object_path.value()
    189             << " Property: " << property_name;
    190     FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_,
    191                       AdapterPropertyChanged(object_path, property_name));
    192   }
    193 
    194   // We maintain a pointer to the bus to be able to request proxies for
    195   // new NFC adapters that appear.
    196   dbus::Bus* bus_;
    197 
    198   // List of observers interested in event notifications.
    199   ObserverList<NfcAdapterClient::Observer> observers_;
    200 
    201   // Mapping from object paths to object proxies and properties structures that
    202   // were already created by us.
    203   scoped_ptr<nfc_client_helpers::DBusObjectMap> object_map_;
    204 
    205   // The manager client that we listen to events notifications from.
    206   NfcManagerClient* manager_client_;
    207 
    208   // Weak pointer factory for generating 'this' pointers that might live longer
    209   // than we do.
    210   // Note: This should remain the last member so it'll be destroyed and
    211   // invalidate its weak pointers before any other members are destroyed.
    212   base::WeakPtrFactory<NfcAdapterClientImpl> weak_ptr_factory_;
    213 
    214   DISALLOW_COPY_AND_ASSIGN(NfcAdapterClientImpl);
    215 };
    216 
    217 NfcAdapterClient::NfcAdapterClient() {
    218 }
    219 
    220 NfcAdapterClient::~NfcAdapterClient() {
    221 }
    222 
    223 NfcAdapterClient* NfcAdapterClient::Create(NfcManagerClient* manager_client) {
    224   return new NfcAdapterClientImpl(manager_client);
    225 }
    226 
    227 }  // namespace chromeos
    228