fix not can not receiver event bug
[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 "unistd.h"
19 #include "hs-client.h"
20 #include "hs-helper.h"
21
22 static const char _event[] = "event";
23 static const char _type[] = "type";
24 static const char _text[] = "text";
25 static const char _info[] = "info";
26 static const char _icon[] = "icon";
27 static const char _parameter[] = "parameter";
28 static const char _replyto[] = "replyto";
29 static const char _caller[] = "caller";
30 static const char _shortcut[] = "shortcut";
31 static const char _shortcut_id[] = "shortcut_id";
32 static const char _shortcut_name[] = "shortcut_name";
33
34 // homescreen-service event and event handler function list
35 const std::unordered_map<std::string, HS_Client::func_handler> HS_Client::func_list {
36     {"tap_shortcut",        &HS_Client::tap_shortcut},
37     {"showWindow",          &HS_Client::showWindow},
38     {"hideWindow",          &HS_Client::hideWindow},
39     {"replyShowWindow",     &HS_Client::replyShowWindow},
40     {"on_screen_message",   &HS_Client::on_screen_message},
41     {"on_screen_reply",     &HS_Client::on_screen_reply},
42     {"subscribe",           &HS_Client::subscribe},
43     {"unsubscribe",         &HS_Client::unsubscribe},
44     {"showNotification",    &HS_Client::showNotification},
45     {"showInformation",     &HS_Client::showInformation},
46     {"registerShortcut",    &HS_Client::registerShortcut},
47     {"updateShortcut",      &HS_Client::updateShortcut}
48 };
49
50 std::list<std::pair<std::string, std::string>> HS_Client::shortcut_list;
51
52 /**
53  * HS_Client construction function
54  *
55  * #### Parameters
56  *  - id: app's id
57  *
58  * #### Return
59  * None
60  *
61  */
62 HS_Client::HS_Client(afb_req_t request, std::string id) : my_id(id)
63 {
64     AFB_DEBUG("called.");
65     my_event = afb_api_make_event(request->api, id.c_str());
66 }
67
68 /**
69  * HS_Client destruction function
70  *
71  * #### Parameters
72  *  - null
73  *
74  * #### Return
75  * None
76  *
77  */
78 HS_Client::~HS_Client()
79 {
80     AFB_DEBUG("called.");
81     afb_event_unref(my_event);
82 }
83
84 /**
85  * push tap_shortcut event
86  *
87  * #### Parameters
88  *  - request : the request
89  *
90  * #### Return
91  * 0 : success
92  * others : fail
93  *
94  */
95 int HS_Client::tap_shortcut(afb_req_t request)
96 {
97     AFB_INFO("request appid = %s.", my_id.c_str());
98     struct json_object* push_obj = json_object_new_object();
99     hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(),
100     _type, __FUNCTION__);
101     afb_event_push(my_event, push_obj);
102     return 0;
103 }
104
105 /**
106  * push on_screen_message event
107  *
108  * #### Parameters
109  *  - request : the request
110  *
111  * #### Return
112  * 0 : success
113  * others : fail
114  *
115  */
116 int HS_Client::on_screen_message(afb_req_t request)
117 {
118     int ret = 0;
119     const char* value = afb_req_value(request, _display_message);
120     if (value) {
121         AFB_INFO("push %s event message [%s].", __FUNCTION__, value);
122         struct json_object* push_obj = json_object_new_object();
123         hs_add_object_to_json_object_str( push_obj, 4, _display_message, value,
124         _type, __FUNCTION__);
125         afb_event_push(my_event, push_obj);
126     }
127     else {
128         AFB_WARNING("Please input display_message");
129         ret = AFB_EVENT_BAD_REQUEST;
130     }
131     return ret;
132 }
133
134 /**
135  * push on_screen_reply event
136  *
137  * #### Parameters
138  *  - request : the request
139  *
140  * #### Return
141  * 0 : success
142  * others : fail
143  *
144  */
145 int HS_Client::on_screen_reply(afb_req_t request)
146 {
147     int ret = 0;
148     const char* value = afb_req_value(request, _reply_message);
149     if (value) {
150         AFB_INFO("push %s event message [%s].", __FUNCTION__, value);
151         struct json_object* push_obj = json_object_new_object();
152         hs_add_object_to_json_object_str( push_obj, 4, _reply_message, value,
153         _type, __FUNCTION__);
154         afb_event_push(my_event, push_obj);
155     }
156     else {
157         AFB_WARNING("Please input reply_message");
158         ret = AFB_EVENT_BAD_REQUEST;
159     }
160     return ret;
161 }
162
163 /**
164  * subscribe event
165  *
166  * #### Parameters
167  *  - request : the request
168  *
169  * #### Return
170  * 0 : success
171  * others : fail
172  *
173  */
174 int HS_Client::subscribe(afb_req_t request)
175 {
176     AFB_DEBUG(" called.");
177     int ret = 0;
178     const char *value = afb_req_value(request, _event);
179     if(value) {
180         AFB_INFO("subscribe event %s", value);
181         if(!isSupportEvent(value)) {
182             AFB_WARNING("subscibe event isn't existing.");
183             ret = AFB_EVENT_BAD_REQUEST;
184         }
185         else {
186             event_list.insert(std::string(value));
187             if(!subscription) {
188                 ret = afb_req_subscribe(request, my_event);
189                 if(ret == 0) {
190                     subscription = true;
191                 }
192             }
193             if (!strcasecmp("updateShortcut", value)) {
194                 pushUpdateShortcutEvent();
195             }
196         }
197     }
198     else {
199         AFB_WARNING("Please input event name");
200         ret = AFB_EVENT_BAD_REQUEST;
201     }
202     return ret;
203 }
204
205 /**
206  * unsubscribe event
207  *
208  * #### Parameters
209  *  - request : the request
210  *
211  * #### Return
212  * 0 : success
213  * others : fail
214  *
215  */
216 int HS_Client::unsubscribe(afb_req_t request)
217 {
218     AFB_DEBUG(" called.");
219     int ret = 0;
220     const char *value = afb_req_value(request, _event);
221     if(value) {
222         AFB_INFO("unsubscribe %s event", value);
223         event_list.erase(std::string(value));
224         if(event_list.empty()) {
225             ret = afb_req_unsubscribe(request, my_event);
226         }
227     }
228     else {
229         AFB_WARNING("Please input event name");
230         ret = AFB_EVENT_BAD_REQUEST;
231     }
232     return ret;
233 }
234
235 /**
236  * showWindow event
237  *
238  * #### Parameters
239  * - request : the request
240  *
241  * #### Return
242  * 0 : success
243  * others : fail
244  *
245  */
246 int HS_Client::showWindow(afb_req_t request)
247 {
248     AFB_INFO("%s application_id = %s.", __FUNCTION__, my_id.c_str());
249     int ret = 0;
250     struct json_object* push_obj = json_object_new_object();
251     hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, __FUNCTION__);
252     const char* param = afb_req_value(request, _parameter);
253     if(param) {
254         std::string req_appid = std::move(get_application_id(request));
255         if(req_appid.empty()) {
256             AFB_WARNING("can't get application identifier");
257             return AFB_REQ_GETAPPLICATIONID_ERROR;
258         }
259
260         struct json_object* param_obj = json_tokener_parse(param);
261         json_object_object_add(param_obj, _replyto, json_object_new_string(req_appid.c_str()));
262         json_object_object_add(push_obj, _parameter, param_obj);
263         afb_event_push(my_event, push_obj);
264     }
265     else {
266         AFB_WARNING("please input correct parameter.");
267         ret = AFB_EVENT_BAD_REQUEST;
268     }
269     return ret;
270 }
271
272 /**
273  * hideWindow event
274  *
275  * #### Parameters
276  * - request : the request
277  *
278  * #### Return
279  * 0 : success
280  * others : fail
281  *
282  */
283 int HS_Client::hideWindow(afb_req_t request)
284 {
285     AFB_DEBUG(" called.");
286     std::string req_appid = std::move(get_application_id(request));
287     if(req_appid.empty()) {
288         AFB_WARNING("can't get application identifier");
289         return AFB_REQ_GETAPPLICATIONID_ERROR;
290     }
291
292     struct json_object* push_obj = json_object_new_object();
293     hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(),
294     _type, __FUNCTION__);
295     struct json_object* param_obj = json_object_new_object();
296     json_object_object_add(param_obj, _caller, json_object_new_string(req_appid.c_str()));
297     json_object_object_add(push_obj, _parameter, param_obj);
298     afb_event_push(my_event, push_obj);
299     return 0;
300 }
301
302 /**
303  * replyShowWindow event
304  *
305  * #### Parameters
306  * - request : the request
307  *
308  * #### Return
309  * 0 : success
310  * others : fail
311  *
312  */
313 int HS_Client::replyShowWindow(afb_req_t request)
314 {
315     AFB_INFO("%s application_id = %s.", __FUNCTION__, my_id.c_str());
316     int ret = 0;
317     struct json_object* push_obj = json_object_new_object();
318     hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, __FUNCTION__);
319     const char* param = afb_req_value(request, _parameter);
320     if(param) {
321         json_object_object_add(push_obj, _parameter, json_tokener_parse(param));
322         afb_event_push(my_event, push_obj);
323     }
324     else {
325         AFB_WARNING("please input correct parameter.");
326         ret = AFB_EVENT_BAD_REQUEST;
327     }
328     return ret;
329 }
330
331 /**
332  * showNotification event
333  *
334  * #### Parameters
335  *  - request : the request
336  *
337  * #### Return
338  * 0 : success
339  * others : fail
340  *
341  */
342 int HS_Client::showNotification(afb_req_t request)
343 {
344     AFB_DEBUG(" called.");
345     int ret = 0;
346     const char *value = afb_req_value(request, _text);
347     if(value) {
348         AFB_INFO("text is %s", value);
349         std::string appid =std::move(get_application_id(request));
350         if(appid.empty()) {
351             AFB_WARNING("can't get application identifier");
352             return AFB_REQ_GETAPPLICATIONID_ERROR;
353         }
354
355         struct json_object* param_obj = json_object_new_object();
356         const char *icon = afb_req_value(request, _icon);
357         if(icon) {
358             json_object_object_add(param_obj, _icon, json_object_new_string(icon));
359             json_object_object_add(param_obj, _text, json_object_new_string(value));
360             json_object_object_add(param_obj, _caller, json_object_new_string(appid.c_str()));
361             struct json_object* push_obj = json_object_new_object();
362             hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, __FUNCTION__);
363             json_object_object_add(push_obj, _parameter, param_obj);
364             afb_event_push(my_event, push_obj);
365         }
366         else {
367             AFB_WARNING("please input icon.");
368             ret = AFB_REQ_SHOWNOTIFICATION_ERROR;
369         }
370     }
371     else {
372         AFB_WARNING("please input text.");
373         ret = AFB_REQ_SHOWNOTIFICATION_ERROR;
374     }
375
376     return ret;
377 }
378
379 /**
380  * showInformation event
381  *
382  * #### Parameters
383  *  - request : the request
384  *
385  * #### Return
386  * 0 : success
387  * others : fail
388  *
389  */
390 int HS_Client::showInformation(afb_req_t request)
391 {
392     AFB_DEBUG(" called.");
393     int ret = 0;
394     const char *value = afb_req_value(request, _info);
395     if(value) {
396         AFB_INFO("info is %s", value);
397         std::string appid = std::move(get_application_id(request));
398         if(appid.empty()) {
399             AFB_WARNING("can't get application identifier");
400             return AFB_REQ_GETAPPLICATIONID_ERROR;
401         }
402
403         struct json_object* param_obj = json_object_new_object();
404         json_object_object_add(param_obj, _info, json_object_new_string(value));
405         struct json_object* push_obj = json_object_new_object();
406         hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, __FUNCTION__);
407         json_object_object_add(push_obj, _parameter, param_obj);
408         afb_event_push(my_event, push_obj);
409     }
410     else {
411         AFB_WARNING("please input information.");
412         ret = AFB_REQ_SHOWINFORMATION_ERROR;
413     }
414
415     return ret;
416 }
417
418 /**
419  * registerShortcut event
420  *
421  * #### Parameters
422  *  - request : the request
423  *
424  * #### Return
425  * 0 : success
426  * others : fail
427  *
428  */
429 int HS_Client::registerShortcut(afb_req_t request)
430 {
431     int ret = 0;
432     struct json_object *param_obj;
433     if(json_object_object_get_ex(afb_req_json(request), _parameter, &param_obj)) {
434         struct json_object* push_obj = json_object_new_object();
435         hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, __FUNCTION__);
436         json_object_object_add(push_obj, _parameter, param_obj);
437         afb_event_push(my_event, push_obj);
438     }
439     else {
440         AFB_WARNING("please input parameter.");
441         ret = AFB_EVENT_BAD_REQUEST;
442     }
443     return ret;
444 }
445
446 /**
447  * updateShortcut event
448  *
449  * #### Parameters
450  *  - request : the request
451  *
452  * #### Return
453  * 0 : success
454  * others : fail
455  *
456  */
457 int HS_Client::updateShortcut(afb_req_t request)
458 {
459     AFB_INFO("%s application_id = %s.", __FUNCTION__, my_id.c_str());
460     int ret = 0;
461     std::list<std::pair<std::string, std::string>> new_shortcut_list;
462     struct json_object *req_json = afb_req_json(request);
463     struct json_object *param_obj, *shortcut_obj;
464     if(json_object_object_get_ex(afb_req_json(request), _parameter, &param_obj)
465     && json_object_object_get_ex(param_obj, _shortcut, &shortcut_obj)) {
466         if(json_object_get_type(shortcut_obj) == json_type_array ) {
467             int array_len = json_object_array_length(shortcut_obj);
468             for (int i = 0; i < array_len; ++i) {
469                 struct json_object *obj = json_object_array_get_idx(shortcut_obj, i);
470                 struct json_object *appid_obj, *appname_obj;
471                 if(json_object_object_get_ex(obj, _shortcut_id, &appid_obj)
472                 && json_object_object_get_ex(obj, _shortcut_name, &appname_obj)) {
473                     new_shortcut_list.push_back(std::pair<std::string, std::string>(json_object_get_string(appid_obj), 
474                                                                                     json_object_get_string(appname_obj)));
475                 }
476                 else {
477                     AFB_WARNING("shortcut list json object pattern error.");
478                     ret = AFB_EVENT_BAD_REQUEST;
479                     break;
480                 }
481             }
482         }
483         else {
484             AFB_WARNING("json object pattern error.");
485             ret = AFB_EVENT_BAD_REQUEST;
486         }
487     }
488     else {
489         AFB_WARNING("input json object error.");
490         ret = AFB_EVENT_BAD_REQUEST;
491     }
492
493     if(ret == 0) {
494         HS_Client::shortcut_list.swap(new_shortcut_list);
495         pushUpdateShortcutEvent();
496     }
497     return ret;
498 }
499
500 /**
501  * check if client subscribe event
502  *
503  * #### Parameters
504  *  - event: homescreen event, tap_shortcut etc.
505  *
506  * #### Return
507  * true: found
508  * false: not found
509  *
510  */
511 bool HS_Client::checkEvent(const char* event)
512 {
513     auto ip = event_list.find(std::string(event));
514     if(ip == event_list.end())
515         return false;
516     else
517         return true;
518 }
519
520 /**
521  * check if event is supporting
522  *
523  * #### Parameters
524  *  - event: homescreen event, tap_shortcut etc.
525  *
526  * #### Return
527  * true: support
528  * false: not fosupportund
529  *
530  */
531 bool HS_Client::isSupportEvent(const char* event)
532 {
533     int ret = hs_search_event_name_index(event);
534     return ret == -1 ? false : true;
535 }
536
537 /**
538  * handle homescreen event
539  *
540  * #### Parameters
541  *  - request : the request
542  *  - verb: request verb name
543  *
544  * #### Return
545  * 0: success
546  * others: fail
547  *
548  */
549 int HS_Client::handleRequest(afb_req_t request, const char *verb)
550 {
551     AFB_DEBUG("called.");
552     if((strcasecmp(verb, "subscribe") && strcasecmp(verb, "unsubscribe")) && !checkEvent(verb))
553         return 0;
554
555     int ret = AFB_EVENT_BAD_REQUEST;
556     auto ip = func_list.find(std::string(verb));
557     if(ip != func_list.end() && ip->second != nullptr) {
558         AFB_INFO("[%s]verb found", verb);
559         ret = (this->*(ip->second))(request);
560     }
561     return ret;
562 }
563
564 /**
565  * push event
566  *
567  * #### Parameters
568  *  - event : the event want to push
569  *  - param : the parameter contents of event
570  *
571  * #### Return
572  * 0 : success
573  * others : fail
574  *
575  */
576 int HS_Client::pushEvent(const char *event, struct json_object *param)
577 {
578     if(!checkEvent(event))
579         return 0;
580
581     sleep(1);
582     AFB_INFO("called, event=%s.",event);
583     struct json_object* push_obj = json_object_new_object();
584     hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, event);
585     if(param != nullptr)
586         json_object_object_add(push_obj, _parameter, param);
587     afb_event_push(my_event, push_obj);
588     return 0;
589 }
590
591 /**
592  * push updateShortcut event
593  *
594  * #### Parameters
595  *  None
596  *
597  * #### Return
598  * Nothing
599  *
600  */
601 void HS_Client::pushUpdateShortcutEvent(void)
602 {
603     struct json_object* arr_obj = json_object_new_array();
604     for(auto &it : HS_Client::shortcut_list) {
605         struct json_object* obj = json_object_new_object();
606         json_object_object_add(obj, _shortcut_id, json_object_new_string(it.first.c_str()));
607         json_object_object_add(obj, _shortcut_name, json_object_new_string(it.second.c_str()));
608         json_object_array_add(arr_obj, obj);
609     }
610     struct json_object* shortcut_obj = json_object_new_object();
611     json_object_object_add(shortcut_obj, _shortcut, arr_obj);
612     struct json_object* push_obj = json_object_new_object();
613     hs_add_object_to_json_object_str(push_obj, 4, _application_id, my_id.c_str(), _type, "updateShortcut");
614     json_object_object_add(push_obj, _parameter, shortcut_obj);
615     afb_event_push(my_event, push_obj);
616 }