dbus-c++: report DBUS_ERROR_OBJECT_PATH_IN_USE error

This CL modifies ObjectAdaptor::register_obj() to throw an
ErrorObjectPathInUse exception if it fails to register a handler for a
given path in the DBus object hierarchy (i.e. upon a
DBUS_ERROR_OBJECT_PATH_IN_USE error).

BUG=chromium:392903
TEST=Tested the following:
1. `emerge-$BOARD dbus-c++`
2. Manually modify shill to register a DBus adaptor with the same
   object path twice, and verify that an ErrorObjectPathInUse exception
   is raised.

Change-Id: Ied787112ecd04aae67c6b78060d8cedb03eeda73
Reviewed-on: https://chromium-review.googlesource.com/207344
Reviewed-by: mukesh agrawal <[email protected]>
Commit-Queue: Ben Chan <[email protected]>
Tested-by: Ben Chan <[email protected]>
diff --git a/include/dbus-c++/error.h b/include/dbus-c++/error.h
index c1d2151..011a50f 100644
--- a/include/dbus-c++/error.h
+++ b/include/dbus-c++/error.h
@@ -279,6 +279,13 @@
 	{}
 };
 
+struct DXXAPI ErrorObjectPathInUse : public Error
+{
+	ErrorObjectPathInUse(const char *message)
+	: Error("org.freedesktop.DBus.Error.ObjectPathInUse", message)
+	{}
+};
+
 } /* namespace DBus */
 
 #endif//__DBUSXX_ERROR_H
diff --git a/src/object.cpp b/src/object.cpp
index e1e40aa..c9bf02d 100644
--- a/src/object.cpp
+++ b/src/object.cpp
@@ -192,9 +192,19 @@
                 throw ErrorInvalidArgs(message.c_str());
         }
 
-	if (!dbus_connection_register_object_path(conn()._pvt->conn, path().c_str(), &_vtable, this))
+	DBusError error = DBUS_ERROR_INIT;
+	if (!dbus_connection_try_register_object_path(conn()._pvt->conn, path().c_str(), &_vtable, this, &error))
 	{
- 		throw ErrorNoMemory("unable to register object path");
+		if (dbus_error_has_name(&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
+		{
+			dbus_error_free(&error);
+			throw ErrorObjectPathInUse("unable to register object path");
+		}
+		else
+		{
+			dbus_error_free(&error);
+			throw ErrorNoMemory("unable to register object path");
+		}
 	}
 
 	_adaptor_table[path()] = this;