hs-proxy: Keep track of clientCtx and client when starting application
[apps/agl-service-homescreen.git] / src / hs-proxy.cpp
index a7236b4..33e5d53 100644 (file)
 #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);
 }