1 /* 2014, Copyright © Intel Coporation, license APACHE-2.0, see LICENSE file */
2 // Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3 // Use of this source code is governed by a apache 2.0 license that can be
4 // found in the LICENSE file.
6 #include "wgt/step/step_parse.h"
8 #include <boost/filesystem/path.hpp>
10 #include <common/app_installer.h>
11 #include <common/installer_context.h>
12 #include <common/step/step.h>
13 #include <common/utils/glist_range.h>
14 #include <manifest_parser/utils/version_number.h>
15 #include <wgt_manifest_handlers/account_handler.h>
16 #include <wgt_manifest_handlers/app_control_handler.h>
17 #include <wgt_manifest_handlers/application_icons_handler.h>
18 #include <wgt_manifest_handlers/application_manifest_constants.h>
19 #include <wgt_manifest_handlers/background_category_handler.h>
20 #include <wgt_manifest_handlers/category_handler.h>
21 #include <wgt_manifest_handlers/content_handler.h>
22 #include <wgt_manifest_handlers/metadata_handler.h>
23 #include <wgt_manifest_handlers/service_handler.h>
24 #include <wgt_manifest_handlers/setting_handler.h>
25 #include <wgt_manifest_handlers/tizen_application_handler.h>
26 #include <wgt_manifest_handlers/widget_handler.h>
28 #include <pkgmgr/pkgmgr_parser.h>
40 #include "wgt/wgt_backend_data.h"
42 namespace bf = boost::filesystem;
46 const std::string kManifestVersion = "1.0.0";
47 const char kTizenPackageXmlNamespace[] = "http://tizen.org/ns/packages";
49 GList* GenerateMetadataListX(const wgt::parse::MetaDataInfo& meta_info) {
50 GList* list = nullptr;
51 for (auto& meta : meta_info.metadata()) {
52 metadata_x* new_meta =
53 static_cast<metadata_x*>(calloc(1, sizeof(metadata_x)));
54 new_meta->key = strdup(meta.first.c_str());
55 if (!meta.second.empty())
56 new_meta->value = strdup(meta.second.c_str());
57 list = g_list_append(list, new_meta);
62 void SetApplicationXDefaults(application_x* application) {
63 application->ambient_support = strdup("false");
64 application->effectimage_type = strdup("image");
65 application->enabled = strdup("true");
66 application->guestmode_visibility = strdup("true");
67 application->hwacceleration = strdup("default");
68 application->indicatordisplay = strdup("true");
69 application->launchcondition = strdup("false");
70 application->permission_type = strdup("normal");
71 application->process_pool = strdup("false");
72 application->recentimage = strdup("false");
73 application->screenreader = strdup("use-system-setting");
74 application->submode = strdup("false");
75 application->support_disable = strdup("false");
76 application->taskmanage = strdup("true");
77 application->ui_gadget = strdup("false");
85 namespace app_keys = wgt::application_widget_keys;
86 namespace sc = std::chrono;
88 StepParse::StepParse(common_installer::InstallerContext* context,
89 bool check_start_file)
91 check_start_file_(check_start_file) {
94 std::set<std::string> StepParse::ExtractPrivileges(
95 std::shared_ptr<const PermissionsInfo> perm_info) const {
96 return perm_info->GetAPIPermissions();
99 std::string StepParse::GetPackageVersion(
100 const std::string& manifest_version) {
101 if (manifest_version.empty()) {
102 return kManifestVersion;
104 std::string version = manifest_version.substr(0,
105 manifest_version.find_first_not_of("1234567890."));
107 utils::VersionNumber version_number(version);
109 if (!version_number.IsValidTizenPackageVersion()) {
110 LOG(WARNING) << "Version number: " << manifest_version
111 << " is not valid version number for tizen package. "
112 << "Default value will be used.";
113 return kManifestVersion;
116 return version_number.ToString();
119 bool StepParse::FillInstallationInfo(manifest_x* manifest) {
120 manifest->root_path = strdup(
121 (context_->root_application_path.get() / manifest->package).c_str());
122 manifest->installed_time =
123 strdup(std::to_string(sc::system_clock::to_time_t(
124 sc::system_clock::now())).c_str());
128 bool StepParse::FillIconPaths(manifest_x* manifest) {
129 std::shared_ptr<const TizenApplicationInfo> app_info =
130 std::static_pointer_cast<const TizenApplicationInfo>(
131 parser_->GetManifestData(app_keys::kTizenApplicationKey));
133 LOG(ERROR) << "Application info manifest data has not been found.";
136 std::shared_ptr<const ApplicationIconsInfo> icons_info =
137 std::static_pointer_cast<const ApplicationIconsInfo>(
138 parser_->GetManifestData(app_keys::kIconsKey));
139 if (icons_info.get()) {
140 for (auto& application_icon : icons_info->icons()) {
141 icon_x* icon = reinterpret_cast<icon_x*> (calloc(1, sizeof(icon_x)));
142 bf::path icon_path = context_->root_application_path.get()
143 / app_info->package() / "res" / "wgt" / application_icon.path();
144 icon->text = strdup(icon_path.c_str());
145 icon->lang = strdup(DEFAULT_LOCALE);
146 manifest->icon = g_list_append(manifest->icon, icon);
152 bool StepParse::FillWidgetInfo(manifest_x* manifest) {
153 std::shared_ptr<const WidgetInfo> wgt_info =
154 std::static_pointer_cast<const WidgetInfo>(parser_->GetManifestData(
155 app_keys::kWidgetKey));
156 if (!wgt_info.get()) {
157 LOG(ERROR) << "Widget info manifest data has not been found.";
161 const std::string& version = wgt_info->version();
163 manifest->ns = strdup(kTizenPackageXmlNamespace);
164 manifest->version = strdup(GetPackageVersion(version).c_str());
166 for (auto& item : wgt_info->description_set()) {
167 description_x* description = reinterpret_cast<description_x*>
168 (calloc(1, sizeof(description_x)));
169 description->text = strdup(item.second.c_str());
170 description->lang = !item.first.empty() ?
171 strdup(item.first.c_str()) : strdup(DEFAULT_LOCALE);
172 manifest->description = g_list_append(manifest->description, description);
175 for (auto& item : wgt_info->name_set()) {
176 label_x* label = reinterpret_cast<label_x*>(calloc(1, sizeof(label_x)));
177 label->name = strdup(item.second.c_str());
178 label->text = strdup(item.second.c_str());
179 label->lang = !item.first.empty() ?
180 strdup(item.first.c_str()) : strdup(DEFAULT_LOCALE);
181 manifest->label = g_list_append(manifest->label, label);
184 manifest->type = strdup("wgt");
185 manifest->appsetting = strdup("false");
186 manifest->nodisplay_setting = strdup("false");
187 manifest->preload = strdup("false");
189 // For wgt package use the long name
190 for (auto& item : wgt_info->name_set()) {
192 reinterpret_cast<application_x*>(manifest->application->data);
193 label_x* label = reinterpret_cast<label_x*>(calloc(1, sizeof(label_x)));
194 label->name = strdup(item.second.c_str());
195 label->text = strdup(item.second.c_str());
196 label->lang = !item.first.empty() ?
197 strdup(item.first.c_str()) : strdup(DEFAULT_LOCALE);
198 app->label = g_list_append(app->label, label);
201 author_x* author = reinterpret_cast<author_x*>(calloc(1, sizeof(author_x)));
202 if (!wgt_info->author().empty())
203 author->text = strdup(wgt_info->author().c_str());
204 if (!wgt_info->author_email().empty())
205 author->email = strdup(wgt_info->author_email().c_str());
206 if (!wgt_info->author_href().empty())
207 author->href = strdup(wgt_info->author_href().c_str());
208 author->lang = strdup(DEFAULT_LOCALE);
209 manifest->author = g_list_append(manifest->author, author);
211 std::shared_ptr<const SettingInfo> settings_info =
212 std::static_pointer_cast<const SettingInfo>(
213 parser_->GetManifestData(
214 wgt::application_widget_keys::kTizenSettingKey));
216 switch (settings_info->install_location()) {
217 case wgt::parse::SettingInfo::InstallLocation::AUTO: {
218 manifest->installlocation = strdup("auto");
221 case wgt::parse::SettingInfo::InstallLocation::INTERNAL: {
222 manifest->installlocation = strdup("internal-only");
225 case wgt::parse::SettingInfo::InstallLocation::EXTERNAL: {
226 manifest->installlocation = strdup("prefer-external");
231 manifest->installlocation = strdup("auto");
237 bool StepParse::FillUIApplicationInfo(manifest_x* manifest) {
238 std::shared_ptr<const TizenApplicationInfo> app_info =
239 std::static_pointer_cast<const TizenApplicationInfo>(
240 parser_->GetManifestData(app_keys::kTizenApplicationKey));
242 LOG(ERROR) << "Application info manifest data has not been found.";
246 application_x* application = reinterpret_cast<application_x*>(
247 calloc(1, sizeof(application_x)));
248 application->component_type = strdup("uiapp");
249 application->mainapp = strdup("true");
250 application->nodisplay = strdup("false");
251 application->multiple = strdup("false");
252 application->appid = strdup(app_info->id().c_str());
253 SetApplicationXDefaults(application);
254 application->package = strdup(app_info->package().c_str());
257 strdup((context_->root_application_path.get() / app_info->package()
258 / "bin" / application->appid).c_str());
259 application->type = strdup("webapp");
260 application->onboot = strdup("false");
261 application->autorestart = strdup("false");
263 application->launch_mode = strdup(app_info->launch_mode().c_str());
264 if (manifest->icon) {
265 icon_x* icon = reinterpret_cast<icon_x*>(manifest->icon->data);
266 icon_x* app_icon = reinterpret_cast<icon_x*>(calloc(1, sizeof(icon_x)));
267 app_icon->text = strdup(icon->text);
268 app_icon->lang = strdup(icon->lang);
269 application->icon = g_list_append(application->icon, app_icon);
271 manifest->application = g_list_append(manifest->application, application);
273 manifest->package = strdup(app_info->package().c_str());
274 manifest->mainapp_id = strdup(app_info->id().c_str());
278 bool StepParse::FillServiceApplicationInfo(manifest_x* manifest) {
279 std::shared_ptr<const ServiceList> service_list =
280 std::static_pointer_cast<const ServiceList>(
281 parser_->GetManifestData(app_keys::kTizenServiceKey));
284 for (auto& service_info : service_list->services) {
285 application_x* application = reinterpret_cast<application_x*>
286 (calloc(1, sizeof(application_x)));
287 application->component_type = strdup("svcapp");
288 application->mainapp = strdup("false");
289 application->nodisplay = strdup("false");
290 application->multiple = strdup("false");
291 application->appid = strdup(service_info.id().c_str());
293 strdup((context_->root_application_path.get() / manifest->package
294 / "bin" / application->appid).c_str());
295 application->type = strdup("webapp");
296 application->onboot =
297 service_info.on_boot() ? strdup("true") : strdup("false");
298 application->autorestart =
299 service_info.auto_restart() ? strdup("true") : strdup("false");
300 SetApplicationXDefaults(application);
301 application->package = strdup(manifest->package);
303 for (auto& pair : service_info.names()) {
304 label_x* label = reinterpret_cast<label_x*>(calloc(1, sizeof(label_x)));
305 label->lang = !pair.first.empty() ?
306 strdup(pair.first.c_str()) : strdup(DEFAULT_LOCALE);
307 label->name = strdup(pair.second.c_str());
308 label->text = strdup(pair.second.c_str());
309 application->label = g_list_append(application->label, label);
312 if (!service_info.icon().empty()) {
313 icon_x* icon = reinterpret_cast<icon_x*>(calloc(1, sizeof(icon_x)));
314 icon->text = strdup(service_info.icon().c_str());
315 icon->lang = strdup(DEFAULT_LOCALE);
316 application->icon = g_list_append(application->icon, icon);
319 // TODO(t.iwanek): what about description, how is it different from name?
321 for (auto& category : service_info.categories()) {
322 application->category = g_list_append(application->category,
323 strdup(category.c_str()));
326 for (auto& pair : service_info.metadata_set()) {
327 metadata_x* item = reinterpret_cast<metadata_x*>(
328 calloc(1, sizeof(metadata_x)));
329 item->key = strdup(pair.first.c_str());
330 if (!pair.second.empty())
331 item->value = strdup(pair.second.c_str());
332 application->metadata = g_list_append(application->metadata, item);
335 manifest->application = g_list_append(manifest->application, application);
340 bool StepParse::FillBackgroundCategoryInfo(manifest_x* manifest) {
341 auto manifest_data = parser_->GetManifestData(
342 app_keys::kTizenBackgroundCategoryKey);
343 std::shared_ptr<const BackgroundCategoryInfoList> bc_list =
344 std::static_pointer_cast<const BackgroundCategoryInfoList>(manifest_data);
350 reinterpret_cast<application_x*>(manifest->application->data);
352 for (auto& background_category : bc_list->background_categories) {
353 app->background_category = g_list_append(
354 app->background_category, strdup(background_category.value().c_str()));
360 bool StepParse::FillAppControl(manifest_x* manifest) {
361 std::shared_ptr<const AppControlInfoList> app_info_list =
362 std::static_pointer_cast<const AppControlInfoList>(
363 parser_->GetManifestData(app_keys::kTizenApplicationAppControlsKey));
366 reinterpret_cast<application_x*>(manifest->application->data);
368 for (const auto& control : app_info_list->controls) {
369 appcontrol_x* app_control =
370 static_cast<appcontrol_x*>(calloc(1, sizeof(appcontrol_x)));
371 app_control->operation = strdup(control.operation().c_str());
372 app_control->mime = strdup(control.mime().c_str());
373 app_control->uri = strdup(control.uri().c_str());
374 app->appcontrol = g_list_append(app->appcontrol, app_control);
380 bool StepParse::FillPrivileges(manifest_x* manifest) {
381 std::shared_ptr<const PermissionsInfo> perm_info =
382 std::static_pointer_cast<const PermissionsInfo>(parser_->GetManifestData(
383 app_keys::kTizenPermissionsKey));
384 std::set<std::string> privileges;
386 privileges = ExtractPrivileges(perm_info);
388 for (auto& priv : privileges) {
389 manifest->privileges =
390 g_list_append(manifest->privileges, strdup(priv.c_str()));
395 bool StepParse::FillCategories(manifest_x* manifest) {
396 std::shared_ptr<const CategoryInfoList> category_info =
397 std::static_pointer_cast<const CategoryInfoList>(parser_->GetManifestData(
398 app_keys::kTizenCategoryKey));
403 reinterpret_cast<application_x*>(manifest->application->data);
404 // there is one app atm
405 for (auto& category : category_info->categories) {
406 app->category = g_list_append(app->category, strdup(category.c_str()));
411 bool StepParse::FillMetadata(manifest_x* manifest) {
412 std::shared_ptr<const MetaDataInfo> meta_info =
413 std::static_pointer_cast<const MetaDataInfo>(parser_->GetManifestData(
414 app_keys::kTizenMetaDataKey));
418 for (application_x* app : GListRange<application_x*>(manifest->application)) {
419 app->metadata = GenerateMetadataListX(*meta_info);
424 bool StepParse::FillAccounts(manifest_x* manifest) {
425 std::shared_ptr<const AccountInfo> account_info =
426 std::static_pointer_cast<const AccountInfo>(parser_->GetManifestData(
427 app_keys::kAccountKey));
430 common_installer::AccountInfo info;
431 for (auto& account : account_info->accounts()) {
432 common_installer::SingleAccountInfo single_info;
433 single_info.capabilities = account.capabilities;
434 single_info.icon_paths = account.icon_paths;
435 single_info.multiple_account_support = account.multiple_account_support;
436 single_info.names = account.names;
437 // wgt can contain only one app so this assumes mainapp_id is valid here
438 single_info.appid = manifest->mainapp_id;
439 info.set_account(single_info);
441 context_->manifest_plugins_data.get().account_info.set(info);
445 bool StepParse::FillExtraManifestInfo(manifest_x* manifest) {
446 return FillAccounts(manifest);
449 bool StepParse::FillManifestX(manifest_x* manifest) {
450 if (!FillIconPaths(manifest))
452 if (!FillUIApplicationInfo(manifest))
454 if (!FillWidgetInfo(manifest))
456 if (!FillInstallationInfo(manifest))
458 if (!FillPrivileges(manifest))
460 if (!FillAppControl(manifest))
462 if (!FillCategories(manifest))
464 if (!FillMetadata(manifest))
466 // TODO(t.iwanek): fix adding ui application element
467 // for now adding application service is added here because rest of code
468 // assumes that there is one application at manifest->application
469 // so this must execute last
470 if (!FillServiceApplicationInfo(manifest))
472 if (!FillBackgroundCategoryInfo(manifest))
474 if (!FillExtraManifestInfo(manifest))
479 bool StepParse::LocateConfigFile() {
480 return StepParse::Check(context_->unpacked_dir_path.get());
483 common_installer::Step::Status StepParse::process() {
484 if (!LocateConfigFile()) {
485 LOG(ERROR) << "No config.xml";
486 return common_installer::Step::Status::MANIFEST_NOT_FOUND;
489 parser_.reset(new wgt::parse::WidgetConfigParser());
490 if (!parser_->ParseManifest(config_)) {
491 LOG(ERROR) << "[Parse] Parse failed. " << parser_->GetErrorMessage();
492 return common_installer::Step::Status::PARSE_ERROR;
494 if (check_start_file_) {
495 if (!parser_->HasValidStartFile()) {
496 LOG(ERROR) << parser_->GetErrorMessage();
497 return common_installer::Step::Status::PARSE_ERROR;
499 if (!parser_->HasValidServicesStartFiles()) {
500 LOG(ERROR) << parser_->GetErrorMessage();
501 return common_installer::Step::Status::PARSE_ERROR;
505 manifest_x* manifest =
506 static_cast<manifest_x*>(calloc(1, sizeof(manifest_x)));
507 if (!FillManifestX(manifest)) {
508 LOG(ERROR) << "[Parse] Storing manifest_x failed. "
509 << parser_->GetErrorMessage();
510 return common_installer::Step::Status::PARSE_ERROR;
513 // Copy data from ManifestData to InstallerContext
514 std::shared_ptr<const TizenApplicationInfo> info =
515 std::static_pointer_cast<const TizenApplicationInfo>(
516 parser_->GetManifestData(
517 wgt::application_widget_keys::kTizenApplicationKey));
518 std::shared_ptr<const WidgetInfo> wgt_info =
519 std::static_pointer_cast<const WidgetInfo>(
520 parser_->GetManifestData(
521 wgt::application_widget_keys::kTizenWidgetKey));
524 const auto& name_set = wgt_info->name_set();
525 if (name_set.find("") != name_set.end())
526 name = name_set.find("")->second;
527 if (name_set.begin() != name_set.end())
528 name = name_set.begin()->second;
530 std::string short_name;
531 const auto& short_name_set = wgt_info->short_name_set();
532 if (short_name_set.find("") != short_name_set.end())
533 short_name = short_name_set.find("")->second;
534 if (short_name_set.begin() != short_name_set.end())
535 short_name = short_name_set.begin()->second;
537 const std::string& package_version = wgt_info->version();
538 const std::string& required_api_version = info->required_version();
540 manifest->api_version = strdup(required_api_version.c_str());
542 context_->pkgid.set(manifest->package);
544 // write pkgid for recovery file
545 if (context_->recovery_info.get().recovery_file) {
546 context_->recovery_info.get().recovery_file->set_pkgid(manifest->package);
547 context_->recovery_info.get().recovery_file->WriteAndCommitFileContent();
550 std::shared_ptr<const PermissionsInfo> perm_info =
551 std::static_pointer_cast<const PermissionsInfo>(
552 parser_->GetManifestData(
553 wgt::application_widget_keys::kTizenPermissionsKey));
554 parser::PermissionSet permissions;
556 permissions = perm_info->GetAPIPermissions();
558 WgtBackendData* backend_data =
559 static_cast<WgtBackendData*>(context_->backend_data.get());
561 std::shared_ptr<const SettingInfo> settings_info =
562 std::static_pointer_cast<const SettingInfo>(
563 parser_->GetManifestData(
564 wgt::application_widget_keys::kTizenSettingKey));
566 backend_data->settings.set(*settings_info);
568 LOG(DEBUG) << " Read data -[ ";
569 LOG(DEBUG) << "App id: " << info->id();
570 LOG(DEBUG) << " package = " << info->package();
571 LOG(DEBUG) << " id = " << info->id();
572 LOG(DEBUG) << " name = " << name;
573 LOG(DEBUG) << " short_name = " << short_name;
574 LOG(DEBUG) << " aplication version = " << package_version;
575 LOG(DEBUG) << " api_version = " << info->required_version();
576 LOG(DEBUG) << " launch_mode = " << info->launch_mode();
577 LOG(DEBUG) << " privileges -[";
578 for (const auto& p : permissions) {
579 LOG(DEBUG) << " " << p;
584 // TODO(t.iwanek): In delta mode this step is running two times
585 if (context_->manifest_data.get())
586 pkgmgr_parser_free_manifest_xml(context_->manifest_data.get());
588 context_->manifest_data.set(manifest);
589 return common_installer::Step::Status::OK;
592 bool StepParse::Check(const boost::filesystem::path& widget_path) {
593 boost::filesystem::path config = widget_path / "config.xml";
595 LOG(DEBUG) << "config.xml path: " << config;
597 if (!boost::filesystem::exists(config))