wrt-plugins-tizen_0.4.23
[framework/web/wrt-plugins-tizen.git] / src / Package / PackageManager.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an AS IS BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 #include <glib.h>
19
20 #include <JSTizenExceptionFactory.h>
21 #include <JSTizenException.h>
22 #include <GlobalContextManager.h>
23 #include <PlatformException.h>
24
25 // to get package name by appid
26 #include <app_manager.h>
27
28 // To get cert information from package
29 #include <package_manager.h>
30 #include <package_info.h>
31
32 // To get app size and installed time
33 #include <pkgmgr-info.h>
34
35 // To use ecore_thread
36 #include <Ecore.h>
37
38 #include "PackageManager.h"
39 #include "PackageInformation.h"
40 #include "JSPackageInformation.h"
41 #include <Logger.h>
42
43 using namespace WrtDeviceApis::Commons;
44 using namespace WrtDeviceApis::CommonsJavaScript;
45 using namespace DeviceAPI::Common;
46
47 using namespace std;
48
49 #ifdef __cplusplus
50 extern "C" {
51 int package_manager_client_destroy(package_manager_request_h request);
52 }
53 #endif
54
55 namespace DeviceAPI {
56 namespace Package {
57
58 PackageInfoCallbackData::PackageInfoCallbackData(JSContextRef globalCtx): 
59         CallbackUserData(globalCtx)
60 {
61     m_exceptionCode = WrtDeviceApis::Commons::ExceptionCodes::None;
62 }
63
64 PackageInfoCallbackData::~PackageInfoCallbackData()
65 {
66         // TODO: Should I clear pkgInfos?
67 }
68
69 vector<PackageInformation> PackageInfoCallbackData::getPackageInfoList()
70 {
71         return m_pkgInfos;
72 }
73
74
75 void PackageInfoCallbackData::addPackageInfo(PackageInformation pkgInfo)
76 {
77         m_pkgInfos.push_back(pkgInfo);
78 }
79
80
81 void PackageInfoCallbackData::setExceptionCode(ExceptionCodes::Enumeration exceptionCode)
82 {
83     m_exceptionCode = exceptionCode;
84 }
85
86 ExceptionCodes::Enumeration PackageInfoCallbackData::getExceptionCode() const
87 {
88         return m_exceptionCode;
89 }
90
91 PackageInfoEventCallback::PackageInfoEventCallback(CallbackUserData* oninstalled, CallbackUserData* onupdated, CallbackUserData* onuninstalled)
92 {
93         m_oninstalled = oninstalled;
94         m_onupdated = onupdated;
95         m_onuninstalled = onuninstalled;
96         m_handle_p = NULL;
97 }
98
99 PackageInfoEventCallback::~PackageInfoEventCallback()
100 {
101         if (m_oninstalled)
102                 delete m_oninstalled;
103
104         if (m_onupdated)
105                 delete m_onupdated;
106
107         if (m_onuninstalled)
108                 delete m_onuninstalled;
109 }
110
111 CallbackUserData* PackageInfoEventCallback::getOnInstalled()
112 {
113         return m_oninstalled;
114 }
115
116 CallbackUserData* PackageInfoEventCallback::getOnUpdated()
117 {
118         return m_onupdated;
119 }
120
121 CallbackUserData* PackageInfoEventCallback::getOnUninstalled()
122 {
123         return m_onuninstalled;
124 }
125
126 pkgmgr_client** PackageInfoEventCallback::getEventHandler()
127 {
128         return m_handle_p;
129 }
130
131 void PackageInfoEventCallback::setEventHandler(pkgmgr_client **handler)
132 {
133         m_handle_p = handler;
134 }
135
136 PackageInstallEventCallback::PackageInstallEventCallback(JSContextRef globalCtx, CallbackUserData* onprogress, CallbackUserData* oncomplete, CallbackUserData* onerror)
137 {
138         m_context = globalCtx;
139         m_onprogress = onprogress;
140         m_oncomplete = oncomplete;
141         m_onerror = onerror;
142         
143         m_request_handle = NULL;
144 }
145
146 PackageInstallEventCallback::~PackageInstallEventCallback()
147 {
148         if (m_request_handle != NULL) {
149                 LoggerD("destroy client handle");
150                 //package_manager_request_destroy(m_request_handle);
151                 package_manager_client_destroy(m_request_handle);
152         }
153         
154         if (m_onprogress)
155                 delete m_onprogress;
156
157         if (m_oncomplete)
158                 delete m_oncomplete;
159
160         if (m_onerror)
161                 delete m_onerror;
162 }
163
164 CallbackUserData* PackageInstallEventCallback::getOnProgress()
165 {
166         return m_onprogress;
167 }
168
169 CallbackUserData* PackageInstallEventCallback::getOnComplete()
170 {
171         return m_oncomplete;
172 }
173
174 CallbackUserData* PackageInstallEventCallback::getOnError()
175 {
176         return m_onerror;
177 }
178
179 JSContextRef PackageInstallEventCallback::getContext()
180 {
181         return m_context;
182 }
183
184 void PackageInstallEventCallback::setHandle(package_manager_request_h handle)
185 {
186         m_request_handle = handle;
187 }
188
189 package_manager_request_h PackageInstallEventCallback::getHandle()
190 {
191         return m_request_handle;
192 }
193
194 static int get_current_pkg_id(char** pkg_id)
195 {
196         LoggerD("get_current_pkg_id enter");
197         int parent_pid = getppid();
198         LoggerD("parent pid : " << parent_pid);
199         char* app_id = NULL;
200         app_info_h handle;
201
202         int ret = app_manager_get_app_id(parent_pid, &app_id);
203         if ((ret != APP_MANAGER_ERROR_NONE) || (app_id == NULL)) {
204                 LoggerD("Cannot get app id from pid : " << parent_pid);
205                 return ret;
206         } else {
207                 LoggerD("app_id : " << app_id);
208         }
209
210         ret = app_manager_get_app_info(app_id, &handle);
211         if (ret != APP_MANAGER_ERROR_NONE) {
212                 LoggerD("Fail to get appinfo by " << app_id);
213                 return ret;
214         }
215
216         ret = app_info_get_package(handle, pkg_id);
217         if ((ret != APP_MANAGER_ERROR_NONE) || (*pkg_id == NULL)) {
218                 LoggerD("Fail to get pkg_id by " << app_id);
219                 return ret;
220         }
221
222         ret = app_info_destroy(handle);
223         if (ret != APP_MANAGER_ERROR_NONE) {
224                 LoggerD("Fail to get destory appinfo");
225                 return ret;
226         }
227
228         return ret; 
229 }
230
231 static bool app_callback(package_info_app_component_type_e comp_type, const char *app_id, void *user_data)
232 {
233         //LoggerD("app_callback enter : " << app_id);
234         PackageInformation* pkgInfo = (PackageInformation*)user_data;
235         pkgInfo->m_appIds.push_back(app_id);
236         return true;
237 }
238
239 static PackageInformation* create_pkg_info(pkgmgrinfo_pkginfo_h handle)
240 {
241         //LoggerD("enter");
242
243         PackageInformation *pkgInfo = new PackageInformation();
244
245         char* id = NULL;
246         char* name = NULL;
247         char* iconPath = NULL;
248         char* version = NULL;
249         int totalSize = 0;
250         int dataSize = 0;
251         int lastModified = 0;
252         char* type = NULL;
253         char* author = NULL;
254         char* description = NULL;
255         vector<string> appIds;
256         int ret = 0;
257
258         ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &id);
259         if ((ret != PMINFO_R_OK) || (id == NULL)) {
260                 LoggerD("Fail to get id. return NULL.");
261                 delete pkgInfo;
262                 return NULL;
263         } else {
264                 pkgInfo->m_id = id;
265         }
266
267         ret = pkgmgrinfo_pkginfo_get_label(handle, &name);
268         if ((ret != PMINFO_R_OK) || (name == NULL)) {
269                 LoggerD("Fail to get labe");
270         } else {
271                 pkgInfo->m_name = name;
272         }
273
274         ret = pkgmgrinfo_pkginfo_get_icon(handle, &iconPath);
275         if ((ret != PMINFO_R_OK) || (iconPath == NULL)) {
276                 LoggerD("Fail to get iconPath");
277         } else {
278                 pkgInfo->m_iconPath = iconPath;
279         }
280
281         ret = pkgmgrinfo_pkginfo_get_version(handle, &version);
282         if ((ret != PMINFO_R_OK) || (version == NULL)) {
283                 LoggerD("Fail to get version");
284         } else {
285                 pkgInfo->m_version = version;
286         }
287
288         ret = pkgmgrinfo_pkginfo_get_total_size(handle, &totalSize);
289         if (ret != PMINFO_R_OK) {
290                 LoggerD("Fail to get totalSize");
291         } else {
292                 pkgInfo->m_totalSize = totalSize;
293         }
294
295         ret = pkgmgrinfo_pkginfo_get_data_size(handle, &dataSize);
296         if (ret != PMINFO_R_OK) {
297                 LoggerD("Fail to get dataSize");
298         } else {
299                 pkgInfo->m_dataSize = dataSize;
300         }
301
302         ret = pkgmgrinfo_pkginfo_get_installed_time(handle, &lastModified);
303         if (ret != PMINFO_R_OK) {
304                 LoggerD("Fail to get lastModified");
305         } else {
306                 pkgInfo->m_lastModified = lastModified;
307         }
308
309         ret = pkgmgrinfo_pkginfo_get_type(handle, &type);
310         if ((ret != PMINFO_R_OK) || (type == NULL)) {
311                 LoggerD("Fail to get type");
312         } else {
313                 pkgInfo->m_type = type;
314         }
315
316         ret = pkgmgrinfo_pkginfo_get_author_name(handle, &author);
317         if ((ret != PMINFO_R_OK) || (author == NULL)) {
318                 LoggerD("Fail to get author");
319         } else {
320                 pkgInfo->m_author = author;
321         }
322
323         ret = pkgmgrinfo_pkginfo_get_description(handle, &description);
324         if ((ret != PMINFO_R_OK) || (description == NULL)) {
325                 LoggerD("Fail to get description");
326         } else {
327                 pkgInfo->m_description = description;
328         }
329
330         package_info_h package_info;
331         
332         ret = package_manager_get_package_info(id, &package_info);
333         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
334                 LoggerD("Cannot create package info by : " << id);
335                 delete pkgInfo;
336                 return NULL;
337         }
338
339         ret = package_info_foreach_app_from_package(package_info, PACKAGE_INFO_ALLAPP, app_callback, (void*)pkgInfo);
340         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
341                 LoggerD("failed while getting appids");
342         }
343
344         ret = package_info_destroy(package_info);
345         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
346                 LoggerD("Cannot destroy package info");
347         }       
348
349         // REMARK: do not destroy handle. because handle is comes from outside!!
350         return pkgInfo;
351 }
352
353 static gboolean getCompleteCB(void *data)
354 {
355         LoggerD("entered");
356
357         PackageInfoCallbackData *callback = (PackageInfoCallbackData *)data;
358         JSContextRef context = callback->getContext();
359
360         if (callback->getExceptionCode() == WrtDeviceApis::Commons::ExceptionCodes::None) {
361                 vector<PackageInformation> pkgInfoList = callback->getPackageInfoList();
362                 
363             JSObjectRef jsResult = JSCreateArrayObject(context, 0, NULL);
364             if (jsResult == NULL) {
365                         JSValueRef error = JSTizenExceptionFactory::makeErrorObject(callback->getContext(), JSTizenException::UNKNOWN_ERROR, "platform exception");
366                 callback->callErrorCallback(error);
367                         return false;
368             }
369
370             for (std::size_t i = 0; i < pkgInfoList.size(); ++i) {
371                 JSValueRef tmpVal = JSPackageInformation::createJSObject(context, &pkgInfoList[i]);
372                 if (!JSSetArrayElement(context, jsResult, i, tmpVal)) {
373                                 JSValueRef error = JSTizenExceptionFactory::makeErrorObject(callback->getContext(), JSTizenException::UNKNOWN_ERROR, "platform exception");
374                         callback->callErrorCallback(error);
375                                 return false;
376                 }
377             }
378
379                 callback->callSuccessCallback(jsResult);
380         } else {
381                 LoggerD("Fail!!");
382                 JSValueRef error = JSTizenExceptionFactory::makeErrorObject(callback->getContext(), JSTizenException::UNKNOWN_ERROR, "platform exception");
383                 callback->callErrorCallback(error);
384         }
385
386         // TODO: cleanup each packageInformation items
387     delete callback;
388         
389         return false;
390 }
391
392 static int get_package_list_cb(pkgmgrinfo_pkginfo_h handle, void *user_data)
393 {
394         //LoggerD("entered");
395         PackageInfoCallbackData *callback = (PackageInfoCallbackData *)user_data;
396         PackageInformation* pkgInfo = create_pkg_info(handle);
397         if (pkgInfo != NULL) {
398                 callback->addPackageInfo(*pkgInfo);
399                 delete pkgInfo;
400         } else {
401                 LoggerE("Fail to get pkgInfo");
402         }
403         return 0;
404 }
405
406 static void getThreadCB(void *data, Ecore_Thread *thread)
407 {
408         LoggerD("entered");
409
410         PackageInfoCallbackData *callback = (PackageInfoCallbackData *)data;
411         
412         int ret = pkgmgrinfo_pkginfo_get_list(get_package_list_cb, data);
413         if (ret != PMINFO_R_OK) {
414                 LoggerD("Fail to get package info");
415                 callback->setExceptionCode(WrtDeviceApis::Commons::ExceptionCodes::PlatformException);
416         }
417
418         // the operation of ecore_thread_run() is not normal. (the finish callback is not called from main thread.)
419         // so, add complete callback to gmainloop explicitly.
420         g_idle_add(getCompleteCB, data);
421 }
422
423
424 static void package_event_cb(app_manger_event_type_e event_type, const char *package, void *user_data)
425 {
426         PackageInfoEventCallback *eventCB = (PackageInfoEventCallback *)user_data;
427         
428         switch(event_type) {
429         case APP_MANAGER_EVENT_INSTALLED: {
430                 pkgmgrinfo_pkginfo_h handle;
431                 int ret = pkgmgrinfo_pkginfo_get_pkginfo(package, &handle);
432                 if (ret != PMINFO_R_OK) {
433                         LoggerD("fail to find pkg info with given pkg : " << package);
434                         // Do not throw exception. No one can handle exception because this code is called from async callback.
435                         //throw NotFoundException("Can't find given package");
436                         break;
437                 }
438         
439                 PackageInformation* pkgInfo = create_pkg_info(handle);
440                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
441         
442                 if (pkgInfo == NULL) {
443                         LoggerD("Fail to get pkg info. skip callback call for pkgid " << package);
444                 } else {
445                         CallbackUserData *callback = eventCB->getOnInstalled();
446                         if (callback) {
447                                 callback->callSuccessCallback(JSPackageInformation::createJSObject(callback->getContext(), pkgInfo));
448                         }
449                 }
450                 break;
451         }
452         case APP_MANAGER_EVENT_UNINSTALLED: {
453                 LoggerD("uninstall : " << package);
454                 CallbackUserData *callback = eventCB->getOnUninstalled();
455                 if (callback) {
456                         Converter converter(callback->getContext());
457                         callback->callSuccessCallback(converter.toJSValueRef(package));
458                 }
459                 break;
460         }
461         case APP_MANAGER_EVENT_UPDATED: {
462                 pkgmgrinfo_pkginfo_h handle;
463                 int ret = pkgmgrinfo_pkginfo_get_pkginfo(package, &handle);
464                 if (ret != PMINFO_R_OK) {
465                         // Do not throw exception. No one can handle exception because this code is called from async callback.
466                         //throw NotFoundException("Can't find given package");
467                         break;
468                 }
469         
470                 PackageInformation* pkgInfo = create_pkg_info(handle);
471                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
472         
473                 if (pkgInfo == NULL) {
474                         LoggerD("Fail to get pkg info. skip callback call for pkgid " << package);
475                 } else {
476                         CallbackUserData *callback = eventCB->getOnUpdated();
477                         if (callback) {
478                                 callback->callSuccessCallback(JSPackageInformation::createJSObject(callback->getContext(), pkgInfo));
479                         }
480                 }
481                 break;
482         }
483         default:
484                 LoggerD("Fail!! Unknown event type is entered : " << event_type);
485                 break;
486         }
487
488         
489 }
490
491 static int app_list_changed_cb_broker(int id, const char *type, const char *package, const char *key, const char *val, const void *msg, void *data)
492 {
493         static app_manger_event_type_e event_type;
494
495         if (!strcasecmp(key, "start"))
496         {
497                 LoggerD("start ");
498                 if (!strcasecmp(val, "install"))
499                 {
500                         event_type = APP_MANAGER_EVENT_INSTALLED;
501                 }
502                 else if (!strcasecmp(val, "uninstall"))
503                 {
504                         event_type = APP_MANAGER_EVENT_UNINSTALLED;
505                 }
506                 else if (!strcasecmp(val, "update"))
507                 {
508                         event_type = APP_MANAGER_EVENT_UPDATED;
509                 }
510         }
511         else if (!strcasecmp(key, "end") && !strcasecmp(val, "ok"))
512         {
513                 LoggerD("end ");
514                 if (event_type >= 0)
515                 {
516                         package_event_cb(event_type, package, data);
517
518                         // Check whether handler is freed in the callback function or not.
519                         // if freed, return error code to avoid iteration of callback function. (core platform side)
520                         PackageInfoEventCallback * callback = (PackageInfoEventCallback *)data;
521                         pkgmgr_client ** handler_p = callback->getEventHandler();
522                         if (*handler_p == NULL) {
523                                 LoggerD("handler is NULL");
524                                 return -1;
525                         }
526                         LoggerD("handler is not NULL");
527                 }
528         }
529
530         return 0;
531 }
532
533
534 void install_request_cb(int id, const char *type, const char *package, 
535                                 package_manager_event_type_e event_type,
536                                 package_manager_event_state_e event_state,
537                                 int progress,
538                                 package_manager_error_e error,
539                                 void *user_data)
540 {
541         LoggerD("install_request_cb ");
542         PackageInstallEventCallback *callback = (PackageInstallEventCallback *)user_data;
543         JSContextRef context = callback->getContext();;
544
545         switch (event_state) {
546         case PACAKGE_MANAGER_EVENT_STATE_COMPLETED: {
547                 if (callback->getOnComplete()) {
548                         Converter converter(context);
549                         callback->getOnComplete()->callSuccessCallback(converter.toJSValueRef(package));
550                 }
551
552                 LoggerD("destroy client handle");
553                 // this api is not supported from platform.
554                 //package_manager_request_destroy(callback->getHandle());
555                 package_manager_client_destroy(callback->getHandle());
556                 callback->setHandle(NULL);
557
558                 //clean-up callback object
559                 delete callback;
560                 
561                 break;
562         }
563         case PACAKGE_MANAGER_EVENT_STATE_FAILED: {
564                 JSValueRef jsError = NULL;
565                 if (error == PACKAGE_MANAGER_ERROR_NO_SUCH_PACKAGE) {
566                         jsError = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::NOT_FOUND_ERROR,"given package is not found");
567                 } else {
568                         jsError = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR,"platform exception");
569                 }
570
571                 if (callback->getOnError()) {
572                         callback->getOnError()->callSuccessCallback(jsError);
573                 }
574
575                 LoggerD("destroy client handle");
576                 // this api is not supported from platform.
577                 //package_manager_request_destroy(callback->getHandle());
578                 package_manager_client_destroy(callback->getHandle());
579                 callback->setHandle(NULL);
580
581                 //clean-up callback object
582                 delete callback;
583                 
584                 break;
585         }
586         case PACAKGE_MANAGER_EVENT_STATE_STARTED:
587         case PACAKGE_MANAGER_EVENT_STATE_PROCESSING: {
588                 if (callback->getOnProgress()) {
589                         Converter converter(context);
590                         JSValueRef args[2] = {converter.toJSValueRef(package), converter.toJSValueRef(progress)};
591                         callback->getOnProgress()->callSuccessCallback(2, args);
592                 }
593                 break;          
594         }
595         default:
596                 JSValueRef error = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR,"platform exception");
597                 if (callback->getOnError()) {
598                         callback->getOnError()->callSuccessCallback(error);
599                 }
600                 LoggerD("destroy client handle");
601                 // this api is not supported from platform.
602                 //package_manager_request_destroy(callback->getHandle());
603                 package_manager_client_destroy(callback->getHandle());
604                 callback->setHandle(NULL);
605
606                 //clean-up callback object
607                 delete callback;
608                 
609                 break;
610         }
611
612 }
613
614 void PackageManager::install(string pkgPath, PackageInstallEventCallback* callback)
615 {
616         LoggerD("install");
617         int ret = 0;
618         int id = 0;
619         package_manager_request_h request_h;
620         JSContextRef globalCtx = callback->getContext();
621         CallbackUserData* errCallback = callback->getOnError();
622
623         ret = package_manager_request_create(&request_h);
624         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
625                 if (errCallback) {
626                         JSValueRef error = 
627                                 JSTizenExceptionFactory::makeErrorObject(globalCtx, JSTizenException::UNKNOWN_ERROR, "Platform Error");
628                         errCallback->callSuccessCallback(error);
629                 }
630                 delete callback;
631                 return;
632         }
633
634         ret = package_manager_request_install(request_h, pkgPath.c_str(), &id);
635         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
636                 LoggerD("error : " << pkgPath);
637                 if (errCallback) {
638                         JSValueRef error = 
639                                 JSTizenExceptionFactory::makeErrorObject(globalCtx, JSTizenException::NOT_FOUND_ERROR, "Not proper file");
640                         errCallback->callSuccessCallback(error);
641                 }
642                 delete callback;
643                 return;
644         }
645
646         callback->setHandle(request_h);
647
648         ret = package_manager_request_set_event_cb(request_h, install_request_cb, callback);
649         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
650                 if (errCallback) {
651                         JSValueRef error = 
652                                 JSTizenExceptionFactory::makeErrorObject(globalCtx, JSTizenException::UNKNOWN_ERROR, "Platform Error");
653                         errCallback->callSuccessCallback(error);
654                 }
655                 delete callback;
656                 return;
657         }
658 }
659
660 void PackageManager::uninstall(string pkgPath, PackageInstallEventCallback* callback)
661 {
662         LoggerD("uninstall");
663         int ret = 0;
664         int id = 0;
665         package_manager_request_h request_h;
666         JSContextRef globalCtx = callback->getContext();
667         CallbackUserData* errCallback = callback->getOnError();
668
669         ret = package_manager_request_create(&request_h);
670         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
671                 if (errCallback) {
672                         JSValueRef error = 
673                                 JSTizenExceptionFactory::makeErrorObject(globalCtx, JSTizenException::UNKNOWN_ERROR, "Platform Error");
674                         errCallback->callSuccessCallback(error);
675                 }
676                 //clean-up callback object
677                 delete callback;
678                 return;
679         }
680
681         ret = package_manager_request_uninstall(request_h, pkgPath.c_str(), &id);
682         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
683                 LoggerD("error : " << pkgPath);
684                 if (errCallback) {
685                         JSValueRef error = 
686                                 JSTizenExceptionFactory::makeErrorObject(globalCtx, JSTizenException::NOT_FOUND_ERROR, "Not proper file");
687                         // TODO: how can I handle about uninstallable package???
688                         errCallback->callSuccessCallback(error);
689                 }
690                 //clean-up callback object
691                 delete callback;
692                 return;
693         }
694
695         callback->setHandle(request_h);
696
697         ret = package_manager_request_set_event_cb(request_h, install_request_cb, callback);
698         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
699                 if (errCallback) {
700                         JSValueRef error = 
701                                 JSTizenExceptionFactory::makeErrorObject(globalCtx, JSTizenException::UNKNOWN_ERROR, "Platform Error");
702                         errCallback->callSuccessCallback(error);
703                 }
704                 //clean-up callback object
705                 delete callback;
706                 return;
707         }
708 }
709
710
711 PackageInformation* PackageManager::getPackageInfo(string pkgId)
712 {
713         if (pkgId.empty() || !pkgId.compare("null")) {
714                 char *pkg_id = NULL;
715
716                 int ret = get_current_pkg_id(&pkg_id);
717                 if((ret != APP_MANAGER_ERROR_NONE) || (pkg_id == NULL)) {
718                         LoggerE("Can not get app id from current pid (" << ret << ")");
719                         throw NotFoundException("Can't find given package");
720                 }
721                 pkgId = pkg_id;
722                 free(pkg_id);
723         }
724
725         pkgmgrinfo_pkginfo_h handle;
726         int ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId.c_str(), &handle);
727         if (ret != PMINFO_R_OK) {
728                 throw NotFoundException("Can't find given package");
729         }
730
731         PackageInformation* pkgInfo = create_pkg_info(handle);
732         pkgmgrinfo_appinfo_destroy_appinfo(handle);
733
734         if (pkgInfo == NULL) {
735                 throw UnknownException("Can't get pkg info from given package");
736         }
737
738         return pkgInfo;
739 }
740
741
742 void PackageManager::getPackagesInfo(PackageInfoCallbackData *user_data)
743 {
744         LoggerD("entered");
745
746         // getting info of all package from other thread. the result callback will be called on main thread
747         ecore_thread_run(getThreadCB, NULL, NULL, user_data);
748 }
749
750
751 void PackageManager::setPackageInfoEventListener(PackageInfoEventCallback * eventCB)
752 {
753         LoggerD("enter");
754
755         if (m_manager_handle == NULL) {
756                 m_manager_handle = pkgmgr_client_new(PC_LISTENING);
757                 if (m_manager_handle == NULL) {
758                         throw UnknownException("Fail to create package manager handle");
759                 }
760         }
761
762         eventCB->setEventHandler(&m_manager_handle);
763
764         pkgmgr_client_listen_status(m_manager_handle, app_list_changed_cb_broker, eventCB);
765 }
766
767 void PackageManager::unsetPackageInfoEventListener()
768 {
769         LoggerD("enter");
770
771         if (m_manager_handle == NULL) {
772                 LoggerD("no package manager handle registered");
773                 return;
774         }
775
776         pkgmgr_client_free(m_manager_handle);
777         m_manager_handle = NULL;
778 }
779
780 PackageManager* PackageManager::getInstance(){
781         LoggerD("enter to getInstance()");
782     static PackageManager instance;
783     return &instance;
784 }
785
786 PackageManager::PackageManager()
787 {
788         LoggerD("Create PackageManager");
789 }
790
791 PackageManager::~PackageManager()
792 {
793         LoggerD("Destroy PackageManager");
794
795         if (m_manager_handle != NULL) {
796                 pkgmgr_client_free(m_manager_handle);
797                 m_manager_handle = NULL;
798         }
799
800 }
801
802
803 // candidate apis
804 #if 0
805 void PackageManager::move(string pkgPath, string target, PackageInstallEventCallback* callback)
806 {
807         LoggerD("entered : " << pkgPath);
808         int ret = 0;
809         package_manager_move_type_e type = PACAKGE_MANAGER_REQUEST_MOVE_TO_INTERNAL;
810
811         if (target.compare("INTERNAL") == 0) {
812                 type = PACAKGE_MANAGER_REQUEST_MOVE_TO_INTERNAL;
813         } else {
814                 type = PACAKGE_MANAGER_REQUEST_MOVE_TO_EXTERNAL;
815         }
816         // compare current storage and target storage
817         
818         package_manager_request_h request_h;
819         
820         ret = package_manager_request_create(&request_h);
821         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
822                 ThrowMsg(PlatformException, "Unknow exception is occured!!");
823         }
824
825         ret = package_manager_request_move(request_h, pkgPath.c_str(), type);
826         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
827                 ThrowMsg(PlatformException, "Unknow exception is occured!!");
828         }
829
830         callback->setHandle(request_h);
831
832         ret = package_manager_request_set_event_cb(request_h, install_request_cb, callback);
833         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
834                 ThrowMsg(PlatformException, "Unknow exception is occured!!");
835         }
836 }
837
838 bool PackageManager::isInstalled(string pkgId)
839 {
840         LoggerD("pkgId = " << pkgId);
841         package_info_h handle;
842         int ret = 0;
843         
844         ret = package_manager_get_package_info(pkgId.c_str(), &handle);
845         if (ret == PACKAGE_MANAGER_ERROR_NO_SUCH_PACKAGE) {
846                 LoggerE("No patched package: " << pkgId);
847                 return false;
848         } else if (ret == PACKAGE_MANAGER_ERROR_NONE) {
849                 // TODO: Should I exception handling while destory handle? what should I do for that time?
850                 package_info_destroy(handle);
851                 return true;
852         } else {
853                 ThrowMsg(PlatformException, "Unknow exception is occured!!");
854         }
855 }
856
857 string PackageManager::getPackageIdFromAppId(string appId)
858 {
859         LoggerD("appId = " << appId);
860         char *pkg_id = NULL;
861         string pkgId;
862         int ret = 0;
863         
864         ret = package_manager_get_package_id_by_app_id(appId.c_str(), &pkg_id);
865         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
866                 LoggerE("Error on get pkgId from appId : " << appId);
867                 ThrowMsg(NotFoundException, "Not found pkg");
868         }
869
870         pkgId = pkg_id;
871         if (pkg_id)
872                 free(pkg_id);
873
874         return pkgId;
875         
876 }
877 #endif
878
879
880 }
881 }