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