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