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/configuration/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 char kCategoryWearableClock[] =
47 "http://tizen.org/category/wearable_clock";
48 const char kCategoryWatchClock[] = "com.samsung.wmanager.WATCH_CLOCK";
50 const std::string kManifestVersion = "1.0.0";
51 const char kTizenPackageXmlNamespace[] = "http://tizen.org/ns/packages";
53 GList* GenerateMetadataListX(const wgt::parse::MetaDataInfo& meta_info) {
54 GList* list = nullptr;
55 for (auto& meta : meta_info.metadata()) {
56 metadata_x* new_meta =
57 static_cast<metadata_x*>(calloc(1, sizeof(metadata_x)));
58 new_meta->key = strdup(meta.first.c_str());
59 if (!meta.second.empty())
60 new_meta->value = strdup(meta.second.c_str());
61 list = g_list_append(list, new_meta);
66 void SetApplicationXDefaults(application_x* application) {
67 application->effectimage_type = strdup("image");
68 application->enabled = strdup("true");
69 application->guestmode_visibility = strdup("true");
70 application->hwacceleration = strdup("default");
71 application->indicatordisplay = strdup("true");
72 application->launchcondition = strdup("false");
73 application->permission_type = strdup("normal");
74 application->process_pool = strdup("false");
75 application->recentimage = strdup("false");
76 application->screenreader = strdup("use-system-setting");
77 application->submode = strdup("false");
78 application->support_disable = strdup("false");
79 application->taskmanage = strdup("true");
80 application->ui_gadget = strdup("false");
86 namespace configuration {
88 namespace app_keys = wgt::application_widget_keys;
89 namespace sc = std::chrono;
91 StepParse::StepParse(common_installer::InstallerContext* context,
92 bool check_start_file)
94 check_start_file_(check_start_file) {
97 std::set<std::string> StepParse::ExtractPrivileges(
98 std::shared_ptr<const wgt::parse::PermissionsInfo> perm_info) const {
99 return perm_info->GetAPIPermissions();
102 std::string StepParse::GetPackageVersion(
103 const std::string& manifest_version) {
104 if (manifest_version.empty()) {
105 return kManifestVersion;
107 std::string version = manifest_version.substr(0,
108 manifest_version.find_first_not_of("1234567890."));
110 utils::VersionNumber version_number(version);
112 if (!version_number.IsValidTizenPackageVersion()) {
113 LOG(WARNING) << "Version number: " << manifest_version
114 << " is not valid version number for tizen package. "
115 << "Default value will be used.";
116 return kManifestVersion;
119 return version_number.ToString();
122 bool StepParse::FillInstallationInfo(manifest_x* manifest) {
123 manifest->root_path = strdup(
124 (context_->root_application_path.get() / manifest->package).c_str());
125 manifest->installed_time =
126 strdup(std::to_string(sc::system_clock::to_time_t(
127 sc::system_clock::now())).c_str());
131 bool StepParse::FillIconPaths(manifest_x* manifest) {
132 std::shared_ptr<const wgt::parse::TizenApplicationInfo> app_info =
133 std::static_pointer_cast<const wgt::parse::TizenApplicationInfo>(
134 parser_->GetManifestData(app_keys::kTizenApplicationKey));
136 LOG(ERROR) << "Application info manifest data has not been found.";
139 std::shared_ptr<const wgt::parse::ApplicationIconsInfo> icons_info =
140 std::static_pointer_cast<const wgt::parse::ApplicationIconsInfo>(
141 parser_->GetManifestData(app_keys::kIconsKey));
142 if (icons_info.get()) {
143 for (auto& application_icon : icons_info->icons()) {
144 icon_x* icon = reinterpret_cast<icon_x*> (calloc(1, sizeof(icon_x)));
145 bf::path icon_path = context_->root_application_path.get()
146 / app_info->package() / "res" / "wgt" / application_icon.path();
147 icon->text = strdup(icon_path.c_str());
148 icon->lang = strdup(DEFAULT_LOCALE);
149 manifest->icon = g_list_append(manifest->icon, icon);
155 bool StepParse::FillWidgetInfo(manifest_x* manifest) {
156 std::shared_ptr<const wgt::parse::WidgetInfo> wgt_info =
157 std::static_pointer_cast<const wgt::parse::WidgetInfo>(
158 parser_->GetManifestData(app_keys::kWidgetKey));
159 if (!wgt_info.get()) {
160 LOG(ERROR) << "Widget info manifest data has not been found.";
164 const std::string& version = wgt_info->version();
166 manifest->ns = strdup(kTizenPackageXmlNamespace);
167 manifest->version = strdup(GetPackageVersion(version).c_str());
169 for (auto& item : wgt_info->description_set()) {
170 description_x* description = reinterpret_cast<description_x*>
171 (calloc(1, sizeof(description_x)));
172 description->text = strdup(item.second.c_str());
173 description->lang = !item.first.empty() ?
174 strdup(item.first.c_str()) : strdup(DEFAULT_LOCALE);
175 manifest->description = g_list_append(manifest->description, description);
178 for (auto& item : wgt_info->name_set()) {
179 label_x* label = reinterpret_cast<label_x*>(calloc(1, sizeof(label_x)));
180 label->name = strdup(item.second.c_str());
181 label->text = strdup(item.second.c_str());
182 label->lang = !item.first.empty() ?
183 strdup(item.first.c_str()) : strdup(DEFAULT_LOCALE);
184 manifest->label = g_list_append(manifest->label, label);
187 manifest->type = strdup("wgt");
188 manifest->appsetting = strdup("false");
189 manifest->nodisplay_setting = strdup("false");
190 manifest->preload = strdup("false");
192 // For wgt package use the long name
193 for (auto& item : wgt_info->name_set()) {
195 reinterpret_cast<application_x*>(manifest->application->data);
196 label_x* label = reinterpret_cast<label_x*>(calloc(1, sizeof(label_x)));
197 label->name = strdup(item.second.c_str());
198 label->text = strdup(item.second.c_str());
199 label->lang = !item.first.empty() ?
200 strdup(item.first.c_str()) : strdup(DEFAULT_LOCALE);
201 app->label = g_list_append(app->label, label);
204 author_x* author = reinterpret_cast<author_x*>(calloc(1, sizeof(author_x)));
205 if (!wgt_info->author().empty())
206 author->text = strdup(wgt_info->author().c_str());
207 if (!wgt_info->author_email().empty())
208 author->email = strdup(wgt_info->author_email().c_str());
209 if (!wgt_info->author_href().empty())
210 author->href = strdup(wgt_info->author_href().c_str());
211 author->lang = strdup(DEFAULT_LOCALE);
212 manifest->author = g_list_append(manifest->author, author);
214 std::shared_ptr<const wgt::parse::SettingInfo> settings_info =
215 std::static_pointer_cast<const wgt::parse::SettingInfo>(
216 parser_->GetManifestData(
217 wgt::application_widget_keys::kTizenSettingKey));
219 switch (settings_info->install_location()) {
220 case wgt::parse::SettingInfo::InstallLocation::AUTO: {
221 manifest->installlocation = strdup("auto");
224 case wgt::parse::SettingInfo::InstallLocation::INTERNAL: {
225 manifest->installlocation = strdup("internal-only");
228 case wgt::parse::SettingInfo::InstallLocation::EXTERNAL: {
229 manifest->installlocation = strdup("prefer-external");
234 manifest->installlocation = strdup("auto");
240 bool StepParse::FillMainApplicationInfo(manifest_x* manifest) {
241 std::shared_ptr<const wgt::parse::TizenApplicationInfo> app_info =
242 std::static_pointer_cast<const wgt::parse::TizenApplicationInfo>(
243 parser_->GetManifestData(app_keys::kTizenApplicationKey));
245 LOG(ERROR) << "Application info manifest data has not been found.";
248 bool has_watch_catergory = false;
249 std::shared_ptr<const wgt::parse::CategoryInfoList> category_info =
250 std::static_pointer_cast<const wgt::parse::CategoryInfoList>(
251 parser_->GetManifestData(app_keys::kTizenCategoryKey));
253 has_watch_catergory = std::find_if(category_info->categories.begin(),
254 category_info->categories.end(),
255 [](const std::string& category) {
256 return category == kCategoryWearableClock ||
257 category == kCategoryWatchClock;
258 }) != category_info->categories.end();
262 application_x* application = reinterpret_cast<application_x*>(
263 calloc(1, sizeof(application_x)));
264 application->component_type =
265 has_watch_catergory ? strdup("watchapp") : strdup("uiapp");
266 application->mainapp = strdup("true");
267 application->nodisplay = strdup("false");
268 application->multiple = strdup("false");
269 application->appid = strdup(app_info->id().c_str());
270 SetApplicationXDefaults(application);
271 if (has_watch_catergory)
272 application->ambient_support =
273 strdup(app_info->ambient_support() ? "true" : "false");
275 application->ambient_support = strdup("false");
276 application->package = strdup(app_info->package().c_str());
279 strdup((context_->root_application_path.get() / app_info->package()
280 / "bin" / application->appid).c_str());
281 application->type = strdup("webapp");
282 application->onboot = strdup("false");
283 application->autorestart = strdup("false");
285 application->launch_mode = strdup(app_info->launch_mode().c_str());
286 if (manifest->icon) {
287 icon_x* icon = reinterpret_cast<icon_x*>(manifest->icon->data);
288 icon_x* app_icon = reinterpret_cast<icon_x*>(calloc(1, sizeof(icon_x)));
289 app_icon->text = strdup(icon->text);
290 app_icon->lang = strdup(icon->lang);
291 application->icon = g_list_append(application->icon, app_icon);
293 manifest->application = g_list_append(manifest->application, application);
295 manifest->package = strdup(app_info->package().c_str());
296 manifest->mainapp_id = strdup(app_info->id().c_str());
300 bool StepParse::FillServiceApplicationInfo(manifest_x* manifest) {
301 std::shared_ptr<const wgt::parse::ServiceList> service_list =
302 std::static_pointer_cast<const wgt::parse::ServiceList>(
303 parser_->GetManifestData(app_keys::kTizenServiceKey));
306 for (auto& service_info : service_list->services) {
307 application_x* application = reinterpret_cast<application_x*>
308 (calloc(1, sizeof(application_x)));
309 application->component_type = strdup("svcapp");
310 application->mainapp = strdup("false");
311 application->nodisplay = strdup("false");
312 application->multiple = strdup("false");
313 application->appid = strdup(service_info.id().c_str());
315 strdup((context_->root_application_path.get() / manifest->package
316 / "bin" / application->appid).c_str());
317 application->type = strdup("webapp");
318 application->onboot =
319 service_info.on_boot() ? strdup("true") : strdup("false");
320 application->autorestart =
321 service_info.auto_restart() ? strdup("true") : strdup("false");
322 SetApplicationXDefaults(application);
323 application->ambient_support = strdup("false");
324 application->package = strdup(manifest->package);
326 for (auto& pair : service_info.names()) {
327 label_x* label = reinterpret_cast<label_x*>(calloc(1, sizeof(label_x)));
328 label->lang = !pair.first.empty() ?
329 strdup(pair.first.c_str()) : strdup(DEFAULT_LOCALE);
330 label->name = strdup(pair.second.c_str());
331 label->text = strdup(pair.second.c_str());
332 application->label = g_list_append(application->label, label);
335 if (!service_info.icon().empty()) {
336 icon_x* icon = reinterpret_cast<icon_x*>(calloc(1, sizeof(icon_x)));
337 icon->text = strdup(service_info.icon().c_str());
338 icon->lang = strdup(DEFAULT_LOCALE);
339 application->icon = g_list_append(application->icon, icon);
342 // TODO(t.iwanek): what about description, how is it different from name?
344 for (auto& category : service_info.categories()) {
345 application->category = g_list_append(application->category,
346 strdup(category.c_str()));
349 for (auto& pair : service_info.metadata_set()) {
350 metadata_x* item = reinterpret_cast<metadata_x*>(
351 calloc(1, sizeof(metadata_x)));
352 item->key = strdup(pair.first.c_str());
353 if (!pair.second.empty())
354 item->value = strdup(pair.second.c_str());
355 application->metadata = g_list_append(application->metadata, item);
358 manifest->application = g_list_append(manifest->application, application);
363 bool StepParse::FillBackgroundCategoryInfo(manifest_x* manifest) {
364 auto manifest_data = parser_->GetManifestData(
365 app_keys::kTizenBackgroundCategoryKey);
366 std::shared_ptr<const wgt::parse::BackgroundCategoryInfoList> bc_list =
367 std::static_pointer_cast<const wgt::parse::BackgroundCategoryInfoList>(
374 reinterpret_cast<application_x*>(manifest->application->data);
376 for (auto& background_category : bc_list->background_categories) {
377 app->background_category = g_list_append(
378 app->background_category, strdup(background_category.value().c_str()));
384 bool StepParse::FillAppControl(manifest_x* manifest) {
385 std::shared_ptr<const wgt::parse::AppControlInfoList> app_info_list =
386 std::static_pointer_cast<const wgt::parse::AppControlInfoList>(
387 parser_->GetManifestData(app_keys::kTizenApplicationAppControlsKey));
390 reinterpret_cast<application_x*>(manifest->application->data);
392 for (const auto& control : app_info_list->controls) {
393 appcontrol_x* app_control =
394 static_cast<appcontrol_x*>(calloc(1, sizeof(appcontrol_x)));
395 app_control->operation = strdup(control.operation().c_str());
396 app_control->mime = strdup(control.mime().c_str());
397 app_control->uri = strdup(control.uri().c_str());
398 app->appcontrol = g_list_append(app->appcontrol, app_control);
404 bool StepParse::FillPrivileges(manifest_x* manifest) {
405 std::shared_ptr<const wgt::parse::PermissionsInfo> perm_info =
406 std::static_pointer_cast<const wgt::parse::PermissionsInfo>(
407 parser_->GetManifestData(app_keys::kTizenPermissionsKey));
408 std::set<std::string> privileges;
410 privileges = ExtractPrivileges(perm_info);
412 for (auto& priv : privileges) {
413 manifest->privileges =
414 g_list_append(manifest->privileges, strdup(priv.c_str()));
419 bool StepParse::FillCategories(manifest_x* manifest) {
420 std::shared_ptr<const wgt::parse::CategoryInfoList> category_info =
421 std::static_pointer_cast<const wgt::parse::CategoryInfoList>(
422 parser_->GetManifestData(app_keys::kTizenCategoryKey));
427 reinterpret_cast<application_x*>(manifest->application->data);
428 // there is one app atm
429 for (auto& category : category_info->categories) {
430 app->category = g_list_append(app->category, strdup(category.c_str()));
435 bool StepParse::FillMetadata(manifest_x* manifest) {
436 std::shared_ptr<const wgt::parse::MetaDataInfo> meta_info =
437 std::static_pointer_cast<const wgt::parse::MetaDataInfo>(
438 parser_->GetManifestData(app_keys::kTizenMetaDataKey));
442 for (application_x* app : GListRange<application_x*>(manifest->application)) {
443 app->metadata = GenerateMetadataListX(*meta_info);
448 bool StepParse::FillAccounts(manifest_x* manifest) {
449 std::shared_ptr<const wgt::parse::AccountInfo> account_info =
450 std::static_pointer_cast<const wgt::parse::AccountInfo>(
451 parser_->GetManifestData(app_keys::kAccountKey));
454 common_installer::AccountInfo info;
455 for (auto& account : account_info->accounts()) {
456 common_installer::SingleAccountInfo single_info;
457 single_info.capabilities = account.capabilities;
458 single_info.icon_paths = account.icon_paths;
459 single_info.multiple_account_support = account.multiple_account_support;
460 single_info.names = account.names;
461 // wgt can contain only one app so this assumes mainapp_id is valid here
462 single_info.appid = manifest->mainapp_id;
463 info.set_account(single_info);
465 context_->manifest_plugins_data.get().account_info.set(info);
469 bool StepParse::FillExtraManifestInfo(manifest_x* manifest) {
470 return FillAccounts(manifest);
473 bool StepParse::FillManifestX(manifest_x* manifest) {
474 if (!FillIconPaths(manifest))
476 if (!FillMainApplicationInfo(manifest))
478 if (!FillWidgetInfo(manifest))
480 if (!FillInstallationInfo(manifest))
482 if (!FillPrivileges(manifest))
484 if (!FillAppControl(manifest))
486 if (!FillCategories(manifest))
488 if (!FillMetadata(manifest))
490 // TODO(t.iwanek): fix adding ui application element
491 // for now adding application service is added here because rest of code
492 // assumes that there is one application at manifest->application
493 // so this must execute last
494 if (!FillServiceApplicationInfo(manifest))
496 if (!FillBackgroundCategoryInfo(manifest))
498 if (!FillExtraManifestInfo(manifest))
503 bool StepParse::LocateConfigFile() {
504 return StepParse::Check(context_->unpacked_dir_path.get());
507 common_installer::Step::Status StepParse::process() {
508 if (!LocateConfigFile()) {
509 LOG(ERROR) << "No config.xml";
510 return common_installer::Step::Status::MANIFEST_NOT_FOUND;
513 parser_.reset(new wgt::parse::WidgetConfigParser());
514 if (!parser_->ParseManifest(config_)) {
515 LOG(ERROR) << "[Parse] Parse failed. " << parser_->GetErrorMessage();
516 return common_installer::Step::Status::PARSE_ERROR;
518 if (check_start_file_) {
519 if (!parser_->HasValidStartFile()) {
520 LOG(ERROR) << parser_->GetErrorMessage();
521 return common_installer::Step::Status::PARSE_ERROR;
523 if (!parser_->HasValidServicesStartFiles()) {
524 LOG(ERROR) << parser_->GetErrorMessage();
525 return common_installer::Step::Status::PARSE_ERROR;
529 manifest_x* manifest =
530 static_cast<manifest_x*>(calloc(1, sizeof(manifest_x)));
531 if (!FillManifestX(manifest)) {
532 LOG(ERROR) << "[Parse] Storing manifest_x failed. "
533 << parser_->GetErrorMessage();
534 return common_installer::Step::Status::PARSE_ERROR;
537 // Copy data from ManifestData to InstallerContext
538 std::shared_ptr<const wgt::parse::TizenApplicationInfo> info =
539 std::static_pointer_cast<const wgt::parse::TizenApplicationInfo>(
540 parser_->GetManifestData(
541 wgt::application_widget_keys::kTizenApplicationKey));
542 std::shared_ptr<const wgt::parse::WidgetInfo> wgt_info =
543 std::static_pointer_cast<const wgt::parse::WidgetInfo>(
544 parser_->GetManifestData(
545 wgt::application_widget_keys::kTizenWidgetKey));
548 const auto& name_set = wgt_info->name_set();
549 if (name_set.find("") != name_set.end())
550 name = name_set.find("")->second;
551 if (name_set.begin() != name_set.end())
552 name = name_set.begin()->second;
554 std::string short_name;
555 const auto& short_name_set = wgt_info->short_name_set();
556 if (short_name_set.find("") != short_name_set.end())
557 short_name = short_name_set.find("")->second;
558 if (short_name_set.begin() != short_name_set.end())
559 short_name = short_name_set.begin()->second;
561 const std::string& package_version = wgt_info->version();
562 const std::string& required_api_version = info->required_version();
564 manifest->api_version = strdup(required_api_version.c_str());
566 context_->pkgid.set(manifest->package);
568 // write pkgid for recovery file
569 if (context_->recovery_info.get().recovery_file) {
570 context_->recovery_info.get().recovery_file->set_pkgid(manifest->package);
571 context_->recovery_info.get().recovery_file->WriteAndCommitFileContent();
574 std::shared_ptr<const wgt::parse::PermissionsInfo> perm_info =
575 std::static_pointer_cast<const wgt::parse::PermissionsInfo>(
576 parser_->GetManifestData(
577 wgt::application_widget_keys::kTizenPermissionsKey));
578 parser::PermissionSet permissions;
580 permissions = perm_info->GetAPIPermissions();
582 WgtBackendData* backend_data =
583 static_cast<WgtBackendData*>(context_->backend_data.get());
585 std::shared_ptr<const wgt::parse::SettingInfo> settings_info =
586 std::static_pointer_cast<const wgt::parse::SettingInfo>(
587 parser_->GetManifestData(
588 wgt::application_widget_keys::kTizenSettingKey));
590 backend_data->settings.set(*settings_info);
592 LOG(DEBUG) << " Read data -[ ";
593 LOG(DEBUG) << "App id: " << info->id();
594 LOG(DEBUG) << " package = " << info->package();
595 LOG(DEBUG) << " id = " << info->id();
596 LOG(DEBUG) << " name = " << name;
597 LOG(DEBUG) << " short_name = " << short_name;
598 LOG(DEBUG) << " aplication version = " << package_version;
599 LOG(DEBUG) << " api_version = " << info->required_version();
600 LOG(DEBUG) << " launch_mode = " << info->launch_mode();
601 LOG(DEBUG) << " privileges -[";
602 for (const auto& p : permissions) {
603 LOG(DEBUG) << " " << p;
608 // TODO(t.iwanek): In delta mode this step is running two times
609 if (context_->manifest_data.get())
610 pkgmgr_parser_free_manifest_xml(context_->manifest_data.get());
612 context_->manifest_data.set(manifest);
613 return common_installer::Step::Status::OK;
616 bool StepParse::Check(const boost::filesystem::path& widget_path) {
617 boost::filesystem::path config = widget_path / "config.xml";
619 LOG(DEBUG) << "config.xml path: " << config;
621 if (!boost::filesystem::exists(config))
628 } // namespace configuration