set area in showWindow
[apps/agl-service-homescreen.git] / src / hs-clientmanager.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 <algorithm>
19 #include "hs-clientmanager.h"
20 #include "hs-apprecover.h"
21
22 static const char _homescreen[] = "homescreen";
23 static const char _area[] = "area";
24 static const char _parameter[] = "parameter";
25 const std::string _listen_all("all");
26
27 HS_ClientManager* HS_ClientManager::me = nullptr;
28
29 static void cbRemoveClientCtxt(void *data)
30 {
31     HS_ClientManager::instance()->removeClientCtxt(data);
32 }
33
34 /**
35  * HS_ClientManager construction function
36  *
37  * #### Parameters
38  *  - Nothing
39  *
40  * #### Return
41  * None
42  *
43  */
44 HS_ClientManager::HS_ClientManager()
45 {
46 }
47
48 /**
49  * get instance
50  *
51  * #### Parameters
52  *  - Nothing
53  *
54  * #### Return
55  * HS_ClientManager instance pointer
56  *
57  */
58 HS_ClientManager* HS_ClientManager::instance(void)
59 {
60     if(me == nullptr)
61         me = new HS_ClientManager();
62
63     return me;
64 }
65
66 /**
67  * HS_ClientManager init function
68  *
69  * #### Parameters
70  *  - Nothing
71  *
72  * #### Return
73  * init result
74  *
75  */
76 int HS_ClientManager::init(void)
77 {
78     listener_list.clear();
79     std::list<listener_interface*> interface_list;
80     listener_list[_listen_all] = std::move(interface_list);
81 }
82
83 /**
84  * create client's afb_req_context
85  *
86  * #### Parameters
87  *  - appid: app's id
88  *
89  * #### Return
90  * HS_ClientCtxt pointer
91  *
92  */
93 HS_ClientCtxt* HS_ClientManager::createClientCtxt(afb_req_t req, std::string appid)
94 {
95     HS_ClientCtxt *ctxt = (HS_ClientCtxt *)afb_req_context_get(req);
96     if (!ctxt)
97     {
98         AFB_INFO( "create new session for %s", appid.c_str());
99         HS_ClientCtxt *ctxt = new HS_ClientCtxt(appid.c_str());
100         afb_req_session_set_LOA(req, 1);
101         afb_req_context_set(req, ctxt, cbRemoveClientCtxt);
102     }
103     return ctxt;
104 }
105
106 /**
107  * add Client
108  *
109  * #### Parameters
110  *  - ctxt: app's id
111  *
112  * #### Return
113  * HS_Client pointer
114  *
115  */
116 HS_Client* HS_ClientManager::addClient(afb_req_t req, std::string appid)
117 {
118     return (client_list[appid] = new HS_Client(req, appid));
119 }
120
121 /**
122  * remove Client
123  *
124  * #### Parameters
125  *  - appid: app's id
126  *
127  * #### Return
128  * None
129  *
130  */
131 void HS_ClientManager::removeClient(std::string appid)
132 {
133     delete client_list[appid];
134     client_list.erase(appid);
135 }
136
137 /**
138  * remove Client from list
139  *
140  * #### Parameters
141  *  - data: HS_ClientCtxt pointer
142  *
143  * #### Return
144  * None
145  *
146  */
147 void HS_ClientManager::removeClientCtxt(void *data)
148 {
149     HS_ClientCtxt *ctxt = (HS_ClientCtxt *)data;
150     if(ctxt == nullptr)
151     {
152         AFB_WARNING( "data is nullptr");
153         return;
154     }
155
156     AFB_INFO( "remove app %s", ctxt->id.c_str());
157     std::lock_guard<std::mutex> lock(this->mtx);
158     removeClient(ctxt->id);
159     delete appid2ctxt[ctxt->id];
160     appid2ctxt.erase(ctxt->id);
161 }
162
163 /**
164  * handle homescreen request
165  *
166  * #### Parameters
167  *  - request : the request
168  *  - verb : the verb name
169  *  - appid : to which application
170  *
171  * #### Return
172  * 0 : success
173  * others : fail
174  *
175  */
176 int HS_ClientManager::handleRequest(afb_req_t request, const char *verb, const char *appid)
177 {
178     AFB_INFO("verb=[%s],appid=[%s].", verb, appid);
179     int ret = 0;
180     bool isRegisterApp = false;
181     if(appid == nullptr) {
182         std::lock_guard<std::mutex> lock(this->mtx);
183         for(auto m : client_list) {
184             m.second->handleRequest(request, verb);
185         }
186     }
187     else {
188         std::lock_guard<std::mutex> lock(this->mtx);
189         auto ip = client_list.find(std::string(appid));
190         if(ip != client_list.end()) {
191             ret = ip->second->handleRequest(request, verb);
192         }
193         else {
194             if(!strcasecmp(verb, "subscribe")) {
195                 appid2ctxt[appid] = createClientCtxt(request, appid);
196                 HS_Client* client = addClient(request, appid);
197                 ret = client->handleRequest(request, "subscribe");
198                 isRegisterApp = true;
199             }
200             else {
201                 AFB_NOTICE("not exist session");
202                 ret = AFB_REQ_NOT_STARTED_APPLICATION;
203             }
204         }
205     }
206     if(isRegisterApp) {
207         notifyListener(request->api, std::string(appid));
208     }
209     return ret;
210 }
211
212 /**
213  * push event
214  *
215  * #### Parameters
216  *  - event : the event want to push
217  *  - param : the parameter contents of event
218  *  - appid : the destination application's id
219  *
220  * #### Return
221  * 0 : success
222  * others : fail
223  *
224  */
225 int HS_ClientManager::pushEvent(const char *event, struct json_object *param, std::string appid)
226 {
227     AFB_INFO("event=[%s], appid=[%s].", event, appid.c_str());
228     if(event == nullptr) {
229         AFB_WARNING("event name is null.");
230         return -1;
231     }
232
233     std::lock_guard<std::mutex> lock(this->mtx);
234     if(appid.empty()) { // broadcast event to clients who subscribed this event
235         for(auto m : client_list) {
236             m.second->pushEvent(event, param);
237         }
238     }
239     else {  // push event to specific client
240         auto ip = client_list.find(appid);
241         if(ip != client_list.end()) {
242             ip->second->pushEvent(event, param);
243         }
244     }
245
246     return 0;
247 }
248
249 /**
250  * check register application
251  *
252  * #### Parameters
253  *  - api : the api
254  *  - appid : register application's id
255  *
256  * #### Return
257  * true : checked
258  * false : not checked
259  *
260  */
261 bool HS_ClientManager::checkRegisterApp(afb_api_t api, const std::string &appid)
262 {
263     bool ret = true;
264     auto &ip = listener_list[_listen_all];
265     if(!ip.empty()) {
266         for(auto &it : ip) {
267             it->notify(api, appid);
268         }
269     }
270     else if(startup_appid == appid) {
271         startup_appid.clear();
272         struct json_object* json_param = json_object_new_object();
273         json_object_object_add(json_param, _area, json_object_new_string(startup_area.c_str()));
274         pushEvent("showWindow", json_param, appid);
275         startup_area.clear();
276     }
277     else {
278         ret = false;
279     }
280     return ret;
281 }
282
283 /**
284  * check whether application was started
285  *
286  * #### Parameters
287  *  - appid : application's id
288  *
289  * #### Return
290  * true : started
291  * false : not start
292  *
293  */
294 bool HS_ClientManager::isAppStarted(const std::string &appid)
295 {
296     auto it = client_list.find(appid);
297     return it != client_list.end() ? true : false;
298 }
299
300 /**
301  * add app register listener
302  *
303  * #### Parameters
304  *  - listener_interface : listener interface
305  *
306  * #### Return
307  * None
308  *
309  */
310 void HS_ClientManager::addListener(listener_interface* listener)
311 {
312     for (auto &it : listener->listenAppSet()) {
313         auto ip = listener_list.find(it);
314         if(ip != listener_list.end()) {
315             ip->second.push_back(listener);
316         }
317         else {
318             std::list<listener_interface*> lst;
319             lst.push_back(listener);
320             listener_list[it] = std::move(lst);
321         }
322     }
323 }
324
325 /**
326  * remove app register listener
327  *
328  * #### Parameters
329  *  - listener_interface : listener interface
330  *
331  * #### Return
332  * None
333  *
334  */
335 void HS_ClientManager::removeListener(listener_interface* listener)
336 {
337     for (auto &iter : listener->listenAppSet()) {
338         auto it = listener_list.find(iter);
339         if(it != listener_list.end()) {
340             auto ip = it->second.begin();
341             for(; ip != it->second.end(); ++ip) {
342                 if(listener->myUid() == (*ip)->myUid()) {
343                     break;
344                 }
345             }
346             it->second.erase(ip);
347             if(it->second.empty()) {
348                 listener_list.erase(it->first);
349             }
350         }
351     }
352 }
353
354 /**
355  * notify listener
356  *
357  * #### Parameters
358  *  - api : the api
359  *  - appid : register application's id
360  *
361  * #### Return
362  * None
363  *
364  */
365 void HS_ClientManager::notifyListener(afb_api_t api, const std::string &appid)
366 {
367     if (checkRegisterApp(api, appid)) {
368         return;
369     }
370
371     AFB_INFO("listen %s, notified", appid.c_str());
372     std::list<listener_interface*> interface_list;
373     auto ip = listener_list.find(appid);
374     if(ip != listener_list.end()) {
375         if(!ip->second.empty()) {
376             interface_list = ip->second;
377         }
378         else {
379             AFB_WARNING("listener is null.");
380             return;
381         }
382     }
383
384     for(auto &it : interface_list) {
385         it->notify(api, appid);
386     }
387
388 }