Fix potential memory leak
[apps/agl-service-homescreen.git] / src / hs-client.cpp
1 /*
2  * Copyright (c) 2018 TOYOTA MOTOR CORPORATION
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <cstring>
18 #include "hs-client.h"
19 #include "hs-helper.h"
20
21 static const char _event[] = "event";
22 static const char _type[] = "type";
23 static const char _text[] = "text";
24 static const char _info[] = "info";
25 static const char _icon[] = "icon";
26 static const char _parameter[] = "parameter";
27 static const char _replyto[] = "replyto";
28 static const char _caller[] = "caller";
29
30 // homescreen-service event and event handler function list
31 const std::unordered_map<std::string, HS_Client::func_handler> HS_Client::func_list {
32     {"tap_shortcut",        &HS_Client::tap_shortcut},
33     {"showWindow",          &HS_Client::showWindow},
34     {"hideWindow",          &HS_Client::hideWindow},
35     {"replyShowWindow",     &HS_Client::replyShowWindow},
36     {"on_screen_message",   &HS_Client::on_screen_message},
37     {"on_screen_reply",     &HS_Client::on_screen_reply},
38     {"subscribe",           &HS_Client::subscribe},
39     {"unsubscribe",         &HS_Client::unsubscribe},
40     {"showNotification",    &HS_Client::showNotification},
41     {"showInformation",     &HS_Client::showInformation},
42     {"application-list-changed", nullptr}
43 };
44
45 /**
46  * HS_Client construction function
47  *
48  * #### Parameters
49  *  - id: app's id
50  *
51  * #### Return
52  * None
53  *
54  */
55 HS_Client::HS_Client(afb_req_t request, std::string id) : my_id(id)
56 {
57     my_event = afb_api_make_event(request->api, id.c_str());
58 }
59
60 /**
61  * HS_Client destruction function
62  *
63  * #### Parameters
64  *  - null
65  *
66  * #### Return
67  * None
68  *
69  */
70 HS_Client::~HS_Client()
71 {
72     afb_event_unref(my_event);
73 }
74
75 /**
76  * push tap_shortcut event
77  *
78  * #### Parameters
79  *  - request : the request
80  *
81  * #### Return
82  * 0 : success
83  * others : fail
84  *
85  */
86 int HS_Client::tap_shortcut(afb_req_t request)
87 {
88     AFB_INFO("request appid = %s.", my_id.c_str());
89     struct json_object* push_obj = json_object_new_object();
90     hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(),
91     _type, __FUNCTION__);
92     afb_event_push(my_event, push_obj);
93     return 0;
94 }
95
96 /**
97  * push on_screen_message event
98  *
99  * #### Parameters
100  *  - request : the request
101  *
102  * #### Return
103  * 0 : success
104  * others : fail
105  *
106  */
107 int HS_Client::on_screen_message(afb_req_t request)
108 {
109     int ret = 0;
110     const char* value = afb_req_value(request, _display_message);
111     if (value) {
112         AFB_INFO("push %s event message [%s].", __FUNCTION__, value);
113         struct json_object* push_obj = json_object_new_object();
114         hs_add_object_to_json_object_str( push_obj, 4, _display_message, value,
115         _type, __FUNCTION__);
116         afb_event_push(my_event, push_obj);
117     }
118     else {
119         AFB_WARNING("Please input display_message");
120         ret = AFB_EVENT_BAD_REQUEST;
121     }
122     return ret;
123 }
124
125 /**
126  * push on_screen_reply event
127  *
128  * #### Parameters
129  *  - request : the request
130  *
131  * #### Return
132  * 0 : success
133  * others : fail
134  *
135  */
136 int HS_Client::on_screen_reply(afb_req_t request)
137 {
138     int ret = 0;
139     const char* value = afb_req_value(request, _reply_message);
140     if (value) {
141         AFB_INFO("push %s event message [%s].", __FUNCTION__, value);
142         struct json_object* push_obj = json_object_new_object();
143         hs_add_object_to_json_object_str( push_obj, 4, _reply_message, value,
144         _type, __FUNCTION__);
145         afb_event_push(my_event, push_obj);
146     }
147     else {
148         AFB_WARNING("Please input reply_message");
149         ret = AFB_EVENT_BAD_REQUEST;
150     }
151     return ret;
152 }
153
154 /**
155  * subscribe event
156  *
157  * #### Parameters
158  *  - request : the request
159  *
160  * #### Return
161  * 0 : success
162  * others : fail
163  *
164  */
165 int HS_Client::subscribe(afb_req_t request)
166 {
167     int ret = 0;
168     const char *value = afb_req_value(request, _event);
169     if(value) {
170         AFB_INFO("subscribe event %s", value);
171         if(!isSupportEvent(value)) {
172             AFB_WARNING("subscibe event isn't existing.");
173             ret = AFB_EVENT_BAD_REQUEST;
174         }
175         else {
176             event_list.insert(std::string(value));
177             if(!subscription) {
178                 ret = afb_req_subscribe(request, my_event);
179                 if(ret == 0) {
180                     subscription = true;
181                 }
182             }
183         }
184     }
185     else {
186         AFB_WARNING("Please input event name");
187         ret = AFB_EVENT_BAD_REQUEST;
188     }
189     return ret;
190 }
191
192 /**
193  * unsubscribe event
194  *
195  * #### Parameters
196  *  - request : the request
197  *
198  * #### Return
199  * 0 : success
200  * others : fail
201  *
202  */
203 int HS_Client::unsubscribe(afb_req_t request)
204 {
205     int ret = 0;
206     const char *value = afb_req_value(request, _event);
207     if(value) {
208         AFB_INFO("unsubscribe %s event", value);
209         event_list.erase(std::string(value));
210         if(event_list.empty()) {
211             ret = afb_req_unsubscribe(request, my_event);
212         }
213     }
214     else {
215         AFB_WARNING("Please input event name");
216         ret = AFB_EVENT_BAD_REQUEST;
217     }
218     return ret;
219 }
220
221 /**
222  * showWindow event
223  *
224  * #### Parameters
225  * - request : the request
226  *
227  * #### Return
228  * 0 : success
229  * others : fail
230  *
231  */
232 int HS_Client::showWindow(afb_req_t request)
233 {
234     AFB_INFO("%s application_id = %s.", __FUNCTION__, my_id.c_str());
235     int ret = 0;
236     const char* param = afb_req_value(request, _parameter);
237     if(param) {
238         std::string req_appid = std::move(get_application_id(request));
239         if(req_appid.empty()) {
240             AFB_WARNING("can't get application identifier");
241             return AFB_REQ_GETAPPLICATIONID_ERROR;
242         }
243
244         struct json_object* push_obj = json_object_new_object();
245         hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, __FUNCTION__);
246         struct json_object* param_obj = json_tokener_parse(param);
247         json_object_object_add(param_obj, _replyto, json_object_new_string(req_appid.c_str()));
248         json_object_object_add(push_obj, _parameter, param_obj);
249         afb_event_push(my_event, push_obj);
250     }
251     else {
252         AFB_WARNING("please input correct parameter.");
253         ret = AFB_EVENT_BAD_REQUEST;
254     }
255     return ret;
256 }
257
258 /**
259  * hideWindow event
260  *
261  * #### Parameters
262  * - request : the request
263  *
264  * #### Return
265  * 0 : success
266  * others : fail
267  *
268  */
269 int HS_Client::hideWindow(afb_req_t request)
270 {
271     std::string req_appid = std::move(get_application_id(request));
272     if(req_appid.empty()) {
273         AFB_WARNING("can't get application identifier");
274         return AFB_REQ_GETAPPLICATIONID_ERROR;
275     }
276
277     struct json_object* push_obj = json_object_new_object();
278     hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(),
279     _type, __FUNCTION__);
280     struct json_object* param_obj = json_object_new_object();
281     json_object_object_add(param_obj, _caller, json_object_new_string(req_appid.c_str()));
282     json_object_object_add(push_obj, _parameter, param_obj);
283     afb_event_push(my_event, push_obj);
284     return 0;
285 }
286
287 /**
288  * replyShowWindow event
289  *
290  * #### Parameters
291  * - request : the request
292  *
293  * #### Return
294  * 0 : success
295  * others : fail
296  *
297  */
298 int HS_Client::replyShowWindow(afb_req_t request)
299 {
300     AFB_INFO("%s application_id = %s.", __FUNCTION__, my_id.c_str());
301     int ret = 0;
302     const char* param = afb_req_value(request, _parameter);
303     if(param) {
304         struct json_object* push_obj = json_object_new_object();
305         hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, __FUNCTION__);
306         json_object_object_add(push_obj, _parameter, json_tokener_parse(param));
307         afb_event_push(my_event, push_obj);
308     }
309     else {
310         AFB_WARNING("please input correct parameter.");
311         ret = AFB_EVENT_BAD_REQUEST;
312     }
313     return ret;
314 }
315
316 /**
317  * showNotification event
318  *
319  * #### Parameters
320  *  - request : the request
321  *
322  * #### Return
323  * 0 : success
324  * others : fail
325  *
326  */
327 int HS_Client::showNotification(afb_req_t request)
328 {
329     int ret = 0;
330     const char *value = afb_req_value(request, _text);
331     if(value) {
332         AFB_INFO("text is %s", value);
333         std::string appid =std::move(get_application_id(request));
334         if(appid.empty()) {
335             AFB_WARNING("can't get application identifier");
336             return AFB_REQ_GETAPPLICATIONID_ERROR;
337         }
338
339         const char *icon = afb_req_value(request, _icon);
340         if(icon) {
341             struct json_object* param_obj = json_object_new_object();
342             json_object_object_add(param_obj, _icon, json_object_new_string(icon));
343             json_object_object_add(param_obj, _text, json_object_new_string(value));
344             json_object_object_add(param_obj, _caller, json_object_new_string(appid.c_str()));
345             struct json_object* push_obj = json_object_new_object();
346             hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, __FUNCTION__);
347             json_object_object_add(push_obj, _parameter, param_obj);
348             afb_event_push(my_event, push_obj);
349         }
350         else {
351             AFB_WARNING("please input icon.");
352             ret = AFB_REQ_SHOWNOTIFICATION_ERROR;
353         }
354     }
355     else {
356         AFB_WARNING("please input text.");
357         ret = AFB_REQ_SHOWNOTIFICATION_ERROR;
358     }
359
360     return ret;
361 }
362
363 /**
364  * showInformation event
365  *
366  * #### Parameters
367  *  - request : the request
368  *
369  * #### Return
370  * 0 : success
371  * others : fail
372  *
373  */
374 int HS_Client::showInformation(afb_req_t request)
375 {
376     int ret = 0;
377     const char *value = afb_req_value(request, _info);
378     if(value) {
379         AFB_INFO("info is %s", value);
380         std::string appid = std::move(get_application_id(request));
381         if(appid.empty()) {
382             AFB_WARNING("can't get application identifier");
383             return AFB_REQ_GETAPPLICATIONID_ERROR;
384         }
385
386         struct json_object* param_obj = json_object_new_object();
387         json_object_object_add(param_obj, _info, json_object_new_string(value));
388         struct json_object* push_obj = json_object_new_object();
389         hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, __FUNCTION__);
390         json_object_object_add(push_obj, _parameter, param_obj);
391         afb_event_push(my_event, push_obj);
392     }
393     else {
394         AFB_WARNING("please input information.");
395         ret = AFB_REQ_SHOWINFORMATION_ERROR;
396     }
397
398     return ret;
399 }
400
401 /**
402  * check if client subscribe event
403  *
404  * #### Parameters
405  *  - event: homescreen event, tap_shortcut etc.
406  *
407  * #### Return
408  * true: found
409  * false: not found
410  *
411  */
412 bool HS_Client::checkEvent(const char* event)
413 {
414     auto ip = event_list.find(std::string(event));
415     if(ip == event_list.end())
416         return false;
417     else
418         return true;
419 }
420
421 /**
422  * check if event is supporting
423  *
424  * #### Parameters
425  *  - event: homescreen event, tap_shortcut etc.
426  *
427  * #### Return
428  * true: support
429  * false: not fosupportund
430  *
431  */
432 bool HS_Client::isSupportEvent(const char* event)
433 {
434     auto ip = func_list.find(std::string(event));
435     if(ip == func_list.end())
436         return false;
437     else
438         return true;
439 }
440
441 /**
442  * handle homescreen event
443  *
444  * #### Parameters
445  *  - request : the request
446  *  - verb: request verb name
447  *
448  * #### Return
449  * 0: success
450  * others: fail
451  *
452  */
453 int HS_Client::handleRequest(afb_req_t request, const char *verb)
454 {
455     if((strcasecmp(verb, "subscribe") && strcasecmp(verb, "unsubscribe")) && !checkEvent(verb))
456         return 0;
457
458     int ret = AFB_EVENT_BAD_REQUEST;
459     auto ip = func_list.find(std::string(verb));
460     if(ip != func_list.end() && ip->second != nullptr) {
461         AFB_INFO("[%s]verb found", verb);
462         ret = (this->*(ip->second))(request);
463     }
464     return ret;
465 }
466
467 /**
468  * push event
469  *
470  * #### Parameters
471  *  - event : the event want to push
472  *  - param : the parameter contents of event
473  *
474  * #### Return
475  * 0 : success
476  * others : fail
477  *
478  */
479 int HS_Client::pushEvent(const char *event, struct json_object *param)
480 {
481     if(!checkEvent(event))
482         return 0;
483
484     AFB_INFO("called, event=%s.",event);
485     struct json_object* push_obj = json_object_new_object();
486     hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, event);
487     if(param != nullptr)
488         json_object_object_add(push_obj, _parameter, param);
489     afb_event_push(my_event, push_obj);
490     return 0;
491 }