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