ab04411ee45f623b92e7a478c840980e4c0c7780
[platform/core/location/maps-plugin-here.git] / src / here_manager.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
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 <unistd.h>
18 #include <libxml/xpath.h>
19
20 #include "here_manager.h"
21 #include "here_base.h"
22 #include "here_geocode.h"
23 #include "here_revgeocode.h"
24 #include "here_multirevgeocode.h"
25 #include "here_place.h"
26 #include "here_route.h"
27 #include "here_utils.h"
28 #include "here_view.h"
29 #include "heremaps-uc-dbus.h"
30
31 #include <common/HereConfig.h>
32 #include <app.h>
33 #include <iostream>
34 #include <fstream>
35 #include <string>
36 #include <vconf.h>
37 #include <vconf-internal-location-keys.h>
38
39 using namespace HERE_PLUGIN_NAMESPACE_PREFIX;
40 using namespace TIZEN_MAPS_NAMESPACE_PREFIX;
41
42 HERE_PLUGIN_BEGIN_NAMESPACE
43
44 HereManager *HereManager::m_pHereManager = NULL;
45 int HereManager::m_nRefCnt = 0;
46 pthread_mutex_t g_mtxRef;
47
48 HereManager::HereManager()
49 : m_nNextReqId(1),
50   m_hPref(NULL)
51 {
52         xmlInitParser();
53         m_hConnection = NULL;
54         pthread_mutex_init(&m_mtxHereList, NULL);
55         pthread_mutex_init(&g_mtxRef, NULL);
56 }
57
58 HereManager::~HereManager()
59 {
60         if (m_hConnection)
61         {
62                 connection_unset_type_changed_cb(m_hConnection);
63                 connection_destroy(m_hConnection);
64                 m_hConnection = NULL;
65         }
66
67         pthread_mutex_destroy(&m_mtxHereList);
68         pthread_mutex_destroy(&g_mtxRef);
69         xmlCleanupParser();
70 }
71
72 bool HereManager::Create()
73 {
74         bool result = false;
75
76         if (!m_pHereManager)
77                 m_pHereManager = new (std::nothrow) HereManager();
78
79         pthread_mutex_lock(&g_mtxRef);
80         if (m_pHereManager)
81         {
82                 m_nRefCnt++;
83                 result = true;
84                 MAPS_LOGD("Created a HereManager instance (%d).", m_nRefCnt);
85         }
86         pthread_mutex_unlock(&g_mtxRef);
87
88         if (m_pHereManager)
89                 m_pHereManager->SetCredentials();
90         return result;
91 }
92
93 void HereManager::Close()
94 {
95         pthread_mutex_lock(&g_mtxRef);
96         bool terminate = (--m_nRefCnt == 0 && m_pHereManager);
97         pthread_mutex_unlock(&g_mtxRef);
98
99         if (terminate)
100         {
101                 m_pHereManager->TerminateAllServices();
102                 HereConfig::Shutdown();
103
104                 delete m_pHereManager;
105                 m_pHereManager = NULL;
106         }
107         MAPS_LOGD("Closed a HereManager instance (%d).", m_nRefCnt);
108 }
109
110 HereManager* HereManager::GetHandler()
111 {
112         return m_pHereManager;
113 }
114
115 void* HereManager::CreateInstance(HereSvcType nHereSvc, void* pCbFunc,
116         void* pUserData, int *nReqId)
117 {
118         HereBase *pHere = NULL;
119
120         int reqId = m_nNextReqId++;
121         if (nReqId) *nReqId = reqId;
122
123         switch(nHereSvc)
124         {
125         case HERE_SVC_GEOCODE:
126                 pHere = (HereBase*)new (std::nothrow) HereGeocode(pCbFunc, pUserData, reqId);
127                 break;
128
129         case HERE_SVC_REV_GEOCODE:
130                 pHere = (HereBase*)new (std::nothrow) HereRevGeocode(pCbFunc, pUserData, reqId);
131                 break;
132
133         case HERE_SVC_PLACE:
134                 pHere = (HereBase*)new (std::nothrow) HerePlace(pCbFunc, pUserData, reqId);
135                 break;
136
137         case HERE_SVC_ROUTE:
138                 pHere = (HereBase*)new (std::nothrow) HereRoute(pCbFunc, pUserData, reqId);
139                 break;
140
141         case HERE_SVC_MULTI_REV_GEOCODE:
142                 pHere = (HereBase*)new (std::nothrow) HereMultiRevGeocode(pCbFunc, pUserData, reqId);
143                 break;
144
145         case HERE_SVC_VIEW:
146                 pHere = (HereBase*)new (std::nothrow) HereView();
147                 break;
148
149         default:
150                 return NULL;
151         }
152
153         pthread_mutex_lock(&m_mtxHereList);
154         if (pHere)
155                 m_HereList.push_back(pHere);
156         pthread_mutex_unlock(&m_mtxHereList);
157
158         return pHere;
159 }
160
161 here_error_e HereManager::CloseInstance(int nReqId)
162 {
163         HereSvcList::iterator it;
164
165         pthread_mutex_lock(&m_mtxHereList);
166         for (it = m_HereList.begin(); it != m_HereList.end(); it++)
167         {
168                 if ((*it)->GetReqId() == nReqId)
169                 {
170                         m_HereList.erase(it);
171                         break;
172                 }
173         }
174         pthread_mutex_unlock(&m_mtxHereList);
175
176         return HERE_ERROR_NONE;
177 }
178
179 here_error_e HereManager::CancelInstance(int nReqId)
180 {
181         HereSvcList::iterator it;
182
183         pthread_mutex_lock(&m_mtxHereList);
184         for (it = m_HereList.begin(); it != m_HereList.end(); it++)
185         {
186                 if ((*it)->GetReqId() == nReqId)
187                 {
188                         m_HereList.erase(it);
189                         RestItemHandle::Cancel((*it)->GetRestReqId());
190                         (*it)->TerminateService();
191                         pthread_mutex_unlock(&m_mtxHereList);
192                         return HERE_ERROR_NONE;
193                 }
194         }
195         pthread_mutex_unlock(&m_mtxHereList);
196
197         return HERE_ERROR_NOT_FOUND;
198 }
199
200 bool HereManager::AppInfoMetadataCb(const char *metadata_key, const char *metadata_value, void *user_data)
201 {
202         if (!metadata_key || !metadata_value)
203                 return false;
204
205         if (!strncmp(metadata_key, "http://tizen.org/metadata/here_key", 35) && strlen(metadata_value) > 0 )
206         {
207                 if (m_pHereManager->SetCredentials(metadata_value) == HERE_ERROR_NONE)
208                 {
209                         MAPS_LOGD("Succeeded getting credential from metadata");
210                 }
211
212                 return false;
213         }
214
215         return true;
216 }
217
218 here_error_e HereManager::SetCredentials(void)
219 {
220         int nRet = 0;
221         app_info_h hAppInfo;
222         pid_t nProcessId = -1;
223         char *strAppId = NULL;
224
225         nProcessId = getpid();
226         nRet = app_manager_get_app_id(nProcessId, &strAppId);
227         if (nRet != APP_MANAGER_ERROR_NONE)
228         {
229                 MAPS_LOGI("Get app_id [%ld]. nRet[%d]", nProcessId, nRet);
230                 return HERE_ERROR_NONE;
231         }
232
233         nRet = app_info_create(strAppId, &hAppInfo);
234         if (nRet != APP_MANAGER_ERROR_NONE)
235         {
236                 MAPS_LOGI("Get appinfo of [%s]. nRet[%d]", strAppId, nRet);
237                 if (strAppId) free(strAppId);
238                 return HERE_ERROR_NONE;
239         }
240
241         if (strAppId) free(strAppId);
242
243         nRet = app_info_foreach_metadata(hAppInfo, AppInfoMetadataCb, NULL);
244         if (nRet != APP_MANAGER_ERROR_NONE)
245         {
246                 MAPS_LOGI("Get metadata. nRet[%d]", nRet);
247         }
248
249         nRet = app_info_destroy(hAppInfo);
250         if (nRet != APP_MANAGER_ERROR_NONE)
251         {
252                 MAPS_LOGI("Destroy app_info. nRet[%d]", nRet);
253         }
254
255         return HERE_ERROR_NONE;
256 }
257
258 here_error_e HereManager::SetCredentials(const char *szKey)
259 {
260         if (!szKey)
261                 return HERE_ERROR_INVALID_PARAMETER;
262
263         String strKey(szKey);
264         String strAppId, strAppCode, strRequestAppId = "";
265         size_t nCodeStart;
266
267         nCodeStart = strKey.find("/");
268
269         if(nCodeStart == 0 || nCodeStart >= (strKey.length()-1))
270         {
271                 MAPS_LOGE("[error] Key type fault : Key type should be as like XXXXX/YYYYY");
272                 return HERE_ERROR_INVALID_PARAMETER;
273         }
274
275         strAppId = strKey.substr(0, nCodeStart);
276         strAppCode = strKey.substr(nCodeStart+1, std::string::npos);
277
278         if (ApplicationContext::GetInstance().GetRequestAppId().length() < 1) {
279                 char *strAppId = NULL;
280                 pid_t nProcessId = getpid();
281
282                 app_manager_get_app_id(nProcessId, &strAppId);
283                 if (strAppId != NULL) {
284                         MAPS_LOGE("RequestAppId is %s", strAppId);
285                         strRequestAppId.append(strAppId);
286                         g_free(strAppId);
287                 }
288         } else
289                 strRequestAppId = ApplicationContext::GetInstance().GetRequestAppId();
290
291         if(!ApplicationContext::GetInstance().Initialize(strAppCode, strAppId, strRequestAppId))
292                 return HERE_ERROR_INVALID_OPERATION;
293
294         //MAPS_LOGD("[success] credential setted to 'XXXXX/XXXXX'");
295
296         return HERE_ERROR_NONE;
297 }
298
299 here_error_e HereManager::GetCredentials(char **szKey)
300 {
301         if (!szKey)
302                 return HERE_ERROR_INVALID_PARAMETER;
303
304         if (!ApplicationContext::GetInstance().IsInitialized())
305                 return HERE_ERROR_NOT_FOUND;
306
307         String strCredentials = ApplicationContext::GetInstance().GetAppId() + "/" +
308                                 ApplicationContext::GetInstance().GetAppCode();
309
310         *szKey = g_strndup(strCredentials.c_str(), strCredentials.length());
311
312         if (*szKey == NULL)
313                 return HERE_ERROR_INVALID_OPERATION;
314
315         //MAPS_LOGD("current credential : %s", *szKey);
316
317         return HERE_ERROR_NONE;
318 }
319
320 here_error_e HereManager::SetPreference(maps_preference_h hPref)
321 {
322         int error = HERE_ERROR_NONE;
323
324         if (!hPref)
325                 return HERE_ERROR_INVALID_PARAMETER;
326
327         if (m_hPref)
328         {
329                 if (maps_preference_destroy(m_hPref) != MAPS_ERROR_NONE)
330                         return HERE_ERROR_INVALID_OPERATION;
331         }
332
333         do {
334                 error = maps_preference_clone(hPref, &m_hPref);
335                 if (error != MAPS_ERROR_NONE) break;
336
337                 char *szLanguage = NULL;
338                 error = maps_preference_get_language(hPref, &szLanguage);
339                 if (error == MAPS_ERROR_NONE && szLanguage && strlen(szLanguage) > 0)
340                         ApplicationContext::GetInstance().SetPreferredLanguage(String(szLanguage));
341         } while(0);
342
343         return (here_error_e)ConvertToHereError(error);
344 }
345
346 here_error_e HereManager::GetPreference(maps_preference_h *hPref)
347 {
348         int ret = HERE_ERROR_NONE;
349
350         if (!hPref)
351                 return HERE_ERROR_INVALID_PARAMETER;
352
353         if (!m_hPref)
354                 return HERE_ERROR_NOT_FOUND;
355
356         ret = maps_preference_clone(m_hPref, hPref);
357
358         return (here_error_e)ConvertToHereError(ret);
359 }
360
361 maps_preference_h HereManager::GetPreference()
362 {
363         return m_hPref;
364 }
365
366 void HereManager::TerminateAllServices(void)
367 {
368         HereSvcList::iterator it;
369
370         while (1)
371         {
372                 pthread_mutex_lock(&m_mtxHereList);
373                 if (m_HereList.empty())
374                 {
375                         pthread_mutex_unlock(&m_mtxHereList);
376                         break;
377                 }
378                 it = m_HereList.begin();
379                 pthread_mutex_unlock(&m_mtxHereList);
380
381                 try {
382                         if (*it) (*it)->TerminateService();
383                         m_HereList.erase(it);
384                 }
385                 catch (std::exception &e) {
386                         MAPS_LOGD("Exception caught: %s", e.what());
387                 }
388         };
389
390         if (m_hPref)
391         {
392                 maps_preference_destroy(m_hPref);
393                 m_hPref = NULL;
394         }
395 }
396
397 here_error_e HereManager::ConvertNetworkErrorCode(const int nErrorCode)
398 {
399         here_error_e err = HERE_ERROR_NONE;
400
401         switch (nErrorCode)
402         {
403         case CONNECTION_ERROR_NONE:
404                 //MAPS_LOGD("No error");
405                 err = HERE_ERROR_NONE;
406                 break;
407         case CONNECTION_ERROR_INVALID_PARAMETER:
408                 MAPS_LOGD("Invalid parameter");
409                 err = HERE_ERROR_INVALID_PARAMETER;
410                 break;
411         case CONNECTION_ERROR_OUT_OF_MEMORY:
412                 MAPS_LOGD("Out of memory error");
413                 err = HERE_ERROR_OUT_OF_MEMORY;
414                 break;
415         case CONNECTION_ERROR_INVALID_OPERATION:
416                 MAPS_LOGD("Invalid Operation");
417                 err = HERE_ERROR_INVALID_OPERATION;
418                 break;
419         case CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED:
420                 MAPS_LOGD("Address family not supported");
421                 err = HERE_ERROR_NOT_SUPPORTED;
422                 break;
423         case CONNECTION_ERROR_PERMISSION_DENIED:
424                 MAPS_LOGD("Permission denied");
425                 err = HERE_ERROR_PERMISSION_DENIED;
426                 break;
427         case CONNECTION_ERROR_OPERATION_FAILED:
428                 MAPS_LOGD("Operation failed");
429                 err = HERE_ERROR_INVALID_OPERATION;
430                 break;
431         case CONNECTION_ERROR_ITERATOR_END:
432                 MAPS_LOGD("End of iteration");
433                 break;
434         case CONNECTION_ERROR_NO_CONNECTION:
435                 MAPS_LOGD("There is no connection");
436                 err = HERE_ERROR_NETWORK_UNREACHABLE;
437                 break;
438         case CONNECTION_ERROR_NOW_IN_PROGRESS:
439                 MAPS_LOGD("Now in progress");
440                 err = HERE_ERROR_RESOURCE_BUSY;
441                 break;
442         case CONNECTION_ERROR_ALREADY_EXISTS:
443                 MAPS_LOGD("Already exists");
444                 break;
445         case CONNECTION_ERROR_OPERATION_ABORTED:
446                 MAPS_LOGD("Operation is aborted");
447                 err = HERE_ERROR_CANCELED;
448                 break;
449         case CONNECTION_ERROR_DHCP_FAILED:
450                 MAPS_LOGD("DHCP failed");
451                 break;
452         case CONNECTION_ERROR_INVALID_KEY:
453                 MAPS_LOGD("Invalid key");
454                 err = HERE_ERROR_KEY_NOT_AVAILABLE;
455                 break;
456         case CONNECTION_ERROR_NO_REPLY:
457                 MAPS_LOGD("No Reply");
458                 err = HERE_ERROR_RESOURCE_BUSY;
459                 break;
460         case CONNECTION_ERROR_NOT_SUPPORTED:
461                 MAPS_LOGD("Not Supported");
462                 err = HERE_ERROR_NOT_SUPPORTED;
463                 break;
464         default:
465                 MAPS_LOGD("Unknown");
466                 break;
467         }
468         //MAPS_LOGD("nErrorCode = 0x%08X", nErrorCode);
469
470         return err;
471 }
472
473 here_error_e HereManager::SetProxyAddress()
474 {
475         int errorCode = CONNECTION_ERROR_NONE;
476
477         char *proxy_address = NULL;
478
479         if (!m_hConnection)
480         {
481                 errorCode = connection_create(&m_hConnection);
482                 if (errorCode == CONNECTION_ERROR_NONE)
483                 {
484                         errorCode = connection_set_type_changed_cb(m_hConnection, NetworkStateChangedIndCb, this);
485
486                 }
487         }
488         if (errorCode != CONNECTION_ERROR_NONE)
489                 return ConvertNetworkErrorCode(errorCode);
490
491         errorCode = connection_get_proxy(m_hConnection, CONNECTION_ADDRESS_FAMILY_IPV4, &proxy_address);
492         if (errorCode == CONNECTION_ERROR_NONE)
493         {
494                 MAPS_LOGD("Proxy = %s", (proxy_address ? proxy_address : "(null)"));
495                 Tizen::Maps::HereConfig::SetProxyAddress(proxy_address);
496         }
497         g_free(proxy_address);
498
499         return ConvertNetworkErrorCode(errorCode);
500 }
501
502 void HereManager::NetworkStateChangedIndCb(connection_type_e type, void *user_data)
503 {
504         MAPS_LOGD("Network state is changed. type=%d", type);
505
506         if (!user_data) return;
507
508         HereManager *pManager = (HereManager*)user_data;
509
510         if ((type != CONNECTION_TYPE_DISCONNECTED) && (type != CONNECTION_TYPE_BT))
511                 pManager->SetProxyAddress();
512 }
513
514 here_error_e HereManager::CheckAgreement()
515 {
516         const char UTC_TPK_APP[] = "org.tizen.capi-maps-service-native-utc";
517         const char ITC_TPK_APP[] = "org.tizen.capi-maps-service-native-itc";
518         const char UTC_APP[] = "core.capi-maps-service-tests";
519         const char ITC_APP[] = "native.capi-maps-service-itc";
520
521         int enabled = 0;
522         int ret = 0;
523         char *strAppId = NULL;
524         here_error_e error = HERE_ERROR_NONE;
525
526         ret = vconf_get_bool(VCONFKEY_LOCATION_HEREMAPS_CONSENT, &enabled);
527         MAPS_LOGD("VCONFKEY_LOCATION_HEREMAPS_CONSENT is %d", enabled);
528         if (ret != 0 || enabled == 0) {
529                 error = HERE_ERROR_SERVICE_NOT_AVAILABLE;
530                 if (ret != 0)
531                         MAPS_LOGD("Fail to get vconf value");
532
533                 pid_t nProcessId = getpid();
534                 ret = app_manager_get_app_id(nProcessId, &strAppId);
535                 if (ret != APP_MANAGER_ERROR_NONE)
536                         MAPS_LOGI("Get app_id [%ld]. nRet[%d]", nProcessId, ret);
537                 else if (!strncmp(strAppId, UTC_APP, strlen(UTC_APP)) ||
538                                 !strncmp(strAppId, ITC_APP, strlen(ITC_APP)) ||
539                                 !strncmp(strAppId, UTC_TPK_APP, strlen(UTC_TPK_APP)) ||
540                                 !strncmp(strAppId, ITC_TPK_APP, strlen(ITC_TPK_APP))) { 
541                         MAPS_LOGD("Requested by tct");
542                         error = HERE_ERROR_NONE;
543                 }
544         }
545
546         if (error != HERE_ERROR_NONE) {
547                 MAPS_LOGD("heremaps_uc_dbus_launch_receiver is called");
548                 ret = heremaps_uc_dbus_launch_receiver();
549                 if (ret != HEREMAPS_UC_DBUS_ERROR_NONE)
550                         MAPS_LOGD("heremaps_uc_dbus_launch_receiver fail");
551         } else
552                 MAPS_LOGD("Vconf value of HereMaps is true");
553
554         if (strAppId != NULL)
555                 g_free(strAppId);
556         return error;
557 }
558
559 HERE_PLUGIN_END_NAMESPACE
560