2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <JSTizenExceptionFactory.h>
21 #include <JSTizenException.h>
22 #include <GlobalContextManager.h>
23 #include <PlatformException.h>
25 // to get package name by appid
26 #include <app_manager.h>
28 // To get cert information from package
29 #include <package_manager.h>
30 #include <package_info.h>
32 // To get app size and installed time
33 #include <pkgmgr-info.h>
35 // To use ecore_thread
38 #include "PackageManager.h"
39 #include "PackageInformation.h"
40 #include "JSPackageInformation.h"
43 using namespace WrtDeviceApis::Commons;
44 using namespace WrtDeviceApis::CommonsJavaScript;
45 using namespace DeviceAPI::Common;
51 int package_manager_client_destroy(package_manager_request_h request);
58 PackageInfoCallbackData::PackageInfoCallbackData(JSContextRef globalCtx):
59 CallbackUserData(globalCtx)
61 m_exceptionCode = WrtDeviceApis::Commons::ExceptionCodes::None;
64 PackageInfoCallbackData::~PackageInfoCallbackData()
66 // TODO: Should I clear pkgInfos?
69 vector<PackageInformation> PackageInfoCallbackData::getPackageInfoList()
75 void PackageInfoCallbackData::addPackageInfo(PackageInformation pkgInfo)
77 m_pkgInfos.push_back(pkgInfo);
81 void PackageInfoCallbackData::setExceptionCode(ExceptionCodes::Enumeration exceptionCode)
83 m_exceptionCode = exceptionCode;
86 ExceptionCodes::Enumeration PackageInfoCallbackData::getExceptionCode() const
88 return m_exceptionCode;
91 PackageInfoEventCallback::PackageInfoEventCallback(CallbackUserData* oninstalled, CallbackUserData* onupdated, CallbackUserData* onuninstalled)
93 m_oninstalled = oninstalled;
94 m_onupdated = onupdated;
95 m_onuninstalled = onuninstalled;
99 PackageInfoEventCallback::~PackageInfoEventCallback()
102 delete m_oninstalled;
108 delete m_onuninstalled;
111 CallbackUserData* PackageInfoEventCallback::getOnInstalled()
113 return m_oninstalled;
116 CallbackUserData* PackageInfoEventCallback::getOnUpdated()
121 CallbackUserData* PackageInfoEventCallback::getOnUninstalled()
123 return m_onuninstalled;
126 pkgmgr_client** PackageInfoEventCallback::getEventHandler()
131 void PackageInfoEventCallback::setEventHandler(pkgmgr_client **handler)
133 m_handle_p = handler;
136 PackageInstallEventCallback::PackageInstallEventCallback(JSContextRef globalCtx, CallbackUserData* onprogress, CallbackUserData* oncomplete, CallbackUserData* onerror)
138 m_context = globalCtx;
139 m_onprogress = onprogress;
140 m_oncomplete = oncomplete;
143 m_request_handle = NULL;
146 PackageInstallEventCallback::~PackageInstallEventCallback()
148 if (m_request_handle != NULL) {
149 //package_manager_request_destroy(m_request_handle);
150 package_manager_client_destroy(m_request_handle);
163 CallbackUserData* PackageInstallEventCallback::getOnProgress()
168 CallbackUserData* PackageInstallEventCallback::getOnComplete()
173 CallbackUserData* PackageInstallEventCallback::getOnError()
178 JSContextRef PackageInstallEventCallback::getContext()
183 void PackageInstallEventCallback::setHandle(package_manager_request_h handle)
185 m_request_handle = handle;
188 package_manager_request_h PackageInstallEventCallback::getHandle()
190 return m_request_handle;
193 static int get_current_pkg_id(char** pkg_id)
197 string appId = PackageManager::getInstance()->getCurrentAppId();
199 int ret = app_manager_get_app_info(appId.c_str(), &handle);
200 if (ret != APP_MANAGER_ERROR_NONE) {
201 LoggerE("Fail to get appinfo");
205 ret = app_info_get_package(handle, pkg_id);
206 if ((ret != APP_MANAGER_ERROR_NONE) || (*pkg_id == NULL)) {
207 LoggerE("Fail to get pkg_id");
211 ret = app_info_destroy(handle);
212 if (ret != APP_MANAGER_ERROR_NONE) {
213 LoggerE("Fail to get destory appinfo");
220 static bool app_callback(package_info_app_component_type_e comp_type, const char *app_id, void *user_data)
222 PackageInformation* pkgInfo = (PackageInformation*)user_data;
223 pkgInfo->m_appIds.push_back(app_id);
227 static PackageInformation* create_pkg_info(pkgmgrinfo_pkginfo_h handle)
229 PackageInformation *pkgInfo = new PackageInformation();
233 char* iconPath = NULL;
234 char* version = NULL;
237 int lastModified = 0;
240 char* description = NULL;
241 vector<string> appIds;
244 ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &id);
245 if ((ret != PMINFO_R_OK) || (id == NULL)) {
246 LoggerE("Fail to get id. return NULL.");
253 ret = pkgmgrinfo_pkginfo_get_label(handle, &name);
254 if ((ret != PMINFO_R_OK) || (name == NULL)) {
255 LoggerE("Fail to get labe");
257 pkgInfo->m_name = name;
260 ret = pkgmgrinfo_pkginfo_get_icon(handle, &iconPath);
261 if ((ret != PMINFO_R_OK) || (iconPath == NULL)) {
262 LoggerE("Fail to get iconPath");
264 pkgInfo->m_iconPath = iconPath;
267 ret = pkgmgrinfo_pkginfo_get_version(handle, &version);
268 if ((ret != PMINFO_R_OK) || (version == NULL)) {
269 LoggerE("Fail to get version");
271 pkgInfo->m_version = version;
274 ret = pkgmgrinfo_pkginfo_get_total_size(handle, &totalSize);
275 if (ret != PMINFO_R_OK) {
276 LoggerE("Fail to get totalSize");
278 pkgInfo->m_totalSize = totalSize;
281 ret = pkgmgrinfo_pkginfo_get_data_size(handle, &dataSize);
282 if (ret != PMINFO_R_OK) {
283 LoggerE("Fail to get dataSize");
285 pkgInfo->m_dataSize = dataSize;
288 ret = pkgmgrinfo_pkginfo_get_installed_time(handle, &lastModified);
289 if (ret != PMINFO_R_OK) {
290 LoggerE("Fail to get lastModified");
292 pkgInfo->m_lastModified = lastModified;
295 ret = pkgmgrinfo_pkginfo_get_type(handle, &type);
296 if ((ret != PMINFO_R_OK) || (type == NULL)) {
297 LoggerE("Fail to get type");
299 pkgInfo->m_type = type;
302 ret = pkgmgrinfo_pkginfo_get_author_name(handle, &author);
303 if ((ret != PMINFO_R_OK) || (author == NULL)) {
304 LoggerE("Fail to get author");
306 pkgInfo->m_author = author;
309 ret = pkgmgrinfo_pkginfo_get_description(handle, &description);
310 if ((ret != PMINFO_R_OK) || (description == NULL)) {
311 LoggerE("Fail to get description");
313 pkgInfo->m_description = description;
316 package_info_h package_info;
318 ret = package_manager_get_package_info(id, &package_info);
319 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
320 LoggerE("Cannot create package info");
325 ret = package_info_foreach_app_from_package(package_info, PACKAGE_INFO_ALLAPP, app_callback, (void*)pkgInfo);
326 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
327 LoggerE("failed while getting appids");
330 ret = package_info_destroy(package_info);
331 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
332 LoggerE("Cannot destroy package info");
335 // REMARK: do not destroy handle. because handle is comes from outside!!
339 static gboolean getCompleteCB(void *data)
341 PackageInfoCallbackData *callback = (PackageInfoCallbackData *)data;
342 JSContextRef context = callback->getContext();
344 if (callback->getExceptionCode() == WrtDeviceApis::Commons::ExceptionCodes::None) {
345 vector<PackageInformation> pkgInfoList = callback->getPackageInfoList();
347 JSObjectRef jsResult = JSCreateArrayObject(context, 0, NULL);
348 if (jsResult == NULL) {
349 JSValueRef error = JSTizenExceptionFactory::makeErrorObject(callback->getContext(), JSTizenException::UNKNOWN_ERROR, "platform exception");
350 callback->callErrorCallback(error);
354 for (size_t i = 0; i < pkgInfoList.size(); ++i) {
355 JSValueRef tmpVal = JSPackageInformation::createJSObject(context, &pkgInfoList[i]);
356 if (!JSSetArrayElement(context, jsResult, i, tmpVal)) {
357 JSValueRef error = JSTizenExceptionFactory::makeErrorObject(callback->getContext(), JSTizenException::UNKNOWN_ERROR, "platform exception");
358 callback->callErrorCallback(error);
363 callback->callSuccessCallback(jsResult);
365 JSValueRef error = JSTizenExceptionFactory::makeErrorObject(callback->getContext(), JSTizenException::UNKNOWN_ERROR, "platform exception");
366 callback->callErrorCallback(error);
374 static int get_package_list_cb(pkgmgrinfo_pkginfo_h handle, void *user_data)
376 PackageInfoCallbackData *callback = (PackageInfoCallbackData *)user_data;
377 PackageInformation* pkgInfo = create_pkg_info(handle);
378 if (pkgInfo != NULL) {
379 callback->addPackageInfo(*pkgInfo);
382 LoggerE("Fail to get pkgInfo");
387 static void getThreadCB(void *data, Ecore_Thread *thread)
389 PackageInfoCallbackData *callback = (PackageInfoCallbackData *)data;
391 int ret = pkgmgrinfo_pkginfo_get_list(get_package_list_cb, data);
392 if (ret != PMINFO_R_OK) {
393 LoggerE("Fail to get package info");
394 callback->setExceptionCode(WrtDeviceApis::Commons::ExceptionCodes::PlatformException);
397 // the operation of ecore_thread_run() is not normal. (the finish callback is not called from main thread.)
398 // so, add complete callback to gmainloop explicitly.
399 g_idle_add(getCompleteCB, data);
403 static void package_event_cb(app_manger_event_type_e event_type, const char *package, void *user_data)
405 PackageInfoEventCallback *eventCB = (PackageInfoEventCallback *)user_data;
408 case APP_MANAGER_EVENT_INSTALLED: {
409 pkgmgrinfo_pkginfo_h handle;
410 int ret = pkgmgrinfo_pkginfo_get_pkginfo(package, &handle);
411 if (ret != PMINFO_R_OK) {
412 LoggerE("fail to find pkg info with given pkg");
413 // Do not throw exception. No one can handle exception because this code is called from async callback.
414 //throw NotFoundException("Can't find given package");
418 PackageInformation* pkgInfo = create_pkg_info(handle);
419 pkgmgrinfo_appinfo_destroy_appinfo(handle);
421 if (pkgInfo == NULL) {
422 LoggerE("Fail to get pkg info. skip callback call");
424 CallbackUserData *callback = eventCB->getOnInstalled();
426 callback->callSuccessCallback(JSPackageInformation::createJSObject(callback->getContext(), pkgInfo));
431 case APP_MANAGER_EVENT_UNINSTALLED: {
432 CallbackUserData *callback = eventCB->getOnUninstalled();
434 Converter converter(callback->getContext());
435 callback->callSuccessCallback(converter.toJSValueRef(package));
439 case APP_MANAGER_EVENT_UPDATED: {
440 pkgmgrinfo_pkginfo_h handle;
441 int ret = pkgmgrinfo_pkginfo_get_pkginfo(package, &handle);
442 if (ret != PMINFO_R_OK) {
443 // Do not throw exception. No one can handle exception because this code is called from async callback.
444 //throw NotFoundException("Can't find given package");
448 PackageInformation* pkgInfo = create_pkg_info(handle);
449 pkgmgrinfo_appinfo_destroy_appinfo(handle);
451 if (pkgInfo == NULL) {
452 LoggerE("Fail to get pkg info. skip callback call");
454 CallbackUserData *callback = eventCB->getOnUpdated();
456 callback->callSuccessCallback(JSPackageInformation::createJSObject(callback->getContext(), pkgInfo));
462 LoggerE("Fail!! Unknown event type is entered : " << event_type);
469 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)
471 static app_manger_event_type_e event_type;
473 if (!strcasecmp(key, "start"))
476 if (!strcasecmp(val, "install"))
478 event_type = APP_MANAGER_EVENT_INSTALLED;
480 else if (!strcasecmp(val, "uninstall"))
482 event_type = APP_MANAGER_EVENT_UNINSTALLED;
484 else if (!strcasecmp(val, "update"))
486 event_type = APP_MANAGER_EVENT_UPDATED;
489 else if (!strcasecmp(key, "end") && !strcasecmp(val, "ok"))
494 package_event_cb(event_type, package, data);
496 // Check whether handler is freed in the callback function or not.
497 // if freed, return error code to avoid iteration of callback function. (core platform side)
498 PackageInfoEventCallback * callback = (PackageInfoEventCallback *)data;
499 pkgmgr_client ** handler_p = callback->getEventHandler();
500 if (*handler_p == NULL) {
501 LoggerE("handler is NULL");
504 LoggerE("handler is not NULL");
512 void install_request_cb(int id, const char *type, const char *package,
513 package_manager_event_type_e event_type,
514 package_manager_event_state_e event_state,
516 package_manager_error_e error,
519 PackageInstallEventCallback *callback = (PackageInstallEventCallback *)user_data;
520 JSContextRef context = callback->getContext();;
522 switch (event_state) {
523 case PACAKGE_MANAGER_EVENT_STATE_COMPLETED: {
524 if (callback->getOnComplete()) {
525 Converter converter(context);
526 callback->getOnComplete()->callSuccessCallback(converter.toJSValueRef(package));
529 LoggerD("destroy client handle");
530 // this api is not supported from platform.
531 //package_manager_request_destroy(callback->getHandle());
532 package_manager_client_destroy(callback->getHandle());
533 callback->setHandle(NULL);
535 //clean-up callback object
540 case PACAKGE_MANAGER_EVENT_STATE_FAILED: {
541 JSValueRef jsError = NULL;
542 if (error == PACKAGE_MANAGER_ERROR_NO_SUCH_PACKAGE) {
543 jsError = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::NOT_FOUND_ERROR,"given package is not found");
545 jsError = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR,"platform exception");
548 if (callback->getOnError()) {
549 callback->getOnError()->callSuccessCallback(jsError);
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);
558 //clean-up callback object
563 case PACAKGE_MANAGER_EVENT_STATE_STARTED:
564 case PACAKGE_MANAGER_EVENT_STATE_PROCESSING: {
565 if (callback->getOnProgress()) {
566 Converter converter(context);
567 JSValueRef args[2] = {converter.toJSValueRef(package), converter.toJSValueRef(progress)};
568 callback->getOnProgress()->callSuccessCallback(2, args);
573 JSValueRef error = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR,"platform exception");
574 if (callback->getOnError()) {
575 callback->getOnError()->callSuccessCallback(error);
577 LoggerD("destroy client handle");
578 // this api is not supported from platform.
579 //package_manager_request_destroy(callback->getHandle());
580 package_manager_client_destroy(callback->getHandle());
581 callback->setHandle(NULL);
583 //clean-up callback object
591 void PackageManager::install(string pkgPath, PackageInstallEventCallback* callback)
595 package_manager_request_h request_h;
596 JSContextRef globalCtx = callback->getContext();
597 CallbackUserData* errCallback = callback->getOnError();
599 ret = package_manager_request_create(&request_h);
600 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
603 JSTizenExceptionFactory::makeErrorObject(globalCtx, JSTizenException::UNKNOWN_ERROR, "Platform Error");
604 errCallback->callSuccessCallback(error);
610 ret = package_manager_request_install(request_h, pkgPath.c_str(), &id);
611 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
614 JSTizenExceptionFactory::makeErrorObject(globalCtx, JSTizenException::NOT_FOUND_ERROR, "Not proper file");
615 errCallback->callSuccessCallback(error);
621 callback->setHandle(request_h);
623 ret = package_manager_request_set_event_cb(request_h, install_request_cb, callback);
624 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
627 JSTizenExceptionFactory::makeErrorObject(globalCtx, JSTizenException::UNKNOWN_ERROR, "Platform Error");
628 errCallback->callSuccessCallback(error);
635 void PackageManager::uninstall(string pkgPath, PackageInstallEventCallback* callback)
639 package_manager_request_h request_h;
640 JSContextRef globalCtx = callback->getContext();
641 CallbackUserData* errCallback = callback->getOnError();
643 ret = package_manager_request_create(&request_h);
644 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
647 JSTizenExceptionFactory::makeErrorObject(globalCtx, JSTizenException::UNKNOWN_ERROR, "Platform Error");
648 errCallback->callSuccessCallback(error);
650 //clean-up callback object
655 ret = package_manager_request_uninstall(request_h, pkgPath.c_str(), &id);
656 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
659 JSTizenExceptionFactory::makeErrorObject(globalCtx, JSTizenException::NOT_FOUND_ERROR, "Not proper file");
660 // TODO: how can I handle about uninstallable package???
661 errCallback->callSuccessCallback(error);
663 //clean-up callback object
668 callback->setHandle(request_h);
670 ret = package_manager_request_set_event_cb(request_h, install_request_cb, callback);
671 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
674 JSTizenExceptionFactory::makeErrorObject(globalCtx, JSTizenException::UNKNOWN_ERROR, "Platform Error");
675 errCallback->callSuccessCallback(error);
677 //clean-up callback object
684 PackageInformation* PackageManager::getPackageInfo(string pkgId)
686 if (pkgId.empty() || !pkgId.compare("null")) {
689 int ret = get_current_pkg_id(&pkg_id);
690 if((ret != APP_MANAGER_ERROR_NONE) || (pkg_id == NULL)) {
691 LoggerE("Can not get app id from current pid");
692 throw NotFoundException("Can't find given package");
698 pkgmgrinfo_pkginfo_h handle;
699 int ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId.c_str(), &handle);
700 if (ret != PMINFO_R_OK) {
701 throw NotFoundException("Can't find given package");
704 PackageInformation* pkgInfo = create_pkg_info(handle);
705 pkgmgrinfo_appinfo_destroy_appinfo(handle);
707 if (pkgInfo == NULL) {
708 throw UnknownException("Can't get pkg info from given package");
715 void PackageManager::getPackagesInfo(PackageInfoCallbackData *user_data)
717 // getting info of all package from other thread. the result callback will be called on main thread
718 ecore_thread_run(getThreadCB, NULL, NULL, user_data);
722 void PackageManager::setPackageInfoEventListener(PackageInfoEventCallback * eventCB)
724 if (m_manager_handle == NULL) {
725 m_manager_handle = pkgmgr_client_new(PC_LISTENING);
726 if (m_manager_handle == NULL) {
727 throw UnknownException("Fail to create package manager handle");
731 eventCB->setEventHandler(&m_manager_handle);
733 pkgmgr_client_listen_status(m_manager_handle, app_list_changed_cb_broker, eventCB);
736 void PackageManager::unsetPackageInfoEventListener()
738 if (m_manager_handle == NULL) {
739 LoggerE("no package manager handle registered");
743 pkgmgr_client_free(m_manager_handle);
744 m_manager_handle = NULL;
747 PackageManager* PackageManager::getInstance()
749 static PackageManager instance;
753 void PackageManager::setCurrentAppId(string appId)
755 m_curr_app_id = appId;
758 string PackageManager::getCurrentAppId() const
760 return m_curr_app_id;
763 PackageManager::PackageManager()
767 PackageManager::~PackageManager()
769 if (m_manager_handle != NULL) {
770 pkgmgr_client_free(m_manager_handle);
771 m_manager_handle = NULL;
779 void PackageManager::move(string pkgPath, string target, PackageInstallEventCallback* callback)
782 package_manager_move_type_e type = PACAKGE_MANAGER_REQUEST_MOVE_TO_INTERNAL;
784 if (target.compare("INTERNAL") == 0) {
785 type = PACAKGE_MANAGER_REQUEST_MOVE_TO_INTERNAL;
787 type = PACAKGE_MANAGER_REQUEST_MOVE_TO_EXTERNAL;
789 // compare current storage and target storage
791 package_manager_request_h request_h;
793 ret = package_manager_request_create(&request_h);
794 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
795 ThrowMsg(PlatformException, "Unknow exception is occured!!");
798 ret = package_manager_request_move(request_h, pkgPath.c_str(), type);
799 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
800 ThrowMsg(PlatformException, "Unknow exception is occured!!");
803 callback->setHandle(request_h);
805 ret = package_manager_request_set_event_cb(request_h, install_request_cb, callback);
806 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
807 ThrowMsg(PlatformException, "Unknow exception is occured!!");
811 bool PackageManager::isInstalled(string pkgId)
813 package_info_h handle;
816 ret = package_manager_get_package_info(pkgId.c_str(), &handle);
817 if (ret == PACKAGE_MANAGER_ERROR_NO_SUCH_PACKAGE) {
819 } else if (ret == PACKAGE_MANAGER_ERROR_NONE) {
820 // TODO: Should I exception handling while destory handle? what should I do for that time?
821 package_info_destroy(handle);
824 ThrowMsg(PlatformException, "Unknow exception is occured!!");
828 string PackageManager::getPackageIdFromAppId(string appId)
834 ret = package_manager_get_package_id_by_app_id(appId.c_str(), &pkg_id);
835 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
836 ThrowMsg(NotFoundException, "Not found pkg");