don't access vhsl-capbilities when it isn't existing
[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     const char *value = afb_req_value(request, _event);
175     if(value) {
176         AFB_INFO("subscribe event %s", value);
177         if(!isSupportEvent(value)) {
178             AFB_WARNING("subscibe event isn't existing.");
179             ret = AFB_EVENT_BAD_REQUEST;
180         }
181         else {
182             event_list.insert(std::string(value));
183             if(!subscription) {
184                 ret = afb_req_subscribe(request, my_event);
185                 if(ret == 0) {
186                     subscription = true;
187                 }
188             }
189         }
190     }
191     else {
192         AFB_WARNING("Please input event name");
193         ret = AFB_EVENT_BAD_REQUEST;
194     }
195     return ret;
196 }
197
198 /**
199  * unsubscribe event
200  *
201  * #### Parameters
202  *  - request : the request
203  *
204  * #### Return
205  * 0 : success
206  * others : fail
207  *
208  */
209 int HS_Client::unsubscribe(afb_req_t request)
210 {
211     int ret = 0;
212     const char *value = afb_req_value(request, _event);
213     if(value) {
214         AFB_INFO("unsubscribe %s event", value);
215         event_list.erase(std::string(value));
216         if(event_list.empty()) {
217             ret = afb_req_unsubscribe(request, my_event);
218         }
219     }
220     else {
221         AFB_WARNING("Please input event name");
222         ret = AFB_EVENT_BAD_REQUEST;
223     }
224     return ret;
225 }
226
227 /**
228  * showWindow event
229  *
230  * #### Parameters
231  * - request : the request
232  *
233  * #### Return
234  * 0 : success
235  * others : fail
236  *
237  */
238 int HS_Client::showWindow(afb_req_t request)
239 {
240     AFB_INFO("%s application_id = %s.", __FUNCTION__, my_id.c_str());
241     int ret = 0;
242     struct json_object* push_obj = json_object_new_object();
243     hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, __FUNCTION__);
244     const char* param = afb_req_value(request, _parameter);
245     if(param) {
246         std::string req_appid = std::move(get_application_id(request));
247         if(req_appid.empty()) {
248             AFB_WARNING("can't get application identifier");
249             return AFB_REQ_GETAPPLICATIONID_ERROR;
250         }
251
252         struct json_object* param_obj = json_tokener_parse(param);
253         json_object_object_add(param_obj, _replyto, json_object_new_string(req_appid.c_str()));
254         json_object_object_add(push_obj, _parameter, param_obj);
255         afb_event_push(my_event, push_obj);
256     }
257     else {
258         AFB_WARNING("please input correct parameter.");
259         ret = AFB_EVENT_BAD_REQUEST;
260     }
261     return ret;
262 }
263
264 /**
265  * hideWindow event
266  *
267  * #### Parameters
268  * - request : the request
269  *
270  * #### Return
271  * 0 : success
272  * others : fail
273  *
274  */
275 int HS_Client::hideWindow(afb_req_t request)
276 {
277     std::string req_appid = std::move(get_application_id(request));
278     if(req_appid.empty()) {
279         AFB_WARNING("can't get application identifier");
280         return AFB_REQ_GETAPPLICATIONID_ERROR;
281     }
282
283     struct json_object* push_obj = json_object_new_object();
284     hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(),
285     _type, __FUNCTION__);
286     struct json_object* param_obj = json_object_new_object();
287     json_object_object_add(param_obj, _caller, json_object_new_string(req_appid.c_str()));
288     json_object_object_add(push_obj, _parameter, param_obj);
289     afb_event_push(my_event, push_obj);
290     return 0;
291 }
292
293 /**
294  * replyShowWindow event
295  *
296  * #### Parameters
297  * - request : the request
298  *
299  * #### Return
300  * 0 : success
301  * others : fail
302  *
303  */
304 int HS_Client::replyShowWindow(afb_req_t request)
305 {
306     AFB_INFO("%s application_id = %s.", __FUNCTION__, my_id.c_str());
307     int ret = 0;
308     struct json_object* push_obj = json_object_new_object();
309     hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, __FUNCTION__);
310     const char* param = afb_req_value(request, _parameter);
311     if(param) {
312         json_object_object_add(push_obj, _parameter, json_tokener_parse(param));
313         afb_event_push(my_event, push_obj);
314     }
315     else {
316         AFB_WARNING("please input correct parameter.");
317         ret = AFB_EVENT_BAD_REQUEST;
318     }
319     return ret;
320 }
321
322 /**
323  * showNotification event
324  *
325  * #### Parameters
326  *  - request : the request
327  *
328  * #### Return
329  * 0 : success
330  * others : fail
331  *
332  */
333 int HS_Client::showNotification(afb_req_t request)
334 {
335     int ret = 0;
336     const char *value = afb_req_value(request, _text);
337     if(value) {
338         AFB_INFO("text is %s", value);
339         std::string appid =std::move(get_application_id(request));
340         if(appid.empty()) {
341             AFB_WARNING("can't get application identifier");
342             return AFB_REQ_GETAPPLICATIONID_ERROR;
343         }
344
345         struct json_object* param_obj = json_object_new_object();
346         const char *icon = afb_req_value(request, _icon);
347         if(icon) {
348             json_object_object_add(param_obj, _icon, json_object_new_string(icon));
349             json_object_object_add(param_obj, _text, json_object_new_string(value));
350             json_object_object_add(param_obj, _caller, json_object_new_string(appid.c_str()));
351             struct json_object* push_obj = json_object_new_object();
352             hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, __FUNCTION__);
353             json_object_object_add(push_obj, _parameter, param_obj);
354             afb_event_push(my_event, push_obj);
355         }
356         else {
357             AFB_WARNING("please input icon.");
358             ret = AFB_REQ_SHOWNOTIFICATION_ERROR;
359         }
360     }
361     else {
362         AFB_WARNING("please input text.");
363         ret = AFB_REQ_SHOWNOTIFICATION_ERROR;
364     }
365
366     return ret;
367 }
368
369 /**
370  * showInformation event
371  *
372  * #### Parameters
373  *  - request : the request
374  *
375  * #### Return
376  * 0 : success
377  * others : fail
378  *
379  */
380 int HS_Client::showInformation(afb_req_t request)
381 {
382     int ret = 0;
383     const char *value = afb_req_value(request, _info);
384     if(value) {
385         AFB_INFO("info is %s", value);
386         std::string appid = std::move(get_application_id(request));
387         if(appid.empty()) {
388             AFB_WARNING("can't get application identifier");
389             return AFB_REQ_GETAPPLICATIONID_ERROR;
390         }
391
392         struct json_object* param_obj = json_object_new_object();
393         json_object_object_add(param_obj, _info, json_object_new_string(value));
394         struct json_object* push_obj = json_object_new_object();
395         hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, __FUNCTION__);
396         json_object_object_add(push_obj, _parameter, param_obj);
397         afb_event_push(my_event, push_obj);
398     }
399     else {
400         AFB_WARNING("please input information.");
401         ret = AFB_REQ_SHOWINFORMATION_ERROR;
402     }
403
404     return ret;
405 }
406
407 /**
408  * registerShortcut event
409  *
410  * #### Parameters
411  *  - request : the request
412  *
413  * #### Return
414  * 0 : success
415  * others : fail
416  *
417  */
418 int HS_Client::registerShortcut(afb_req_t request)
419 {
420     int ret = 0;
421     struct json_object *param_obj;
422     if(json_object_object_get_ex(afb_req_json(request), _parameter, &param_obj)) {
423         struct json_object* push_obj = json_object_new_object();
424         hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, __FUNCTION__);
425         json_object_object_add(push_obj, _parameter, param_obj);
426         afb_event_push(my_event, push_obj);
427     }
428     else {
429         AFB_WARNING("please input parameter.");
430         ret = AFB_EVENT_BAD_REQUEST;
431     }
432     return ret;
433 }
434
435 /**
436  * updateShortcut event
437  *
438  * #### Parameters
439  *  - request : the request
440  *
441  * #### Return
442  * 0 : success
443  * others : fail
444  *
445  */
446 int HS_Client::updateShortcut(afb_req_t request)
447 {
448     AFB_INFO("%s application_id = %s.", __FUNCTION__, my_id.c_str());
449     int ret = 0;
450     std::list<std::pair<std::string, std::string>> new_shortcut_list;
451     struct json_object *req_json = afb_req_json(request);
452     struct json_object *param_obj, *shortcut_obj;
453     if(json_object_object_get_ex(afb_req_json(request), _parameter, &param_obj)
454     && json_object_object_get_ex(param_obj, _shortcut, &shortcut_obj)) {
455         if(json_object_get_type(shortcut_obj) == json_type_array ) {
456             int array_len = json_object_array_length(shortcut_obj);
457             for (int i = 0; i < array_len; ++i) {
458                 struct json_object *obj = json_object_array_get_idx(shortcut_obj, i);
459                 struct json_object *appid_obj, *appname_obj;
460                 if(json_object_object_get_ex(obj, _shortcut_id, &appid_obj)
461                 && json_object_object_get_ex(obj, _shortcut_name, &appname_obj)) {
462                     new_shortcut_list.push_back(std::pair<std::string, std::string>(json_object_get_string(appid_obj), 
463                                                                                     json_object_get_string(appname_obj)));
464                 }
465                 else {
466                     AFB_WARNING("shortcut list json object pattern error.");
467                     ret = AFB_EVENT_BAD_REQUEST;
468                     break;
469                 }
470             }
471         }
472         else {
473             AFB_WARNING("json object pattern error.");
474             ret = AFB_EVENT_BAD_REQUEST;
475         }
476     }
477     else {
478         AFB_WARNING("input json object error.");
479         ret = AFB_EVENT_BAD_REQUEST;
480     }
481
482     if(ret == 0) {
483         HS_Client::shortcut_list.swap(new_shortcut_list);
484         pushUpdateShortcutEvent();
485     }
486     return ret;
487 }
488
489 /**
490  * check if client subscribe event
491  *
492  * #### Parameters
493  *  - event: homescreen event, tap_shortcut etc.
494  *
495  * #### Return
496  * true: found
497  * false: not found
498  *
499  */
500 bool HS_Client::checkEvent(const char* event)
501 {
502     auto ip = event_list.find(std::string(event));
503     if(ip == event_list.end())
504         return false;
505     else
506         return true;
507 }
508
509 /**
510  * check if event is supporting
511  *
512  * #### Parameters
513  *  - event: homescreen event, tap_shortcut etc.
514  *
515  * #### Return
516  * true: support
517  * false: not fosupportund
518  *
519  */
520 bool HS_Client::isSupportEvent(const char* event)
521 {
522     int ret = hs_search_event_name_index(event);
523     return ret == -1 ? false : true;
524 }
525
526 /**
527  * handle homescreen event
528  *
529  * #### Parameters
530  *  - request : the request
531  *  - verb: request verb name
532  *
533  * #### Return
534  * 0: success
535  * others: fail
536  *
537  */
538 int HS_Client::handleRequest(afb_req_t request, const char *verb)
539 {
540     if((strcasecmp(verb, "subscribe") && strcasecmp(verb, "unsubscribe")) && !checkEvent(verb))
541         return 0;
542
543     int ret = AFB_EVENT_BAD_REQUEST;
544     auto ip = func_list.find(std::string(verb));
545     if(ip != func_list.end() && ip->second != nullptr) {
546         AFB_INFO("[%s]verb found", verb);
547         ret = (this->*(ip->second))(request);
548     }
549     return ret;
550 }
551
552 /**
553  * push event
554  *
555  * #### Parameters
556  *  - event : the event want to push
557  *  - param : the parameter contents of event
558  *
559  * #### Return
560  * 0 : success
561  * others : fail
562  *
563  */
564 int HS_Client::pushEvent(const char *event, struct json_object *param)
565 {
566     if(!checkEvent(event))
567         return 0;
568
569     AFB_INFO("called, event=%s.", event);
570     struct json_object* push_obj = json_object_new_object();
571     hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, event);
572     if(param != nullptr)
573         json_object_object_add(push_obj, _parameter, param);
574     afb_event_push(my_event, push_obj);
575     return 0;
576 }
577
578 /**
579  * push updateShortcut event
580  *
581  * #### Parameters
582  *  None
583  *
584  * #### Return
585  * Nothing
586  *
587  */
588 void HS_Client::pushUpdateShortcutEvent(void)
589 {
590     struct json_object* arr_obj = json_object_new_array();
591     for(auto &it : HS_Client::shortcut_list) {
592         struct json_object* obj = json_object_new_object();
593         json_object_object_add(obj, _shortcut_id, json_object_new_string(it.first.c_str()));
594         json_object_object_add(obj, _shortcut_name, json_object_new_string(it.second.c_str()));
595         json_object_array_add(arr_obj, obj);
596     }
597     struct json_object* shortcut_obj = json_object_new_object();
598     json_object_object_add(shortcut_obj, _shortcut, arr_obj);
599     struct json_object* push_obj = json_object_new_object();
600     hs_add_object_to_json_object_str(push_obj, 4, _application_id, my_id.c_str(), _type, "updateShortcut");
601     json_object_object_add(push_obj, _parameter, shortcut_obj);
602     afb_event_push(my_event, push_obj);
603 }