aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarius Vlad <marius.vlad@collabora.com>2020-08-19 13:11:19 +0300
committerMarius Vlad <marius.vlad@collabora.com>2020-08-19 17:00:07 +0300
commite5c9cb71a537b92096f2f05058522b811f735838 (patch)
treef16b8c0fe4c9b77ef9dc0b2880c3849571ed3131
parentf6c6f42502ba2919f23f553239dd8b117440b365 (diff)
hs-proxy: Keep track of clientCtx and client when starting applicationjellyfish_9.99.4jellyfish/9.99.49.99.4
The subscribe verb was used in the past to keep track of applications, which was done in background with the help of event handlers. As that no longer happens we keep track of the client and its clientCtx when starting directly from the homescreen binding, faking the subscribe logic. As the afb_req_t object is no longer in scope when the async callback handler returns, we do it before doing the call to af-main, and assume that we'll succeed. We use the async callback handler to verify if the application was indeed started but any application crashing afterwards will require an additional check performed, as it will found in the hash table of clients. Bug-AGL: SPEC-3524 Signed-off-by: Marius Vlad <marius.vlad@collabora.com> Change-Id: I0e417dc5f2953947cd27ca551c0d2a2af5c57e6d
-rw-r--r--src/hs-clientmanager.cpp1
-rw-r--r--src/hs-proxy.cpp62
2 files changed, 60 insertions, 3 deletions
diff --git a/src/hs-clientmanager.cpp b/src/hs-clientmanager.cpp
index 7c2adc5..beac816 100644
--- a/src/hs-clientmanager.cpp
+++ b/src/hs-clientmanager.cpp
@@ -184,6 +184,7 @@ int HS_ClientManager::handleRequest(afb_req_t request, const char *verb, const c
std::string id(appid);
auto ip = client_list.find(id);
if(ip != client_list.end()) {
+ // FIXME: do another verification here in case the application died
ret = ip->second->handleRequest(request, verb);
}
else {
diff --git a/src/hs-proxy.cpp b/src/hs-proxy.cpp
index a7236b4..33e5d53 100644
--- a/src/hs-proxy.cpp
+++ b/src/hs-proxy.cpp
@@ -17,6 +17,12 @@
#include "homescreen.h"
#include "hs-proxy.h"
+struct closure_data {
+ std::string appid;
+ HS_ClientCtxt *clientCtx;
+ struct hs_instance *hs_instance;
+};
+
const char _afm_main[] = "afm-main";
@@ -37,6 +43,24 @@ const char _afm_main[] = "afm-main";
static void api_callback(void *closure, struct json_object *object, const char *error, const char *info, afb_api_t api)
{
AFB_INFO("asynchronous call, error=%s, info=%s, object=%s.", error, info, json_object_get_string(object));
+ struct closure_data *cdata = static_cast<struct closure_data *>(closure);
+
+ if (!cdata->hs_instance) {
+ return;
+ }
+
+ struct HS_ClientManager *clientManager = cdata->hs_instance->client_manager;
+ if (!clientManager) {
+ return;
+ }
+
+ /* if we have an error then we couldn't start the application so we remove it */
+ if (error) {
+ clientManager->removeClientCtxt(cdata->clientCtx);
+ clientManager->removeClient(cdata->appid);
+ }
+
+ free(cdata);
}
/**
@@ -52,10 +76,10 @@ static void api_callback(void *closure, struct json_object *object, const char *
* None
*
*/
-static void api_call(afb_api_t api, const char *service, const char *verb, struct json_object *args)
+static void api_call(afb_api_t api, const char *service, const char *verb, struct json_object *args, struct closure_data *cdata)
{
AFB_INFO("service=%s verb=%s, args=%s.", service, verb, json_object_get_string(args));
- afb_api_call(api, service, verb, args, api_callback, nullptr);
+ afb_api_call(api, service, verb, args, api_callback, cdata);
}
/**
@@ -131,5 +155,37 @@ int HS_AfmMainProxy::detail(afb_api_t api, const std::string &id, struct json_ob
void HS_AfmMainProxy::start(struct hs_instance *instance, afb_req_t request, const std::string &id)
{
struct json_object *args = json_object_new_string(id.c_str());
- api_call(request->api, _afm_main, __FUNCTION__, args);
+ struct closure_data *cdata;
+
+ /* tentatively store the client and client context, as the afb_req_t
+ * request will no longer be available in the async callback handler. This
+ * is similar to that is done showWindow(), handleRequest() in
+ * homescreen.cpp, but allows to fake the subscription here as well to
+ * avoid clients create/install dummy event handlers as to 'register' (or
+ * to keep track of applications started).
+ *
+ * In case api_callback() does return an error we'll remove then the client
+ * and client context there. We pass the closure_data with the client context
+ * and the application id to remove it.
+ */
+ if (!instance)
+ return;
+
+ cdata = static_cast<struct closure_data *>(calloc(1, sizeof(*cdata)));
+ cdata->hs_instance = instance;
+ cdata->appid = id;
+
+ struct HS_ClientManager *clientManager = instance->client_manager;
+ if (!clientManager) {
+ return;
+ }
+
+ cdata->clientCtx = clientManager->createClientCtxt(request, id);
+ HS_Client *client = clientManager->addClient(request, id);
+ if (client) {
+ if (client->handleRequest(request, "subscribe"))
+ AFB_WARNING("Failed to handle subcribe\n");
+ }
+
+ api_call(request->api, _afm_main, __FUNCTION__, args, cdata);
}