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 #ifndef CHROMEOS_DBUS_NFC_CLIENT_HELPERS_H_ 6 #define CHROMEOS_DBUS_NFC_CLIENT_HELPERS_H_ 7 8 #include <map> 9 #include <string> 10 #include <utility> 11 12 #include "base/basictypes.h" 13 #include "base/callback.h" 14 #include "base/values.h" 15 #include "chromeos/chromeos_export.h" 16 #include "chromeos/dbus/nfc_property_set.h" 17 #include "dbus/bus.h" 18 #include "dbus/message.h" 19 #include "dbus/object_path.h" 20 #include "dbus/object_proxy.h" 21 22 namespace chromeos { 23 namespace nfc_client_helpers { 24 25 // Constants used to indicate exceptional error conditions. 26 CHROMEOS_EXPORT extern const char kNoResponseError[]; 27 CHROMEOS_EXPORT extern const char kUnknownObjectError[]; 28 29 // The ErrorCallback is used by D-Bus methods to indicate failure. 30 // It receives two arguments: the name of the error in |error_name| and 31 // an optional message in |error_message|. 32 typedef base::Callback<void(const std::string& error_name, 33 const std::string& error_message)> ErrorCallback; 34 35 // A vector of object paths is used frequently among the NFC client classes. 36 // This typedef makes the type specifier a little less verbose. 37 typedef std::vector<dbus::ObjectPath> ObjectPathVector; 38 39 // Called when a response for a successful method call is received. 40 CHROMEOS_EXPORT void OnSuccess(const base::Closure& callback, 41 dbus::Response* response); 42 43 // Extracts the error data from |response| and invokes |error_callback| with 44 // the resulting error name and error message. 45 CHROMEOS_EXPORT void OnError(const ErrorCallback& error_callback, 46 dbus::ErrorResponse* response); 47 48 // Appends any value (basic types and nested types) represented by |value| to 49 // the writer |writer| as a variant type. 50 // TODO(armansito): Consider moving this to dbus/values_util.h" 51 CHROMEOS_EXPORT void AppendValueDataAsVariant(dbus::MessageWriter* writer, 52 const base::Value& value); 53 54 // DBusObjectMap is a simple data structure that facilitates keeping track of 55 // D-Bus object proxies and properties. It maintains a mapping from object 56 // paths to object proxy - property structure pairs. 57 // TODO(armansito): This is only needed until neard implements the D-Bus 58 // org.freedesktop.DBus.ObjectManager interface. Remove this once we upgrade 59 // to neard-0.14. 60 class CHROMEOS_EXPORT DBusObjectMap { 61 public: 62 // DBusObjectMap::Delegate must be implemented by classes that use an 63 // instance of DBusObjectMap to manage object proxies. 64 class Delegate { 65 public: 66 virtual ~Delegate() {} 67 68 // Called by DBusObjectMap to create a Properties structure for the remote 69 // D-Bus object accessible through |object_proxy|. The implementation class 70 // should create and return an instance of its own subclass of 71 // ::chromeos::NfcPropertySet. DBusObjectMap will handle connecting the 72 // signals and update the properties. 73 virtual NfcPropertySet* CreateProperties( 74 dbus::ObjectProxy* object_proxy) = 0; 75 76 // Notifies the delegate that an object was added with object path 77 // |object_path|. 78 virtual void ObjectAdded(const dbus::ObjectPath& object_path) {} 79 80 // Notifies the delegate that an object was removed with object path 81 // |object_path|. The object proxy will still be valid before this method 82 // returns, so that delegates can perform any clean up that use the object 83 // properties. Note that the remote object will no longer be available, 84 // but the delegates can still access the cached properties of the object. 85 virtual void ObjectRemoved(const dbus::ObjectPath& object_path) {} 86 }; 87 88 // Constructor takes in the D-Bus service name the proxies belong to and 89 // the delegate which will be used to construct properties structures. 90 // |service_name| must be a valid D-Bus service name, and |delegate| cannot 91 // be NULL. 92 DBusObjectMap(const std::string& service_name, 93 Delegate* delegate, 94 dbus::Bus* bus); 95 96 // Destructor destroys all managed object proxies and notifies the delegate 97 // for each removed object. 98 virtual ~DBusObjectMap(); 99 100 // Returns the object proxy for object path |object_path|. If no object proxy 101 // exists for |object_path|, returns NULL. 102 dbus::ObjectProxy* GetObjectProxy(const dbus::ObjectPath& object_path); 103 104 // Returns the properties structure for remote object with object path 105 // |object_path|. If no properties structure exists for |object_path|, 106 // returns NULL. 107 NfcPropertySet* GetObjectProperties(const dbus::ObjectPath& object_path); 108 109 // Updates the object proxies from the given list of object paths 110 // |object_paths|. It notifies the delegate of each added and removed object 111 // via |Delegate::ObjectAdded| and |Delegate::ObjectRemoved|. 112 void UpdateObjects(const ObjectPathVector& object_paths); 113 114 // Creates and stores an object proxy and properties structure for a remote 115 // object with object path |object_path|. If an object proxy was already 116 // created, this operation returns false; returns true otherwise. 117 bool AddObject(const dbus::ObjectPath& object_path); 118 119 // Removes the D-Bus object proxy and the properties structure for the 120 // remote object with object path |object_path|. If no known proxy for 121 // |object_path| exists, then this operation is a no-op. 122 void RemoveObject(const dbus::ObjectPath& object_path); 123 124 // Invokes GetAll on the property structure belonging to object path 125 // |object_path|. If |object_path| is unknown, this method is a no-op. 126 void RefreshProperties(const dbus::ObjectPath& object_path); 127 128 // Invokes GetAll on the property structures belonging to all object paths 129 // that are managed by this instance. 130 void RefreshAllProperties(); 131 132 // Returns a list containing the object paths of all remote objects that are 133 // managed by this instance. 134 ObjectPathVector GetObjectPaths(); 135 136 private: 137 typedef std::pair<dbus::ObjectProxy*, NfcPropertySet*> ObjectPropertyPair; 138 typedef std::map<dbus::ObjectPath, ObjectPropertyPair> ObjectMap; 139 140 // Returns an instance of ObjectPropertyPair by looking up |object_path| in 141 // |object_map_|. If no entry is found, returns an instance that contains 142 // NULL pointers. 143 ObjectPropertyPair GetObjectPropertyPair(const dbus::ObjectPath& object_path); 144 145 // Cleans up the object proxy and properties structure in |pair|. This method 146 // will remove the object proxy by calling |dbus::Bus::RemoveObjectProxy| and 147 // explicitly deallocate the properties structure. Once this method exits, 148 // both pointers stored by |pair| will become invalid and should not be used. 149 // If |pair| contains invalid pointers at the time when this method is called 150 // memory errors are likely to happen, so only valid pointers should be 151 // passed. 152 void CleanUpObjectPropertyPair(const ObjectPropertyPair& pair); 153 154 dbus::Bus* bus_; 155 ObjectMap object_map_; 156 std::string service_name_; 157 Delegate* delegate_; 158 159 DISALLOW_COPY_AND_ASSIGN(DBusObjectMap); 160 }; 161 162 // Most NFC D-Bus client classes need to be able to look up object proxies by 163 // the path of the object that owns them. For example, NfcTagClient updates tag 164 // proxies based on the adapter that owns them. ObjectProxyTree is a two-level 165 // mapping that makes this management easy. 166 class ObjectProxyTree { 167 public: 168 ObjectProxyTree(); 169 170 // The destructor destroys all contained DBusObjectMap instances. This will 171 // cause the delegate to get notified for each removed object proxy according 172 // to the DBusObjectMap destructor. 173 virtual ~ObjectProxyTree(); 174 175 // Creates a DBusObjectMap instance at object path |object_path|. 176 // |service_name|, |delegate|, and |bus| are passed to the constructor of the 177 // DBusObjectMap that is created. If a DBusObjectMap for |object_path| was 178 // already assigned, returns false and does nothing. Otherwise, if a new 179 // DBusObjectMap was created, returns true. 180 bool CreateObjectMap(const dbus::ObjectPath& object_path, 181 const std::string& service_name, 182 DBusObjectMap::Delegate* delegate, 183 dbus::Bus* bus); 184 185 // Destroys the DBusObjectMap instance at object path |object_path|. 186 void RemoveObjectMap(const dbus::ObjectPath& object_path); 187 188 // Returns the DBusObjectMap instance at object path |object_path|, or NULL 189 // if no such instance exists. 190 DBusObjectMap* GetObjectMap(const dbus::ObjectPath& object_path); 191 192 // Returns the object proxy by searching all stored DBusObjectMap instances 193 // for |object_proxy_path|. Returns NULL, if nothing is found. 194 dbus::ObjectProxy* FindObjectProxy( 195 const dbus::ObjectPath& object_proxy_path); 196 197 // Returns the object property structure by searching all stored DBusObjectMap 198 // instances for |object_proxy_path|. Returns NULL, if nothing is found. 199 NfcPropertySet* FindObjectProperties( 200 const dbus::ObjectPath& object_proxy_path); 201 202 private: 203 typedef std::map<dbus::ObjectPath, DBusObjectMap*> PathsToObjectMapsType; 204 PathsToObjectMapsType paths_to_object_maps_; 205 206 DISALLOW_COPY_AND_ASSIGN(ObjectProxyTree); 207 }; 208 209 } // namespace nfc_client_helpers 210 } // namespace chromeos 211 212 #endif // CHROMEOS_DBUS_NFC_CLIENT_HELPERS_H_ 213