2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * @file backendlib.cpp
20 * @author Soyoung Kim (sy037.kim@samsung.com)
22 * @brief This is implementation file for providing widget information
25 #include "package-manager-plugin.h"
26 #include <package-manager.h>
29 #include <dpl/wrt-dao-ro/global_config.h>
30 #include <vcore/VCore.h>
31 #include <dpl/wrt-dao-ro/WrtDatabase.h>
32 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
33 #include <dpl/wrt-dao-ro/feature_dao_read_only.h>
34 #include <dpl/wrt-dao-ro/widget_config.h>
36 #include <dpl/db/sql_connection.h>
37 #include <dpl/log/log.h>
38 #include <dpl/foreach.h>
39 #include <dpl/utils/folder_size.h>
40 #include <dpl/wrt-dao-ro/wrt_db_types.h>
42 #include <dpl/abstract_waitable_input_adapter.h>
43 #include <dpl/abstract_waitable_output_adapter.h>
44 #include <dpl/zip_input.h>
45 #include <dpl/binary_queue.h>
46 #include <dpl/file_input.h>
47 #include <dpl/wrt-dao-ro/config_parser_data.h>
48 #include <dpl/localization/LanguageTagsProvider.h>
49 #include "root_parser.h"
50 #include "widget_parser.h"
51 #include "parser_runner.h"
53 using namespace WrtDB;
59 #define GET_DIRECTORY_SIZE_KB(x) (x) / 1024
66 static void pkg_native_plugin_on_unload();
67 static int pkg_plugin_app_is_installed(const char *pkg_name);
68 static int pkg_plugin_get_installed_apps_list(const char *category,
70 package_manager_pkg_info_t **list,
72 static int pkg_plugin_get_app_detail_info(
74 package_manager_pkg_detail_info_t *
76 static int pkg_plugin_get_app_detail_info_from_package(
78 package_manager_pkg_detail_info_t
81 pkgmgr_info *pkgmgr_client_check_pkginfo_from_file(const char *pkg_path);
83 static void pkg_native_plugin_on_unload()
85 LogDebug("pkg_native_plugin_unload() is called");
88 static int pkg_plugin_app_is_installed(const char *pkg_name)
90 const char* REG_PKGID_PATTERN = "^[a-zA-Z0-9]{10}$";
91 LogDebug("pkg_plugin_app_is_installed() is called");
93 WrtDB::WrtDatabase::attachToThreadRO();
96 if (regcomp(®, REG_PKGID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
97 LogDebug("Regcomp failed");
100 WrtDB::TizenAppId appid;
102 if (!(regexec(®, pkg_name,
103 static_cast<size_t>(0), NULL, 0) == 0))
105 LogError("Invalid argument : " << pkg_name);
110 WrtDB::TizenPkgId pkgid(DPL::FromUTF8String(pkg_name));
111 appid = WidgetDAOReadOnly::getTzAppId(pkgid);
112 LogDebug("appid : " << appid);
113 } Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) {
114 WrtDB::WrtDatabase::detachFromThread();
117 WrtDB::WrtDatabase::detachFromThread();
121 static int pkg_plugin_get_installed_apps_list(const char * /*category*/,
122 const char * /*option*/,
123 package_manager_pkg_info_t **list,
126 LogDebug("pkg_plugin_get_installed_apps_list() is called");
128 package_manager_pkg_info_t *pkg_list = NULL;
129 package_manager_pkg_info_t *pkg_last = NULL;
131 WrtDB::WrtDatabase::attachToThreadRO();
132 TizenAppIdList tizenAppidList = WidgetDAOReadOnly::getTizenAppidList();
135 FOREACH(iterator, tizenAppidList) {
136 package_manager_pkg_info_t *pkg_info =
137 static_cast<package_manager_pkg_info_t*>
138 (malloc(sizeof(package_manager_pkg_info_t)));
140 if (NULL == pkg_list) {
144 pkg_last->next = pkg_info;
147 TizenAppId tzAppid = *iterator;
148 WidgetDAOReadOnly widget(tzAppid);
149 strncpy(pkg_info->pkg_type, "wgt", PKG_TYPE_STRING_LEN_MAX);
150 snprintf(pkg_info->pkg_name, PKG_NAME_STRING_LEN_MAX, "%s",
151 DPL::ToUTF8String(tzAppid).c_str());
153 DPL::Optional<DPL::String> version = widget.getVersion();
154 if (!version.IsNull()) {
155 strncpy(pkg_info->version,
156 DPL::ToUTF8String(*version).c_str(),
157 PKG_VERSION_STRING_LEN_MAX - 1);
164 WrtDB::WrtDatabase::detachFromThread();
169 static int pkg_plugin_get_app_detail_info(
170 const char *pkg_name,
171 package_manager_pkg_detail_info_t *
174 LogDebug("pkg_plugin_get_app_detail_info() is called");
176 WrtDB::WrtDatabase::attachToThreadRO();
178 WrtDB::TizenAppId appid;
180 WrtDB::TizenPkgId pkgid(DPL::FromUTF8String(pkg_name));
181 appid = WidgetDAOReadOnly::getTzAppId(pkgid);
182 LogDebug("appid : " << appid);
183 } Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) {
184 WrtDB::WrtDatabase::detachFromThread();
188 WidgetDAOReadOnly widget(appid);
190 DPL::Optional<DPL::String> version = widget.getVersion();
191 DPL::Optional<DPL::String> id = widget.getGUID();
192 DPL::Optional<DPL::String> locale = widget.getDefaultlocale();
194 if (!version.IsNull()) {
195 strncpy(pkg_detail_info->version,
196 DPL::ToUTF8String(*version).c_str(),
197 PKG_VERSION_STRING_LEN_MAX - 1);
199 snprintf(pkg_detail_info->pkgid, PKG_NAME_STRING_LEN_MAX, "%s",
201 snprintf(pkg_detail_info->optional_id, PKG_NAME_STRING_LEN_MAX, "%s",
202 DPL::ToUTF8String(appid).c_str());
203 WidgetLocalizedInfo localizedInfo;
205 if (locale.IsNull()) {
206 LogDebug("locale is NULL");
207 DPL::String languageTag(L"");
208 localizedInfo = widget.getLocalizedInfo(languageTag);
210 localizedInfo = widget.getLocalizedInfo(*locale);
212 DPL::Optional<DPL::String> desc(localizedInfo.description);
214 if (!desc.IsNull()) {
215 strncpy(pkg_detail_info->pkg_description,
216 DPL::ToUTF8String(*desc).c_str(),
217 PKG_VALUE_STRING_LEN_MAX - 1);
219 strncpy(pkg_detail_info->pkg_type, "wgt", PKG_TYPE_STRING_LEN_MAX);
220 strncpy(pkg_detail_info->pkg_name, pkg_name, PKG_NAME_STRING_LEN_MAX - 1);
222 std::string min_version = DPL::ToUTF8String((*widget.getMinimumWacVersion()));
224 strncpy(pkg_detail_info->min_platform_version, min_version.c_str(),
225 PKG_VERSION_STRING_LEN_MAX - 1);
227 /* set installed time */
228 pkg_detail_info->installed_time = widget.getInstallTime();
230 /* set Widget size */
231 DPL::String pkgName = DPL::FromUTF8String(pkg_name);
232 std::string installPath = WidgetConfig::GetWidgetBasePath(pkgName);
233 std::string persistentPath =
234 WidgetConfig::GetWidgetPersistentStoragePath(pkgName);
235 std::string tempPath =
236 WidgetConfig::GetWidgetTemporaryStoragePath(pkgName);
239 persistentPath += "/";
241 size_t installedSize = Utils::getFolderSize(installPath);
242 size_t persistentSize = Utils::getFolderSize(persistentPath);
243 size_t appSize = installedSize - persistentSize;
244 size_t dataSize = persistentSize + Utils::getFolderSize(tempPath);
246 pkg_detail_info->installed_size = GET_DIRECTORY_SIZE_KB(installedSize);
247 pkg_detail_info->app_size = GET_DIRECTORY_SIZE_KB(appSize);
248 pkg_detail_info->data_size = GET_DIRECTORY_SIZE_KB(dataSize);
250 WrtDB::WrtDatabase::detachFromThread();
254 int getConfigParserData(const std::string &widgetPath, ConfigParserData& configInfo)
256 const char* CONFIG_XML = "config.xml";
257 const char* WITH_OSP_XML = "res/wgt/config.xml";
262 std::unique_ptr<DPL::ZipInput> zipFile(
263 new DPL::ZipInput(widgetPath));
265 std::unique_ptr<DPL::ZipInput::File> configFile;
267 // Open config.xml file
269 configFile.reset(zipFile->OpenFile(CONFIG_XML));
271 Catch(DPL::ZipInput::Exception::OpenFileFailed)
273 configFile.reset(zipFile->OpenFile(WITH_OSP_XML));
277 DPL::BinaryQueue buffer;
278 DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get());
279 DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
280 DPL::Copy(&inputAdapter, &outputAdapter);
281 parser.Parse(&buffer,
283 new RootParser<WidgetParser>(configInfo,
288 Catch(DPL::ZipInput::Exception::OpenFailed)
290 LogError("Failed to open widget package");
293 Catch(DPL::ZipInput::Exception::OpenFileFailed)
295 LogError("Failed to open config.xml file");
298 Catch(DPL::CopyFailed)
300 LogError("Failed to extract config.xml file");
303 Catch(DPL::FileInput::Exception::OpenFailed)
305 LogError("Failed to open config.xml file");
308 Catch(ElementParser::Exception::ParseError)
310 LogError("Failed to parse config.xml file");
313 Catch(DPL::ZipInput::Exception::SeekFileFailed)
315 LogError("Failed to seek widget archive - corrupted package?");
322 char* getIconInfo(const std::string widgetPath,
323 const std::string icon_name, int &icon_size)
326 std::unique_ptr<DPL::ZipInput> zipFile(
327 new DPL::ZipInput(widgetPath));
329 std::unique_ptr<DPL::ZipInput::File> iconFile;
332 iconFile.reset(zipFile->OpenFile(icon_name));
334 Catch(DPL::ZipInput::Exception::OpenFileFailed)
336 LogDebug("This web app is hybrid web app");
337 std::string hybrid_icon = "res/wgt/" + icon_name;
338 iconFile.reset(zipFile->OpenFile(hybrid_icon));
341 DPL::BinaryQueue buffer;
342 DPL::AbstractWaitableInputAdapter inputAdapter(iconFile.get());
343 DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
344 DPL::Copy(&inputAdapter, &outputAdapter);
345 icon_size = buffer.Size();
346 char *getBuffer = (char*) calloc(1, (sizeof(char) * icon_size) + 1);
347 buffer.Flatten(getBuffer, buffer.Size());
350 Catch(DPL::ZipInput::Exception::OpenFailed)
352 LogError("Failed to open widget package");
355 Catch(DPL::ZipInput::Exception::OpenFileFailed)
357 LogError("Failed to open icon file");
362 int getWidgetDetailInfoFromPackage(const char* pkgPath,
363 package_manager_pkg_detail_info_t* pkg_detail_info)
365 const std::string widget_path(pkgPath);
366 ConfigParserData configInfo;
368 if (FALSE == getConfigParserData(widget_path, configInfo)) {
372 strncpy(pkg_detail_info->pkg_type, "wgt", PKG_TYPE_STRING_LEN_MAX);
373 if (!configInfo.tizenPkgId.IsNull()) {
374 strncpy(pkg_detail_info->pkgid,
375 DPL::ToUTF8String(*configInfo.tizenPkgId).c_str(), PKG_TYPE_STRING_LEN_MAX - 1);
377 if (!configInfo.tizenAppId.IsNull()) {
378 strncpy(pkg_detail_info->pkg_name,
379 DPL::ToUTF8String(*configInfo.tizenAppId).c_str(),
380 PKG_NAME_STRING_LEN_MAX - 1);
382 if (!configInfo.version.IsNull()) {
383 strncpy(pkg_detail_info->version,
384 DPL::ToUTF8String(*configInfo.version).c_str(),
385 PKG_VERSION_STRING_LEN_MAX - 1);
388 DPL::Optional<DPL::String> name;
389 DPL::Optional<DPL::String> desc;
391 LanguageTags tags = LanguageTagsProviderSingleton::Instance().getLanguageTags();
393 auto toLowerCase = [](const DPL::String & r)
396 std::transform(r.begin(), r.end(), std::inserter(result, result.begin()), ::tolower);
400 if (!!configInfo.defaultlocale)
402 Locale & dl = *configInfo.defaultlocale;
403 configInfo.defaultlocale = toLowerCase(dl);
409 *tag = toLowerCase(*tag);
410 FOREACH(localizedData, configInfo.localizedDataSet)
412 Locale i = localizedData->first;
415 if (!!configInfo.defaultlocale && *configInfo.defaultlocale == i)
417 name = localizedData->second.name;
418 desc = localizedData->second.description;
422 name = localizedData->second.name;
423 desc = localizedData->second.description;
431 if( !name.IsNull()) {
432 strncpy(pkg_detail_info->label, DPL::ToUTF8String(*name).c_str(),
433 PKG_LABEL_STRING_LEN_MAX - 1);
436 if (!desc.IsNull()) {
437 strncpy(pkg_detail_info->pkg_description,
438 DPL::ToUTF8String(*desc).c_str(),
439 PKG_VALUE_STRING_LEN_MAX - 1);
442 if (!configInfo.tizenMinVersionRequired.IsNull()) {
443 strncpy(pkg_detail_info->min_platform_version,
444 DPL::ToUTF8String(*configInfo.tizenMinVersionRequired).c_str(),
445 PKG_VERSION_STRING_LEN_MAX - 1);
448 if (!configInfo.authorName.IsNull()) {
449 strncpy(pkg_detail_info->author,
450 DPL::ToUTF8String(*configInfo.authorName).c_str(),
451 PKG_VALUE_STRING_LEN_MAX - 1);
455 pkg_detail_info->privilege_list = NULL;
456 FOREACH(it, configInfo.featuresList) {
457 std::string featureInfo = DPL::ToUTF8String(it->name);
458 LogDebug("privilege : " << featureInfo);
459 int length = featureInfo.size();
460 char *privilege = (char*) calloc(1, (sizeof(char) * (length + 1)));
461 snprintf(privilege, length + 1, "%s", featureInfo.c_str());
462 pkg_detail_info->privilege_list =
463 g_list_append(pkg_detail_info->privilege_list, privilege);
466 std::string icon_name;
467 FOREACH(i, configInfo.iconsList) {
468 LogDebug("icon name: " << i->src);
469 icon_name = DPL::ToUTF8String(i->src);
473 pkg_detail_info->icon_buf = getIconInfo(widget_path, icon_name,
474 pkg_detail_info->icon_size);
475 LogDebug("icon size : " << pkg_detail_info->icon_size);
480 static int pkg_plugin_get_app_detail_info_from_package(
481 const char * pkg_path,
482 package_manager_pkg_detail_info_t * pkg_detail_info)
484 LogDebug("pkg_plugin_get_app_detail_info_from_package() is called");
485 return getWidgetDetailInfoFromPackage(pkg_path, pkg_detail_info);
488 pkgmgr_info *pkgmgr_client_check_pkginfo_from_file(const char *pkg_path)
490 LogDebug("pkgmgr_client_check_pkginfo_from_file() is called");
491 package_manager_pkg_detail_info_t *pkg_detail_info;
492 pkg_detail_info = (package_manager_pkg_detail_info_t*)malloc(
493 sizeof(package_manager_pkg_detail_info_t));
494 int ret = getWidgetDetailInfoFromPackage(pkg_path, pkg_detail_info);
496 LogError("Failed to get package detail info ");
499 return reinterpret_cast<pkgmgr_info*>(pkg_detail_info);
502 __attribute__ ((visibility("default")))
503 int pkg_plugin_on_load(pkg_plugin_set *set)
505 DPL::Log::LogSystemSingleton::Instance().SetTag("WGT-BACKLIB");
509 memset(set, 0x00, sizeof(pkg_plugin_set));
511 set->plugin_on_unload = pkg_native_plugin_on_unload;
512 set->pkg_is_installed = pkg_plugin_app_is_installed;
513 set->get_installed_pkg_list = pkg_plugin_get_installed_apps_list;
514 set->get_pkg_detail_info = pkg_plugin_get_app_detail_info;
515 set->get_pkg_detail_info_from_package =
516 pkg_plugin_get_app_detail_info_from_package;