[Bug/Feature] Enable deferred set of result in dbus method handler.
[Cause] N/A
[Solution] N/A
[Verification] Build, install, run tests
Change-Id: I11b3abe0886bc560f8b63f6206c64695f2f7eb1a
public:
MethodResultBuilderImpl(GDBusMethodInvocation* invocation)
: mInvocation(invocation), mResultSet(false) {}
+ ~MethodResultBuilderImpl()
+ {
+ if (!mResultSet) {
+ setError("org.freedesktop.DBus.Error.UnknownMethod", "Not implemented");
+ }
+ }
void set(GVariant* parameters)
{
g_dbus_method_invocation_return_value(mInvocation, parameters);
g_dbus_method_invocation_return_dbus_error(mInvocation, name.c_str(), message.c_str());
mResultSet = true;
}
- bool isUndefined() const
- {
- return !mResultSet;
- }
private:
GDBusMethodInvocation* mInvocation;
bool mResultSet;
LOGD("MethodCall: " << objectPath << "; " << interface << "; " << method);
- MethodResultBuilderImpl resultBuilder(invocation);
+ MethodResultBuilder::Pointer resultBuilder(new MethodResultBuilderImpl(invocation));
if (callback) {
callback(objectPath, interface, method, parameters, resultBuilder);
}
-
- if (resultBuilder.isUndefined()) {
- LOGW("Unimplemented method: " << objectPath << "; " << interface << "; " << method);
- resultBuilder.setError("org.freedesktop.DBus.Error.UnknownMethod", "Not implemented");
- }
}
GVariantPtr DbusConnection::callMethod(const std::string& busName,
*/
class MethodResultBuilder {
public:
+ typedef std::shared_ptr<MethodResultBuilder> Pointer;
+
virtual ~MethodResultBuilder() {}
virtual void set(GVariant* parameters) = 0;
virtual void setVoid() = 0;
const std::string& interface,
const std::string& methodName,
GVariant* parameters,
- MethodResultBuilder& result
+ MethodResultBuilder::Pointer result
)> MethodCallCallback;
typedef std::function<void(const std::string& senderBusName,
const std::string& interface,
const std::string& methodName,
GVariant* /*parameters*/,
- dbus::MethodResultBuilder& result)
+ dbus::MethodResultBuilder::Pointer result)
{
if (objectPath != api::OBJECT_PATH || interface != api::INTERFACE) {
return;
if (methodName == api::METHOD_GAIN_FOCUS) {
if (mGainFocusCallback) {
mGainFocusCallback();
- result.setVoid();
+ result->setVoid();
}
} else if (methodName == api::METHOD_LOSE_FOCUS) {
if (mLoseFocusCallback) {
mLoseFocusCallback();
- result.setVoid();
+ result->setVoid();
}
}
}
const std::string& interface,
const std::string& methodName,
GVariant* parameters,
- dbus::MethodResultBuilder& result);
+ dbus::MethodResultBuilder::Pointer result);
};
const std::string& interface,
const std::string& methodName,
GVariant* parameters,
- dbus::MethodResultBuilder& result)
+ dbus::MethodResultBuilder::Pointer result)
{
if (objectPath != api::OBJECT_PATH || interface != api::INTERFACE) {
return;
g_variant_get(parameters, "(&s&s)", &application, &message);
if (mNotifyActiveContainerCallback) {
mNotifyActiveContainerCallback(application, message);
- result.setVoid();
+ result->setVoid();
}
}
typedef std::function<void(const std::string& destination,
const std::string& path,
- dbus::MethodResultBuilder& result
+ dbus::MethodResultBuilder::Pointer result
)> FileMoveRequestCallback;
/**
const std::string& interface,
const std::string& methodName,
GVariant* parameters,
- dbus::MethodResultBuilder& result);
+ dbus::MethodResultBuilder::Pointer result);
void onSignalReceived(const std::string& senderBusName,
const std::string& objectPath,
const std::string& interface,
void ContainersManager::handleContainerMoveFileRequest(const std::string& srcContainerId,
const std::string& dstContainerId,
const std::string& path,
- dbus::MethodResultBuilder& result)
+ dbus::MethodResultBuilder::Pointer result)
{
// TODO: this implementation is only a placeholder.
// There are too many unanswered questions and security concerns:
ContainerMap::const_iterator dstIter = mContainers.find(dstContainerId);
if (dstIter == mContainers.end()) {
LOGE("Destination container '" << dstContainerId << "' not found");
- result.set(g_variant_new("(s)", api::FILE_MOVE_DESTINATION_NOT_FOUND.c_str()));
+ result->set(g_variant_new("(s)", api::FILE_MOVE_DESTINATION_NOT_FOUND.c_str()));
return;
}
Container& dstContanier = *dstIter->second;
if (srcContainerId == dstContainerId) {
LOGE("Cannot send a file to yourself");
- result.set(g_variant_new("(s)", api::FILE_MOVE_WRONG_DESTINATION.c_str()));
+ result->set(g_variant_new("(s)", api::FILE_MOVE_WRONG_DESTINATION.c_str()));
return;
}
if (!regexMatchVector(path, srcContainer.getPermittedToSend())) {
LOGE("Source container has no permissions to send the file: " << path);
- result.set(g_variant_new("(s)", api::FILE_MOVE_NO_PERMISSIONS_SEND.c_str()));
+ result->set(g_variant_new("(s)", api::FILE_MOVE_NO_PERMISSIONS_SEND.c_str()));
return;
}
if (!regexMatchVector(path, dstContanier.getPermittedToRecv())) {
LOGE("Destination container has no permissions to receive the file: " << path);
- result.set(g_variant_new("(s)", api::FILE_MOVE_NO_PERMISSIONS_RECEIVE.c_str()));
+ result->set(g_variant_new("(s)", api::FILE_MOVE_NO_PERMISSIONS_RECEIVE.c_str()));
return;
}
if (!utils::moveFile(srcPath, dstPath)) {
LOGE("Failed to move the file: " << path);
- result.set(g_variant_new("(s)", api::FILE_MOVE_FAILED.c_str()));
+ result->set(g_variant_new("(s)", api::FILE_MOVE_FAILED.c_str()));
} else {
- result.set(g_variant_new("(s)", api::FILE_MOVE_SUCCEEDED.c_str()));
+ result->set(g_variant_new("(s)", api::FILE_MOVE_SUCCEEDED.c_str()));
try {
dstContanier.sendNotification(srcContainerId, path, api::FILE_MOVE_SUCCEEDED);
} catch (ServerException&) {
void handleContainerMoveFileRequest(const std::string& srcContainerId,
const std::string& dstContainerId,
const std::string& path,
- dbus::MethodResultBuilder& result);
+ dbus::MethodResultBuilder::Pointer result);
};
const std::string& interface,
const std::string& methodName,
GVariant* /*parameters*/,
- dbus::MethodResultBuilder& result)
+ dbus::MethodResultBuilder::Pointer result)
{
if (objectPath != hostapi::OBJECT_PATH || interface != hostapi::INTERFACE) {
return;
if (methodName == hostapi::METHOD_TEST) {
if (mTestCallback) {
mTestCallback();
- result.setVoid();
+ result->setVoid();
}
}
}
const std::string& interface,
const std::string& methodName,
GVariant* parameters,
- dbus::MethodResultBuilder& result);
+ dbus::MethodResultBuilder::Pointer result);
};
const std::string& interface,
const std::string& methodName,
GVariant* parameters,
- dbus::MethodResultBuilder& result)
+ dbus::MethodResultBuilder::Pointer result)
{
try {
if (objectPath != TESTAPI_OBJECT_PATH || interface != TESTAPI_INTERFACE) {
if (methodName == TESTAPI_METHOD_NOOP) {
noop();
- result.setVoid();
+ result->setVoid();
} else if (methodName == TESTAPI_METHOD_PROCESS) {
const gchar* arg;
g_variant_get(parameters, "(&s)", &arg);
std::string ret = process(arg);
GVariant* variant = g_variant_new("(s)", ret.c_str());
- result.set(variant);
+ result->set(variant);
} else if (methodName == TESTAPI_METHOD_THROW) {
int arg;
g_variant_get(parameters, "(i)", &arg);
throwException(arg);
- result.setVoid();
+ result->setVoid();
} else {
LOGE("unknown method; should never happen");
}
} catch (const std::exception& e) {
- result.setError("org.tizen.containers.Error.Test", e.what());
+ result->setError("org.tizen.containers.Error.Test", e.what());
}
}
const std::string& interface,
const std::string& methodName,
GVariant* parameters,
- dbus::MethodResultBuilder& result);
+ dbus::MethodResultBuilder::Pointer result);
};
const std::string& interface,
const std::string& methodName,
GVariant* parameters,
- MethodResultBuilder& result) {
+ MethodResultBuilder::Pointer result) {
if (objectPath != TESTAPI_OBJECT_PATH || interface != TESTAPI_INTERFACE) {
return;
}
if (methodName == TESTAPI_METHOD_NOOP) {
- result.setVoid();
+ result->setVoid();
} else if (methodName == TESTAPI_METHOD_PROCESS) {
const gchar* arg = NULL;
g_variant_get(parameters, "(&s)", &arg);
std::string str = std::string("resp: ") + arg;
- result.set(g_variant_new("(s)", str.c_str()));
+ result->set(g_variant_new("(s)", str.c_str()));
} else if (methodName == TESTAPI_METHOD_THROW) {
int arg = 0;
g_variant_get(parameters, "(i)", &arg);
- result.setError("org.tizen.containers.Error.Test", "msg: " + std::to_string(arg));
+ result->setError("org.tizen.containers.Error.Test", "msg: " + std::to_string(arg));
}
};
conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler);
const std::string& interface,
const std::string& methodName,
GVariant* parameters,
- MethodResultBuilder& result) {
+ MethodResultBuilder::Pointer result) {
if (objectPath != TESTAPI_OBJECT_PATH || interface != TESTAPI_INTERFACE) {
return;
}
if (methodName == TESTAPI_METHOD_NOOP) {
- result.setVoid();
+ result->setVoid();
} else if (methodName == TESTAPI_METHOD_PROCESS) {
const gchar* arg = NULL;
g_variant_get(parameters, "(&s)", &arg);
std::string str = std::string("resp: ") + arg;
- result.set(g_variant_new("(s)", str.c_str()));
+ result->set(g_variant_new("(s)", str.c_str()));
} else if (methodName == TESTAPI_METHOD_THROW) {
int arg = 0;
g_variant_get(parameters, "(i)", &arg);
- result.setError("org.tizen.containers.Error.Test", "msg: " + std::to_string(arg));
+ result->setError("org.tizen.containers.Error.Test", "msg: " + std::to_string(arg));
}
};
conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler);
BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
}
+BOOST_AUTO_TEST_CASE(MethodAsyncCallAsyncHandlerTest)
+{
+ ScopedDbusDaemon daemon;
+ ScopedGlibLoop loop;
+ Latch nameAcquired;
+
+ DbusConnection::Pointer conn1 = DbusConnection::create(DBUS_ADDRESS);
+ DbusConnection::Pointer conn2 = DbusConnection::create(DBUS_ADDRESS);
+
+ conn1->setName(TESTAPI_BUS_NAME,
+ [&] {nameAcquired.set();},
+ [] {});
+ BOOST_REQUIRE(nameAcquired.wait(EVENT_TIMEOUT));
+
+ Latch handlerDone;
+ std::string strResult;
+ MethodResultBuilder::Pointer deferredResult;
+
+ auto handler = [&](const std::string& objectPath,
+ const std::string& interface,
+ const std::string& methodName,
+ GVariant* parameters,
+ MethodResultBuilder::Pointer result) {
+ if (objectPath != TESTAPI_OBJECT_PATH || interface != TESTAPI_INTERFACE) {
+ return;
+ }
+ if (methodName == TESTAPI_METHOD_PROCESS) {
+ const gchar* arg = NULL;
+ g_variant_get(parameters, "(&s)", &arg);
+ strResult = std::string("resp: ") + arg;
+ deferredResult = result;
+ handlerDone.set();
+ }
+ };
+ conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler);
+
+ Latch callDone;
+
+ auto asyncResult = [&](dbus::AsyncMethodCallResult& asyncMethodCallResult) {
+ const gchar* ret = NULL;
+ g_variant_get(asyncMethodCallResult.get(), "(&s)", &ret);
+ BOOST_CHECK_EQUAL("resp: arg", ret);
+ callDone.set();
+ };
+ conn2->callMethodAsync(TESTAPI_BUS_NAME,
+ TESTAPI_OBJECT_PATH,
+ TESTAPI_INTERFACE,
+ TESTAPI_METHOD_PROCESS,
+ g_variant_new("(s)", "arg"),
+ "(s)",
+ asyncResult);
+ BOOST_REQUIRE(handlerDone.wait(EVENT_TIMEOUT));
+ BOOST_REQUIRE(callDone.empty());
+ deferredResult->set(g_variant_new("(s)", strResult.c_str()));
+ BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+}
+
BOOST_AUTO_TEST_CASE(MethodCallExceptionTest)
{
ScopedDbusDaemon daemon;