nfc_adapter_client.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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/fake_nfc_adapter_client.h" 15#include "chromeos/dbus/nfc_manager_client.h" 16#include "dbus/bus.h" 17#include "dbus/message.h" 18#include "third_party/cros_system_api/dbus/service_constants.h" 19 20namespace chromeos { 21 22NfcAdapterClient::Properties::Properties( 23 dbus::ObjectProxy* object_proxy, 24 const PropertyChangedCallback& callback) 25 : NfcPropertySet(object_proxy, 26 nfc_adapter::kNfcAdapterInterface, 27 callback) { 28 RegisterProperty(nfc_adapter::kModeProperty, &mode); 29 RegisterProperty(nfc_adapter::kPoweredProperty, &powered); 30 RegisterProperty(nfc_adapter::kPollingProperty, &polling); 31 RegisterProperty(nfc_adapter::kProtocolsProperty, &protocols); 32 RegisterProperty(nfc_adapter::kTagsProperty, &tags); 33 RegisterProperty(nfc_adapter::kDevicesProperty, &devices); 34} 35 36NfcAdapterClient::Properties::~Properties() { 37} 38 39// The NfcAdapterClient implementation used in production. 40class NfcAdapterClientImpl 41 : public NfcAdapterClient, 42 public NfcManagerClient::Observer, 43 public nfc_client_helpers::DBusObjectMap::Delegate { 44 public: 45 explicit NfcAdapterClientImpl(NfcManagerClient* manager_client) 46 : initial_adapters_received_(false), 47 bus_(NULL), 48 manager_client_(manager_client), 49 weak_ptr_factory_(this) { 50 DCHECK(manager_client); 51 } 52 53 virtual ~NfcAdapterClientImpl() { 54 manager_client_->RemoveObserver(this); 55 } 56 57 // NfcAdapterClient override. 58 virtual void AddObserver(NfcAdapterClient::Observer* observer) OVERRIDE { 59 DCHECK(observer); 60 observers_.AddObserver(observer); 61 } 62 63 // NfcAdapterClient override. 64 virtual void RemoveObserver(NfcAdapterClient::Observer* observer) OVERRIDE { 65 DCHECK(observer); 66 observers_.RemoveObserver(observer); 67 } 68 69 // NfcAdapterClient override. 70 virtual Properties* GetProperties(const dbus::ObjectPath& object_path) 71 OVERRIDE { 72 return static_cast<Properties*>( 73 object_map_->GetObjectProperties(object_path)); 74 } 75 76 // NfcAdapterClient override. 77 virtual void StartPollLoop( 78 const dbus::ObjectPath& object_path, 79 const std::string& mode, 80 const base::Closure& callback, 81 const nfc_client_helpers::ErrorCallback& error_callback) OVERRIDE { 82 dbus::ObjectProxy* object_proxy = object_map_->GetObjectProxy(object_path); 83 if (!object_proxy) { 84 std::string error_message = 85 base::StringPrintf("NFC adapter with object path \"%s\" does not " 86 "exist.", object_path.value().c_str()); 87 LOG(ERROR) << error_message; 88 error_callback.Run(nfc_client_helpers::kUnknownObjectError, 89 error_message); 90 return; 91 } 92 dbus::MethodCall method_call(nfc_adapter::kNfcAdapterInterface, 93 nfc_adapter::kStartPollLoop); 94 dbus::MessageWriter writer(&method_call); 95 writer.AppendString(mode); 96 object_proxy->CallMethodWithErrorCallback( 97 &method_call, 98 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 99 base::Bind(&nfc_client_helpers::OnSuccess, callback), 100 base::Bind(&nfc_client_helpers::OnError, error_callback)); 101 } 102 103 // NfcAdapterClient override. 104 virtual void StopPollLoop( 105 const dbus::ObjectPath& object_path, 106 const base::Closure& callback, 107 const nfc_client_helpers::ErrorCallback& error_callback) OVERRIDE { 108 dbus::ObjectProxy* object_proxy = object_map_->GetObjectProxy(object_path); 109 if (!object_proxy) { 110 std::string error_message = 111 base::StringPrintf("NFC adapter with object path \"%s\" does not " 112 "exist.", object_path.value().c_str()); 113 LOG(ERROR) << error_message; 114 error_callback.Run(nfc_client_helpers::kUnknownObjectError, 115 error_message); 116 return; 117 } 118 dbus::MethodCall method_call(nfc_adapter::kNfcAdapterInterface, 119 nfc_adapter::kStopPollLoop); 120 object_proxy->CallMethodWithErrorCallback( 121 &method_call, 122 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 123 base::Bind(&nfc_client_helpers::OnSuccess, callback), 124 base::Bind(&nfc_client_helpers::OnError, error_callback)); 125 } 126 127 protected: 128 // DBusClient override. 129 virtual void Init(dbus::Bus* bus) OVERRIDE { 130 VLOG(1) << "Creating NfcAdapterClientImpl"; 131 DCHECK(bus); 132 bus_ = bus; 133 object_map_.reset(new nfc_client_helpers::DBusObjectMap( 134 nfc_adapter::kNfcAdapterServiceName, this, bus)); 135 DCHECK(manager_client_); 136 manager_client_->AddObserver(this); 137 } 138 139 private: 140 // NfcManagerClient::Observer override. 141 virtual void AdapterAdded(const dbus::ObjectPath& object_path) OVERRIDE { 142 VLOG(1) << "AdapterAdded: " << object_path.value(); 143 // Initialize the object proxy here, so that observers can start receiving 144 // notifications for it and it is cached for reuse. Note that, even if we 145 // miss this signal, a proxy will be created on demand for any object paths 146 // that are passed to the public methods later. 147 object_map_->AddObject(object_path); 148 FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_, 149 AdapterAdded(object_path)); 150 } 151 152 // NfcManagerClient::Observer override. 153 virtual void AdapterRemoved(const dbus::ObjectPath& object_path) OVERRIDE { 154 VLOG(1) << "AdapterRemoved: " << object_path.value(); 155 // Remove the object proxy, as we know that the adapter no longer exists. 156 // Note that this doesn't prevent a client from recreating a proxy for an 157 // object path that is no longer valid, as proxies are created on demand as 158 // necessary by the public methods. 159 object_map_->RemoveObject(object_path); 160 FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_, 161 AdapterRemoved(object_path)); 162 } 163 164 // NfcManagerClient::Observer override. 165 virtual void ManagerPropertyChanged(const std::string& property_name) 166 OVERRIDE { 167 NfcManagerClient::Properties* manager_properties = 168 manager_client_->GetProperties(); 169 if (!initial_adapters_received_ && 170 property_name == manager_properties->adapters.name()) { 171 initial_adapters_received_ = true; 172 VLOG(1) << "Initial set of adapters received."; 173 // Create proxies for all adapters that are known to the manager, so that 174 // observers can start getting notified for any signals emitted by 175 // adapters. We use the PropertyChanged signal from manager only to 176 // create proxies for the initial fetch. We rely on the AdapterAdded and 177 // AdapterRemoved signals after that. 178 std::vector<dbus::ObjectPath> adapters = 179 manager_properties->adapters.value(); 180 for (std::vector<dbus::ObjectPath>::iterator iter = adapters.begin(); 181 iter != adapters.end(); ++iter) { 182 VLOG(1) << "Creating proxy for: " << iter->value(); 183 object_map_->AddObject(*iter); 184 } 185 } 186 } 187 188 // nfc_client_helpers::DBusObjectMap::Delegate override. 189 virtual NfcPropertySet* CreateProperties( 190 dbus::ObjectProxy* object_proxy) OVERRIDE { 191 return new Properties( 192 object_proxy, 193 base::Bind(&NfcAdapterClientImpl::OnPropertyChanged, 194 weak_ptr_factory_.GetWeakPtr(), 195 object_proxy->object_path())); 196 } 197 198 // Called by NfcPropertySet when a property value is changed, either by 199 // result of a signal or response to a GetAll() or Get() call. 200 void OnPropertyChanged(const dbus::ObjectPath& object_path, 201 const std::string& property_name) { 202 VLOG(1) << "Adapter property changed; Path: " << object_path.value() 203 << " Property: " << property_name; 204 FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_, 205 AdapterPropertyChanged(object_path, property_name)); 206 } 207 208 // This variable stores whether or not we have ever been notified of 209 // ManagerPropertiesChanged. This is used to bootstrap adapter proxies 210 // after receiving the initial set of properties from the NFC manager. 211 bool initial_adapters_received_; 212 213 // We maintain a pointer to the bus to be able to request proxies for 214 // new NFC adapters that appear. 215 dbus::Bus* bus_; 216 217 // Mapping from object paths to object proxies and properties structures that 218 // were already created by us. 219 scoped_ptr<nfc_client_helpers::DBusObjectMap> object_map_; 220 221 // The manager client that we listen to events notifications from. 222 NfcManagerClient* manager_client_; 223 224 // List of observers interested in event notifications. 225 ObserverList<NfcAdapterClient::Observer> observers_; 226 227 // Weak pointer factory for generating 'this' pointers that might live longer 228 // than we do. 229 // Note: This should remain the last member so it'll be destroyed and 230 // invalidate its weak pointers before any other members are destroyed. 231 base::WeakPtrFactory<NfcAdapterClientImpl> weak_ptr_factory_; 232 233 DISALLOW_COPY_AND_ASSIGN(NfcAdapterClientImpl); 234}; 235 236NfcAdapterClient::NfcAdapterClient() { 237} 238 239NfcAdapterClient::~NfcAdapterClient() { 240} 241 242NfcAdapterClient* NfcAdapterClient::Create(DBusClientImplementationType type, 243 NfcManagerClient* manager_client) { 244 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) 245 return new NfcAdapterClientImpl(manager_client); 246 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); 247 return new FakeNfcAdapterClient(); 248} 249 250} // namespace chromeos 251