Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011 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 DBUS_MESSAGE_H_ | |
| 6 #define DBUS_MESSAGE_H_ | |
| 7 #pragma once | |
| 8 | |
| 9 #include <string> | |
| 10 #include <vector> | |
| 11 #include <dbus/dbus.h> | |
| 12 | |
| 13 #include "base/basictypes.h" | |
| 14 | |
| 15 namespace dbus { | |
| 16 | |
| 17 class MessageWriter; | |
| 18 class MessageReader; | |
| 19 | |
| 20 // Message is the base class of D-Bus message types. Client code should | |
| 21 // usually use sub classes such as MethodCall and Response instead. | |
| 22 // | |
| 23 // The class name Message is very generic, but there should be no problem | |
| 24 // as the class is inside 'dbus' namespace. We chose to name this way, as | |
| 25 // libdbus defines lots of types starting with DBus, such as | |
| 26 // DBusMessage. We should avoid confusion and conflict with these types. | |
| 27 class Message { | |
| 28 public: | |
| 29 // The message type used in D-Bus. | |
| 30 // Redefined here so client code doesn't need to use raw D-Bus macros. | |
| 31 enum MessageType { | |
| 32 MESSAGE_INVALID = DBUS_MESSAGE_TYPE_INVALID, | |
| 33 MESSAGE_METHOD_CALL = DBUS_MESSAGE_TYPE_METHOD_CALL, | |
| 34 MESSAGE_METHOD_RETURN = DBUS_MESSAGE_TYPE_METHOD_RETURN, | |
| 35 MESSAGE_SIGNAL = DBUS_MESSAGE_TYPE_SIGNAL, | |
| 36 MESSAGE_ERROR = DBUS_MESSAGE_TYPE_ERROR, | |
| 37 }; | |
|
stevenjb
2011/07/27 17:56:26
I'm not sure that there is anything gained by mapp
satorux1
2011/07/27 21:20:35
DBUS_MESSAGE_TYPE_INVALID etc. are #define macros.
stevenjb
2011/07/27 21:44:13
Ah, if these are #defines that makes sense then. F
| |
| 38 | |
| 39 // The data type used in the D-Bus type system. | |
| 40 // Redefined here so client code doesn't need to use raw D-Bus macros. | |
| 41 enum DataType { | |
| 42 INVALID_DATA = DBUS_TYPE_INVALID, | |
| 43 BYTE = DBUS_TYPE_BYTE, | |
| 44 BOOL = DBUS_TYPE_BOOLEAN, | |
| 45 INT16 = DBUS_TYPE_INT16, | |
| 46 UINT16 = DBUS_TYPE_UINT16, | |
| 47 INT32 = DBUS_TYPE_INT32, | |
| 48 UINT32 = DBUS_TYPE_UINT32, | |
| 49 INT64 = DBUS_TYPE_INT64, | |
| 50 UINT64 = DBUS_TYPE_UINT64, | |
| 51 DOUBLE = DBUS_TYPE_DOUBLE, | |
| 52 STRING = DBUS_TYPE_STRING, | |
| 53 OBJECT_PATH = DBUS_TYPE_OBJECT_PATH, | |
| 54 ARRAY = DBUS_TYPE_ARRAY, | |
| 55 STRUCT = DBUS_TYPE_STRUCT, | |
| 56 DICT_ENTRY = DBUS_TYPE_DICT_ENTRY, | |
| 57 VARIANT = DBUS_TYPE_VARIANT, | |
| 58 }; | |
|
stevenjb
2011/07/27 17:56:26
Same comment as above.
satorux1
2011/07/27 21:20:35
Ditto.
| |
| 59 | |
| 60 // Creates a Message. The internal raw message is NULL until it's set | |
| 61 // from outside by reset_raw_message(). | |
| 62 Message(); | |
| 63 virtual ~Message(); | |
| 64 | |
| 65 // Returns the type of the message. Returns MESSAGE_INVALID if | |
| 66 // raw_message_ is NULL. | |
| 67 MessageType GetMessageType(); | |
| 68 | |
| 69 DBusMessage* raw_message() { return raw_message_; } | |
| 70 | |
| 71 // Resets raw_message_ with the given raw message. Takes the ownership | |
| 72 // of raw_message. raw_message_ will be unref'ed in the destructor. | |
| 73 void reset_raw_message(DBusMessage* raw_message); | |
|
stevenjb
2011/07/27 17:56:26
Do we need to expose this publicly, or could we ma
satorux1
2011/07/27 21:20:35
Good point. This is exposed for unit tests and Obj
stevenjb
2011/07/27 21:44:13
I'll have to look at ObjectProxy. Making a test cl
| |
| 74 | |
| 75 // Returns the string representation of this message. Useful for | |
| 76 // debugging. The returned string is similar to dbus-send's output. | |
| 77 std::string ToString(); | |
| 78 | |
| 79 private: | |
| 80 // Helper function used in ToString(). | |
| 81 std::string ToStringInternal(const std::string& indent, | |
| 82 MessageReader* reader); | |
| 83 | |
| 84 DBusMessage* raw_message_; | |
| 85 DISALLOW_COPY_AND_ASSIGN(Message); | |
| 86 }; | |
| 87 | |
| 88 // MessageCall is a type of message used for calling a method via D-Bus. | |
| 89 class MethodCall : public Message { | |
| 90 public: | |
| 91 // Creates a method call message for the specified interface name and | |
| 92 // the method name. | |
| 93 // | |
| 94 // For instance, to call "Get" method of DBUS_INTERFACE_INTROSPECTABLE | |
| 95 // interface ("org.freedesktop.DBus.Introspectable"), create a method | |
| 96 // call like this: | |
| 97 // | |
| 98 // MethodCall method_call(DBUS_INTERFACE_INTROSPECTABLE, "Get"); | |
| 99 // | |
| 100 // The constructor creates the internal raw_message_, so the client | |
| 101 // doesn't need to set this by reset_raw_message(). | |
| 102 MethodCall(const std::string& interface_name, | |
| 103 const std::string& method_name); | |
| 104 | |
| 105 const std::string& interface_name() { return interface_name_; } | |
| 106 const std::string& method_name() { return method_name_; } | |
| 107 | |
| 108 private: | |
| 109 friend class ObjectProxy; | |
| 110 | |
| 111 // Sets the service name. This will be handled by the object proxy. | |
| 112 void SetServiceName(const std::string& service_name); | |
| 113 // Sets the object path. This will be handled by the object proxy. | |
| 114 void SetObjectPath(const std::string& object_path); | |
| 115 | |
| 116 std::string interface_name_; | |
| 117 std::string method_name_; | |
| 118 | |
| 119 DISALLOW_COPY_AND_ASSIGN(MethodCall); | |
| 120 }; | |
| 121 | |
| 122 // Response is a type of message used for receiving a response from a | |
| 123 // method via D-Bus. | |
| 124 class Response : public Message { | |
| 125 public: | |
| 126 // Creates a Response message. The internal raw message is | |
| 127 // NULL. ObjectProxy will set it properly once it gets a response from | |
| 128 // the server. | |
| 129 Response(); | |
| 130 | |
| 131 private: | |
| 132 DISALLOW_COPY_AND_ASSIGN(Response); | |
| 133 }; | |
| 134 | |
| 135 // MessageWriter is used to write outgoing messages for calling methods | |
| 136 // and sending signals. | |
| 137 class MessageWriter { | |
| 138 public: | |
| 139 // The data will be written into the given message. | |
| 140 MessageWriter(Message* message); | |
| 141 ~MessageWriter(); | |
| 142 | |
| 143 // Appends a byte to the message. | |
| 144 void AppendByte(uint8 value); | |
| 145 // The following functions do the same for other basic types. | |
|
stevenjb
2011/07/27 17:56:26
This comment is probably not necessary and made me
satorux1
2011/07/27 21:20:35
Done.
| |
| 146 void AppendBool(bool value); | |
| 147 void AppendInt16(int16 value); | |
| 148 void AppendUint16(uint16 value); | |
| 149 void AppendInt32(int32 value); | |
| 150 void AppendUint32(uint32 value); | |
| 151 void AppendInt64(int64 value); | |
| 152 void AppendUint64(uint64 value); | |
| 153 void AppendDouble(double value); | |
| 154 void AppendString(const std::string& value); | |
| 155 void AppendObjectPath(const std::string& value); | |
| 156 | |
| 157 // Opens an array. The array contents can be added to the array with | |
| 158 // sub_writer. The client code should close the array by CloseContainer(), | |
|
stevenjb
2011/07/27 17:56:26
|sub_writer|
s/by/with/
| |
| 159 // once all contents are added. | |
|
stevenjb
2011/07/27 17:56:26
Can multiple arrays use the same sub_writer? If so
satorux1
2011/07/27 21:20:35
I think we can do it, but this style is consistent
| |
| 160 // | |
| 161 // |signature| parameter is used to supply the D-Bus type signature of | |
| 162 // the array contents. For instance, if you want an array of strings, | |
| 163 // then you pass "s" as the signature. need to take | |
|
stevenjb
2011/07/27 17:56:26
"need to take"?
satorux1
2011/07/27 21:20:35
Done.
| |
| 164 // | |
| 165 // See the spec for details about the type signatures. | |
| 166 // http://dbus.freedesktop.org/doc/dbus-specification.html | |
| 167 // #message-protocol-signatures | |
| 168 // | |
| 169 // Ideally, client shouldn't need to supply the signature string, but | |
| 170 // the underlying D-Bus library requires us to supply this before | |
| 171 // appending contents to array and variant. It's technically possible | |
| 172 // for us to design API that doesn't require the signature but it'll | |
|
stevenjb
2011/07/27 17:56:26
s/it'll/it will/ (it'll is rarely written as a con
satorux1
2011/07/27 21:20:35
Done.
| |
| 173 // complicate the implementation so we decided to have the signature | |
| 174 // parameter. Hopefully, variants are less used in request messages from | |
| 175 // client side than response message from server side, so this should | |
| 176 // not be a big issue. | |
| 177 // | |
| 178 void OpenArray(const std::string& signature, MessageWriter* sub_writer); | |
| 179 // Do the same for a variant. | |
| 180 void OpenVariant(const std::string& signature, MessageWriter* sub_writer); | |
| 181 // Do the same for Struct and dict entry. They don't need the signature. | |
| 182 void OpenStruct(MessageWriter* sub_writer); | |
| 183 void OpenDictEntry(MessageWriter* sub_writer); | |
| 184 | |
| 185 // Close the container for a array/variant/struct/dict entry. | |
| 186 void CloseContainer(MessageWriter* sub_writer); | |
| 187 | |
| 188 // Appends the array of bytes. Arrays of bytes are often used for | |
| 189 // exchanging binary blobs hence it's worth having a specialized | |
| 190 // function. | |
| 191 void AppendArrayOfBytes(const std::vector<uint8>& bytes); | |
|
stevenjb
2011/07/27 17:56:26
This might be more flexible if it takes a const ui
satorux1
2011/07/27 21:20:35
Good idea. Done.
| |
| 192 | |
| 193 // Appends the byte wrapped in a variant data container. Variants are | |
| 194 // widely used in D-Bus services so it's worth having a specialized | |
| 195 // function. For instance, The third parameter of | |
| 196 // "org.freedesktop.DBus.Properties.Set" is a variant. | |
| 197 void AppendVariantOfByte(uint8 value); | |
| 198 // The following functions do the same for other basic types. | |
|
stevenjb
2011/07/27 17:56:26
This comment is probably not necessary and made me
satorux1
2011/07/27 21:20:35
Done.
| |
| 199 void AppendVariantOfBool(bool value); | |
| 200 void AppendVariantOfInt16(int16 value); | |
| 201 void AppendVariantOfUint16(uint16 value); | |
| 202 void AppendVariantOfInt32(int32 value); | |
| 203 void AppendVariantOfUint32(uint32 value); | |
| 204 void AppendVariantOfInt64(int64 value); | |
| 205 void AppendVariantOfUint64(uint64 value); | |
| 206 void AppendVariantOfDouble(double value); | |
| 207 void AppendVariantOfString(const std::string& value); | |
| 208 void AppendVariantOfObjectPath(const std::string& value); | |
| 209 | |
| 210 private: | |
| 211 // Helper function used to implement AppendByte etc. | |
| 212 void AppendBasic(int dbus_type, const void* value); | |
| 213 | |
| 214 // Helper function used to implement AppendVariantOfByte() etc. | |
| 215 void AppendVariantOfBasic(int dbus_type, const void* value); | |
| 216 | |
| 217 Message* message_; | |
| 218 DBusMessageIter raw_message_iter_; | |
| 219 bool container_is_open_; | |
| 220 | |
| 221 DISALLOW_COPY_AND_ASSIGN(MessageWriter); | |
| 222 }; | |
| 223 | |
| 224 // MessageReader is used to read incoming messages such as responses for | |
| 225 // method calls. | |
| 226 // | |
| 227 // MessageReader manages an internal iterator to read data. All functions | |
| 228 // starting with Pop advance the iterator on success. | |
| 229 // | |
| 230 // The main design goal of MessageReader and MessageWriter classes is to | |
| 231 // provide type safe API. In the past, there was a Chrome OS blocker bug, | |
|
stevenjb
2011/07/27 17:56:26
s/type safe API/a type safe API
satorux1
2011/07/27 21:20:35
Done.
| |
| 232 // that took days to fix, that would have been prevented if the API was | |
| 233 // type-safe. | |
| 234 // | |
| 235 // For instance, instead of doing something like: | |
| 236 // | |
| 237 // // We shouldn't add '&' to str here, but it compiles with '&' added. | |
| 238 // dbus_g_proxy_call(..., G_TYPE_STRING, str, G_TYPE_INVALID, ...) | |
| 239 // | |
| 240 // We want to do something like: | |
| 241 // | |
| 242 // writer.AppendString(str); | |
| 243 // | |
| 244 // See crosbug.com/7619 for details about the bug in question. | |
|
stevenjb
2011/07/27 17:56:26
Comment about blocker bug is probably not necessar
satorux1
2011/07/27 21:20:35
Done.
| |
| 245 class MessageReader { | |
| 246 public: | |
| 247 // The data will be read from the given message. | |
| 248 MessageReader(Message* message); | |
| 249 ~MessageReader(); | |
| 250 | |
| 251 // Returns true if the reader has more data to read. The function is | |
| 252 // used to iterate contents in a container like: | |
| 253 // | |
| 254 // while (reader.HasMore()) | |
| 255 // reader.PopString(&value); | |
| 256 bool HasMore(); | |
|
stevenjb
2011/07/27 17:56:26
nit: HasMoreData()
satorux1
2011/07/27 21:20:35
Done.
| |
| 257 | |
| 258 // Gets the byte at the current iterator position. On success, advances | |
| 259 // the iterator and returns true. It's an error if the actual data type | |
| 260 // is not a byte, so false will be returned in this case. | |
| 261 bool PopByte(uint8* value); | |
| 262 // The following functions do the same for other basic types. | |
|
stevenjb
2011/07/27 17:56:26
nit: Don't separate PopBool,etc from PopByte with
satorux1
2011/07/27 21:20:35
Done.
| |
| 263 bool PopBool(bool* value); | |
| 264 bool PopInt16(int16* value); | |
| 265 bool PopUint16(uint16* value); | |
| 266 bool PopInt32(int32* value); | |
| 267 bool PopUint32(uint32* value); | |
| 268 bool PopInt64(int64* value); | |
| 269 bool PopUint64(uint64* value); | |
| 270 bool PopDouble(double* value); | |
| 271 bool PopString(std::string* value); | |
| 272 bool PopObjectPath(std::string* value); | |
| 273 | |
| 274 // Sets up the given message reader to read an array at the current | |
| 275 // iterator position. On success, advances the iterator and returns | |
| 276 // true. It's an error if the actual data type is not an array, so false | |
| 277 // will be returned in this case. | |
| 278 bool PopArray(MessageReader* sub_reader); | |
| 279 // The following functions do the same for other container types. | |
|
stevenjb
2011/07/27 17:56:26
nit: Don't separate with a comment.
satorux1
2011/07/27 21:20:35
Done.
| |
| 280 bool PopStruct(MessageReader* sub_reader); | |
| 281 bool PopDictEntry(MessageReader* sub_reader); | |
| 282 bool PopVariant(MessageReader* sub_reader); | |
| 283 | |
| 284 // Gets the array of bytes at the current iterator position. On success, | |
| 285 // advances the iterator and returns true. Arrays of bytes are often | |
| 286 // used for exchanging binary blobs hence it's worth having a | |
| 287 // specialized function. | |
|
stevenjb
2011/07/27 17:56:26
I think there should be a version of this that tak
satorux1
2011/07/27 21:20:35
Good point. What about adding such a version when
stevenjb
2011/07/27 21:44:13
It's not a question of whether or not vector<> can
satorux1
2011/07/27 22:12:14
I'm convinced. Changed it to uint8* + size_t, to m
| |
| 288 bool PopArrayOfBytes(std::vector<uint8>* bytes); | |
| 289 | |
| 290 // Gets the array of object paths at the current iterator position. On | |
| 291 // success, advances the iterator and returns true. Arrays of object | |
| 292 // paths are often used to communicate with D-Bus services like | |
| 293 // NetworkManager, hence it's worth having a specialized function. | |
| 294 bool PopArrayOfObjectPaths(std::vector<std::string>* object_paths); | |
| 295 | |
| 296 // Gets the byte from the variant data container at the current iterator | |
| 297 // position. On success, returns true and advances the | |
| 298 // iterator. Variants are widely used in D-Bus services so it's worth | |
| 299 // having a specialized function. For instance, The return value type of | |
| 300 // "org.freedesktop.DBus.Properties.Get" is a variant. | |
| 301 bool PopVariantOfByte(uint8* value); | |
| 302 // The following functions do the same for other basic types. | |
|
stevenjb
2011/07/27 17:56:26
nit: Don't separate with a comment.
satorux1
2011/07/27 21:20:35
Done.
| |
| 303 bool PopVariantOfBool(bool* value); | |
| 304 bool PopVariantOfInt16(int16* value); | |
| 305 bool PopVariantOfUint16(uint16* value); | |
| 306 bool PopVariantOfInt32(int32* value); | |
| 307 bool PopVariantOfUint32(uint32* value); | |
| 308 bool PopVariantOfInt64(int64* value); | |
| 309 bool PopVariantOfUint64(uint64* value); | |
| 310 bool PopVariantOfDouble(double* value); | |
| 311 bool PopVariantOfString(std::string* value); | |
| 312 bool PopVariantOfObjectPath(std::string* value); | |
| 313 | |
| 314 // Get the data type of the value at the current iterator | |
| 315 // position. INVALID_DATA will be returned if the iterator points to the | |
| 316 // end of the message. | |
| 317 Message::DataType GetDataType(); | |
| 318 | |
| 319 private: | |
| 320 // Returns true if the data type at the current iterator position | |
| 321 // matches the given D-Bus type, such as DBUS_TYPE_BYTE. | |
| 322 bool CheckDataType(int dbus_type); | |
| 323 | |
| 324 // Helper function used to implement PopByte() etc. | |
| 325 bool PopBasic(int dbus_type, void *value); | |
| 326 | |
| 327 // Helper function used to implement PopArray() etc. | |
| 328 bool PopContainer(int dbus_type, MessageReader* sub_reader); | |
| 329 | |
| 330 // Helper function used to implement PopVariantOfByte() etc. | |
| 331 bool PopVariantOfBasic(int dbus_type, void* value); | |
| 332 | |
| 333 Message* message_; | |
| 334 DBusMessageIter raw_message_iter_; | |
| 335 | |
| 336 DISALLOW_COPY_AND_ASSIGN(MessageReader); | |
| 337 }; | |
| 338 | |
| 339 } // namespace dbus | |
| 340 | |
| 341 #endif // DBUS_MESSAGE_H_ | |
| OLD | NEW |