Change code to store api_version of application
[platform/core/appfw/app-installers.git] / src / common / step / configuration / step_parse_manifest.cc
1 // Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by an apache 2.0 license that can be
3 // found in the LICENSE file.
4
5 #include "common/step/configuration/step_parse_manifest.h"
6
7 #include <boost/tokenizer.hpp>
8
9 #include <pkgmgr/pkgmgr_parser.h>
10 #include <pkgmgr-info.h>
11
12 #include <tpk_manifest_handlers/account_handler.h>
13 #include <tpk_manifest_handlers/common/appdefined_privilege_handler.h>
14 #include <tpk_manifest_handlers/application_manifest_constants.h>
15 #include <tpk_manifest_handlers/author_handler.h>
16 #include <tpk_manifest_handlers/description_handler.h>
17 #include <tpk_manifest_handlers/feature_handler.h>
18 #include <tpk_manifest_handlers/package_handler.h>
19 #include <tpk_manifest_handlers/privileges_handler.h>
20 #include <tpk_manifest_handlers/profile_handler.h>
21 #include <tpk_manifest_handlers/provides_appdefined_privileges_handler.h>
22 #include <tpk_manifest_handlers/service_application_handler.h>
23 #include <tpk_manifest_handlers/shortcut_handler.h>
24 #include <tpk_manifest_handlers/trust_anchor_handler.h>
25 #include <tpk_manifest_handlers/ui_application_handler.h>
26 #include <tpk_manifest_handlers/watch_application_handler.h>
27 #include <tpk_manifest_handlers/widget_application_handler.h>
28
29 #include <chrono>
30 #include <cstdio>
31 #include <cstdlib>
32 #include <cstring>
33 #include <memory>
34 #include <set>
35 #include <type_traits>
36 #include <string>
37 #include <vector>
38
39 #include "common/app2ext_dynamic_service.h"
40 #include "common/app_installer.h"
41 #include "common/feature_validator.h"
42 #include "common/installer_context.h"
43 #include "common/paths.h"
44 #include "common/privileges.h"
45 #include "common/pkgmgr_registration.h"
46 #include "common/pkgmgr_query.h"
47 #include "common/step/step.h"
48 #include "common/utils/glist_range.h"
49
50 namespace app_keys = tpk::application_keys;
51 namespace bf = boost::filesystem;
52
53 namespace {
54
55 const char kManifestFileName[] = "tizen-manifest.xml";
56 const char kInstalledInternally[] = "installed_internal";
57 const char kInstalledExternally[] = "installed_external";
58 const char kPortraitOrientation[] = "portrait";
59 const char kLandscapeOrientation[] = "landscape";
60 const char kOperationEffectKey[] = "operation_effect";
61 const char kLaunchEffectKey[] = "launch_effect";
62 const char kPortraitEffectImageValue[] = "portrait-effectimage";
63 const char kLandscapeEffectImageValue[] = "landscape-effectimage";
64 const char kIndicatorDisplayValue[] = "indicatordisplay";
65
66 }  // namespace
67
68 namespace common_installer {
69 namespace configuration {
70
71 StepParseManifest::StepParseManifest(
72     InstallerContext* context, ManifestLocation manifest_location,
73     StoreLocation store_location)
74     : Step(context),
75       manifest_location_(manifest_location),
76       store_location_(store_location) {
77 }
78
79 Step::Status StepParseManifest::precheck() {
80   switch (manifest_location_) {
81     case ManifestLocation::RECOVERY:
82       if (context_->pkgid.get().empty())
83         return Status::RECOVERY_DONE;
84       break;
85     case ManifestLocation::INSTALLED:
86       if (context_->pkgid.get().empty()) {
87         LOG(ERROR) << "Package id is not set";
88         return Status::INVALID_VALUE;
89       }
90       break;
91     case ManifestLocation::PACKAGE:
92       if (context_->unpacked_dir_path.get().empty()) {
93         LOG(ERROR) << "Unpacked directory doesn't exist";
94         return Status::INVALID_VALUE;
95       }
96       break;
97     default:
98       LOG(ERROR) << "Unknown manifest location";
99       return Status::INVALID_VALUE;
100   }
101   return Status::OK;
102 }
103
104 bool StepParseManifest::LocateConfigFile() {
105   boost::filesystem::path manifest;
106   switch (manifest_location_) {
107     case ManifestLocation::RECOVERY: {
108       context_->pkg_path.set(
109           context_->root_application_path.get() / context_->pkgid.get());
110       bf::path backup_path = common_installer::GetBackupPathForPackagePath(
111           context_->pkg_path.get()) / kManifestFileName;
112       bf::path in_package_path = context_->pkg_path.get() / kManifestFileName;
113       bf::path install_path =
114           bf::path(getUserManifestPath(context_->uid.get(),
115                       context_->is_readonly_package.get()))
116               / bf::path(context_->pkgid.get());
117       install_path += ".xml";
118       if (bf::exists(backup_path))
119         manifest = backup_path;
120       else if (bf::exists(in_package_path))
121         manifest = in_package_path;
122       else if (bf::exists(install_path))
123         manifest = install_path;
124       break;
125     }
126     case ManifestLocation::INSTALLED: {
127       uid_t uid;
128       bool is_readonly = context_->is_readonly_package.get();
129       PkgQueryInterface pkg_query(context_->pkgid.get(), context_->uid.get());
130       if (pkg_query.IsGlobalPackage())
131         uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
132       else
133         uid = context_->uid.get();
134       bf::path xml_path =
135           bf::path(getUserManifestPath(uid, is_readonly))
136           / bf::path(context_->pkgid.get());
137       xml_path += ".xml";
138       context_->xml_path.set(xml_path);
139       manifest = context_->xml_path.get();
140       if (!boost::filesystem::exists(manifest)) {
141         /* This routine has added for platform update */
142         manifest = context_->unpacked_dir_path.get();
143         manifest /= kManifestFileName;
144       }
145       break;
146     }
147     case ManifestLocation::PACKAGE: {
148       manifest = context_->unpacked_dir_path.get();
149       manifest /= kManifestFileName;
150       break;
151     }
152     default: {
153       LOG(ERROR) << "Unknown manifest location value";
154       return false;
155     }
156   }
157
158   LOG(DEBUG) << "manifest path: " << manifest;
159
160   if (!boost::filesystem::exists(manifest))
161     return false;
162
163   path_ = manifest;
164   return true;
165 }
166
167 int StepParseManifest::GetSupportModeVal(std::string support_mode) {
168   int mode = 0;
169   std::size_t found = std::string::npos;
170
171   found = support_mode.find(APP_SUPPORT_MODE_ULTRA_POWER_SAVING_STR);
172   if (found != std::string::npos)
173     mode |= APP_SUPPORT_MODE_ULTRA_POWER_SAVING_VAL;
174
175   found = support_mode.find(APP_SUPPORT_MODE_COOL_DOWN_STR);
176   if (found != std::string::npos)
177     mode |= APP_SUPPORT_MODE_COOL_DOWN_VAL;
178
179   found = support_mode.find(APP_SUPPORT_MODE_SCREEN_READER_STR);
180   if (found != std::string::npos)
181     mode |= APP_SUPPORT_MODE_SCREEN_READER_VAL;
182
183   return mode;
184 }
185
186 bool StepParseManifest::FillInstallationInfo(manifest_x* manifest) {
187   manifest->root_path = strdup(
188       (context_->root_application_path.get() / manifest->package).c_str());
189   manifest->installed_time =
190       strdup(std::to_string(std::chrono::system_clock::to_time_t(
191           std::chrono::system_clock::now())).c_str());
192   return true;
193 }
194
195 bool StepParseManifest::FillPackageInfo(manifest_x* manifest) {
196   std::shared_ptr<const tpk::parse::PackageInfo> pkg_info =
197       std::static_pointer_cast<const tpk::parse::PackageInfo>(
198           parser_->GetManifestData(app_keys::kManifestKey));
199   if (!pkg_info) {
200     LOG(ERROR) << "Package info manifest data has not been found.";
201     return false;
202   }
203
204   auto ui_application_list =
205       std::static_pointer_cast<const tpk::parse::UIApplicationInfoList>(
206           parser_->GetManifestData(app_keys::kUIApplicationKey));
207   auto service_application_list =
208       std::static_pointer_cast<const tpk::parse::ServiceApplicationInfoList>(
209           parser_->GetManifestData(app_keys::kServiceApplicationKey));
210   auto widget_application_list =
211       std::static_pointer_cast<const tpk::parse::WidgetApplicationInfoList>(
212           parser_->GetManifestData(app_keys::kWidgetApplicationKey));
213   auto watch_application_list =
214       std::static_pointer_cast<const tpk::parse::WatchApplicationInfoList>(
215           parser_->GetManifestData(app_keys::kWatchApplicationKey));
216
217   // mandatory check
218   if (!ui_application_list && !service_application_list &&
219       !widget_application_list && !watch_application_list) {
220     LOG(ERROR) << "UI Application or Service Application or Widget Application "
221                   "or Watch Application are mandatory and has not been found.";
222     return false;
223   }
224
225   int support_mode_val = GetSupportModeVal(pkg_info->support_mode());
226
227   manifest->ns = strdup(pkg_info->xmlns().c_str());
228   manifest->package = strdup(pkg_info->package().c_str());
229   manifest->nodisplay_setting = strdup(pkg_info->nodisplay_setting().c_str());
230   manifest->support_mode = strdup((std::to_string(support_mode_val)).c_str());
231   manifest->appsetting = strdup("false");
232   manifest->support_disable = strdup(pkg_info->support_disable().c_str());
233   manifest->version = strdup(pkg_info->version().c_str());
234   manifest->installlocation = strdup(pkg_info->install_location().c_str());
235   manifest->api_version = strdup(pkg_info->api_version().c_str());
236   manifest->readonly = strdup(pkg_info->readonly().c_str());
237   manifest->preload = strdup(pkg_info->preload().c_str());
238   manifest->removable = strdup(pkg_info->removable().c_str());
239
240   common_installer::RequestType req_type = context_->request_type.get();
241   if (pkg_info->type().empty()) {
242     if ((req_type == RequestType::ManifestDirectInstall ||
243         req_type == RequestType::ManifestDirectUpdate) &&
244         context_->is_readonly_package.get())
245       manifest->type = strdup("rpm");
246     else
247       manifest->type = strdup("tpk");
248   } else {
249     manifest->type = strdup(pkg_info->type().c_str());
250   }
251
252   // Set external path if the package is installed at external storage.
253   if (req_type == RequestType::ManifestDirectInstall ||
254       req_type == RequestType::ManifestDirectUpdate ||
255       req_type == RequestType::ManifestPartialInstall ||
256       req_type == RequestType::ManifestPartialUpdate) {
257     App2ExtDynamicService service;
258     std::string image_path = service.GetExternalImagePath(
259         context_->pkgid.get().c_str(), context_->uid.get());
260     if (!image_path.empty()) {
261       manifest->external_path = strdup(image_path.c_str());
262       manifest->installed_storage = strdup(kInstalledExternally);
263     }
264   }
265
266   for (auto& pair : pkg_info->labels()) {
267     label_x* label = reinterpret_cast<label_x*>(calloc(1, sizeof(label_x)));
268     if (!label) {
269       LOG(ERROR) << "Out of memory";
270       return false;
271     }
272     if (!pair.first.empty())
273       label->lang = strdup(pair.first.c_str());
274     else
275       label->lang = strdup(DEFAULT_LOCALE);
276     label->text = strdup(pair.second.c_str());
277     manifest->label = g_list_append(manifest->label, label);
278   }
279
280   std::shared_ptr<const tpk::parse::ProfileInfo> profile_info =
281       std::static_pointer_cast<const tpk::parse::ProfileInfo>(
282           parser_->GetManifestData(tpk::parse::ProfileInfo::Key()));
283   if (profile_info) {
284     for (auto& profile : profile_info->profiles()) {
285       manifest->deviceprofile = g_list_append(manifest->deviceprofile,
286                                               strdup(profile.c_str()));
287     }
288   }
289
290   // set installed_storage if package is installed
291   // this is internal field in package manager but after reading configuration
292   // we must know it
293   if (!manifest->installed_storage) {
294     if (manifest_location_ == ManifestLocation::INSTALLED ||
295         manifest_location_ == ManifestLocation::RECOVERY) {
296       PkgQueryInterface pkg_query(manifest->package, context_->uid.get());
297       std::string storage = pkg_query.StorageForPkgId();
298       if (storage.empty()) {
299         // Failed to query installation storage, assign internal
300         manifest->installed_storage = strdup(kInstalledInternally);
301       } else {
302         manifest->installed_storage = strdup(storage.c_str());
303       }
304     } else {
305       manifest->installed_storage = strdup(kInstalledInternally);
306     }
307   }
308
309   return true;
310 }
311
312 bool StepParseManifest::FillAuthorInfo(manifest_x* manifest) {
313   std::shared_ptr<const tpk::parse::AuthorInfo> author_info =
314       std::static_pointer_cast<const tpk::parse::AuthorInfo>(
315           parser_->GetManifestData(tpk::parse::AuthorInfo::Key()));
316
317   if (!author_info)
318     return true;
319
320   author_x* author = reinterpret_cast<author_x*>(calloc(1, sizeof(author_x)));
321   if (!author) {
322     LOG(ERROR) << "Out of memory";
323     return false;
324   }
325   author->text = strdup(author_info->name().c_str());
326   author->email = strdup(author_info->email().c_str());
327   author->href = strdup(author_info->href().c_str());
328   author->lang = strdup(DEFAULT_LOCALE);
329   manifest->author = g_list_append(manifest->author, author);
330   return true;
331 }
332
333 bool StepParseManifest::FillDescriptionInfo(manifest_x* manifest) {
334   std::shared_ptr<const tpk::parse::DescriptionInfoList> description_info =
335       std::static_pointer_cast<const tpk::parse::DescriptionInfoList>(
336           parser_->GetManifestData(tpk::parse::DescriptionInfoList::Key()));
337
338   if (!description_info)
339     return true;
340
341   for (auto& desc : description_info->descriptions) {
342     description_x* description = reinterpret_cast<description_x*>
343         (calloc(1, sizeof(description_x)));
344     if (!description) {
345       LOG(ERROR) << "Out of memory";
346       return false;
347     }
348     description->text = strdup(desc.description().c_str());
349     description->lang = !desc.xml_lang().empty() ?
350         strdup(desc.xml_lang().c_str()) : strdup(DEFAULT_LOCALE);
351     manifest->description = g_list_append(manifest->description, description);
352   }
353   return true;
354 }
355
356 bool StepParseManifest::FillPrivileges(manifest_x* manifest) {
357   std::shared_ptr<const tpk::parse::PrivilegesInfo> perm_info =
358       std::static_pointer_cast<const tpk::parse::PrivilegesInfo>(
359           parser_->GetManifestData(app_keys::kPrivilegesKey));
360   if (!perm_info)
361     return true;
362
363   const auto& privileges = perm_info->GetPrivileges();
364   for (auto& priv : privileges) {
365     privilege_x* privilege =
366         reinterpret_cast<privilege_x*>(calloc(1, sizeof(privilege_x)));
367     if (!privilege) {
368       LOG(ERROR) << "Out of memory";
369       return false;
370     }
371     privilege->value = strdup(priv.first.c_str());
372     privilege->type = strdup(priv.second.c_str());
373     manifest->privileges = g_list_append(manifest->privileges, privilege);
374   }
375
376   const auto& appdef_privileges_list =
377       perm_info->GetAppDefinedPrivilegeInfoList();
378   for (auto& appdef_info : appdef_privileges_list) {
379     appdefined_privilege_x* privilege =
380         reinterpret_cast<appdefined_privilege_x*>(calloc(1,
381             sizeof(appdefined_privilege_x)));
382     if (privilege == nullptr) {
383       LOG(ERROR) << "Memory alloc failure";
384       return false;
385     }
386     auto& priv = appdef_info.GetAppDefinedPrivilege();
387     privilege->value = strdup(priv.privilege.c_str());
388     privilege->type = strdup(priv.type.c_str());
389     if (!priv.license.empty()) {
390       if (bf::path(priv.license).is_absolute())
391         privilege->license = strdup(priv.license.c_str());
392       else
393         privilege->license = strdup((context_->pkg_path.get()
394             / priv.license).c_str());
395     }
396     manifest->appdefined_privileges =
397         g_list_append(manifest->appdefined_privileges, privilege);
398   }
399
400   return true;
401 }
402
403 bool StepParseManifest::FillProvidesAppDefinedPrivileges(
404     manifest_x* manifest) {
405   std::shared_ptr<const tpk::parse::ProvidesAppDefinedPrivilegesInfo>
406       priv_info = std::static_pointer_cast<
407           const tpk::parse::ProvidesAppDefinedPrivilegesInfo>(
408               parser_->GetManifestData(
409                   app_keys::kProvidesAppDefinedPrivilegesKey));
410   if (!priv_info)
411     return true;
412
413   const auto& privileges_list = priv_info->GetAppDefinedPrivilegeInfoList();
414   for (auto& appdef_info : privileges_list) {
415     appdefined_privilege_x* privilege =
416         reinterpret_cast<appdefined_privilege_x*>(calloc(1,
417             sizeof(appdefined_privilege_x)));
418     if (privilege == nullptr) {
419       LOG(ERROR) << "Memory alloc failure";
420       return false;
421     }
422     auto& priv = appdef_info.GetAppDefinedPrivilege();
423     privilege->value = strdup(priv.privilege.c_str());
424     privilege->type = strdup(priv.type.c_str());
425     if (!priv.license.empty()) {
426       if (bf::path(priv.license).is_absolute())
427         privilege->license = strdup(priv.license.c_str());
428       else
429         privilege->license = strdup((context_->pkg_path.get()
430             / priv.license).c_str());
431     }
432     manifest->provides_appdefined_privileges =
433         g_list_append(manifest->provides_appdefined_privileges, privilege);
434   }
435
436   return true;
437 }
438
439 bool StepParseManifest::FillWidgetApplication(manifest_x* manifest) {
440   auto widget_application_list =
441       std::static_pointer_cast<const tpk::parse::WidgetApplicationInfoList>(
442           parser_->GetManifestData(app_keys::kWidgetApplicationKey));
443   if (!widget_application_list)
444     return true;
445
446   for (const auto& application : widget_application_list->items) {
447     int package_support_mode_val = atoi(manifest->support_mode);
448     int app_support_mode_val = package_support_mode_val |
449         GetSupportModeVal(application.app_info.support_mode());
450
451     application_x* widget_app =
452         static_cast<application_x*>(calloc(1, sizeof(application_x)));
453     if (!widget_app) {
454       LOG(ERROR) << "Out of memory";
455       return false;
456     }
457     widget_app->appid = strdup(application.app_info.appid().c_str());
458     widget_app->launch_mode =
459         strdup(application.app_info.launch_mode().c_str());
460     widget_app->multiple = strdup("false");
461     widget_app->nodisplay = strdup("true");
462     widget_app->support_mode =
463         strdup((std::to_string(app_support_mode_val)).c_str());
464     widget_app->taskmanage = strdup("false");
465     widget_app->indicatordisplay = strdup("false");
466     widget_app->type =
467         strdup(application.app_info.type().c_str());
468     widget_app->component_type = strdup("widgetapp");
469     widget_app->hwacceleration =
470         strdup(application.app_info.hwacceleration().c_str());
471     widget_app->onboot = strdup("false");
472     widget_app->autorestart = strdup("false");
473     widget_app->mainapp = strdup(application.app_info.mainapp().c_str());
474     widget_app->screenreader = strdup("use-system-setting");
475     widget_app->recentimage = strdup("false");
476     widget_app->launchcondition = strdup("false");
477     widget_app->guestmode_visibility = strdup("true");
478     widget_app->permission_type = strdup("normal");
479     widget_app->support_ambient = strdup("false");
480     widget_app->effectimage_type = strdup("image");
481     widget_app->submode = strdup("false");
482     widget_app->process_pool = strdup("false");
483     widget_app->package = strdup(manifest->package);
484     widget_app->support_disable = strdup(manifest->support_disable);
485     widget_app->launch_mode = strdup("single");
486     widget_app->api_version = strdup(manifest->api_version);
487     manifest->application = g_list_append(manifest->application, widget_app);
488     if (bf::path(application.app_info.exec().c_str()).is_absolute())
489       widget_app->exec = strdup(application.app_info.exec().c_str());
490     else
491       widget_app->exec = strdup((context_->root_application_path.get()
492                             / manifest->package / "bin"
493                             / application.app_info.exec()).c_str());
494
495     if (!FillApplicationIconPaths(widget_app, application.app_icons))
496       return false;
497     if (!FillLabel(widget_app, application.label))
498       return false;
499     if (!FillImage(widget_app, application.app_images))
500       return false;
501     if (!FillCategories(widget_app, application.categories))
502       return false;
503     if (!FillMetadata(widget_app, application.meta_data))
504       return false;
505   }
506   return true;
507 }
508
509 bool StepParseManifest::FillServiceApplication(manifest_x* manifest) {
510   auto service_application_list =
511       std::static_pointer_cast<const tpk::parse::ServiceApplicationInfoList>(
512           parser_->GetManifestData(app_keys::kServiceApplicationKey));
513   if (!service_application_list)
514     return true;
515
516   for (const auto& application : service_application_list->items) {
517     int package_support_mode_val = atoi(manifest->support_mode);
518     int app_support_mode_val = package_support_mode_val |
519         GetSupportModeVal(application.app_info.support_mode());
520
521     application_x* service_app =
522         static_cast<application_x*>(calloc(1, sizeof(application_x)));
523     if (!service_app) {
524       LOG(ERROR) << "Out of memory";
525       return false;
526     }
527     service_app->appid = strdup(application.app_info.appid().c_str());
528     service_app->multiple = strdup(application.app_info.multiple().c_str());
529     service_app->taskmanage = strdup(application.app_info.taskmanage().c_str());
530     service_app->support_mode =
531         strdup((std::to_string(app_support_mode_val)).c_str());
532     service_app->autorestart =
533         strdup(application.app_info.auto_restart().c_str());
534     service_app->onboot = strdup(application.app_info.on_boot().c_str());
535     service_app->type = strdup(application.app_info.type().c_str());
536     service_app->process_pool =
537         strdup(application.app_info.process_pool().c_str());
538     service_app->component_type = strdup("svcapp");
539     service_app->mainapp = strdup(application.app_info.mainapp().c_str());
540     service_app->nodisplay = strdup("true");
541     service_app->hwacceleration = strdup("default");
542     service_app->screenreader = strdup("use-system-setting");
543     service_app->recentimage = strdup("false");
544     service_app->launchcondition = strdup("false");
545     service_app->indicatordisplay = strdup("true");
546     service_app->effectimage_type = strdup("image");
547     service_app->guestmode_visibility = strdup("true");
548     service_app->permission_type = strdup("normal");
549     service_app->submode = strdup("false");
550     service_app->process_pool = strdup("false");
551     service_app->support_ambient = strdup("false");
552     service_app->package = strdup(manifest->package);
553     service_app->support_disable = strdup(manifest->support_disable);
554     service_app->launch_mode = strdup("single");
555     service_app->api_version = strdup(manifest->api_version);
556     manifest->application = g_list_append(manifest->application, service_app);
557     if (bf::path(application.app_info.exec().c_str()).is_absolute())
558       service_app->exec = strdup(application.app_info.exec().c_str());
559     else
560       service_app->exec = strdup((context_->root_application_path.get()
561                             / manifest->package / "bin"
562                             / application.app_info.exec()).c_str());
563
564     if (!FillAppControl(service_app,  application.app_control))
565       return false;
566     if (!FillDataControl(service_app, application.data_control))
567       return false;
568     if (!FillApplicationIconPaths(service_app, application.app_icons))
569       return false;
570     if (!FillLabel(service_app, application.label))
571       return false;
572     if (!FillMetadata(service_app, application.meta_data))
573       return false;
574     if (!FillCategories(service_app, application.categories))
575       return false;
576     if (!FillBackgroundCategoryInfo(service_app,
577         application.background_category))
578       return false;
579   }
580   return true;
581 }
582
583 bool StepParseManifest::FillUIApplication(manifest_x* manifest) {
584   std::shared_ptr<const tpk::parse::UIApplicationInfoList> ui_application_list =
585       std::static_pointer_cast<const tpk::parse::UIApplicationInfoList>(
586           parser_->GetManifestData(app_keys::kUIApplicationKey));
587   if (!ui_application_list)
588     return true;
589
590   for (const auto& application : ui_application_list->items) {
591     int package_support_mode_val = atoi(manifest->support_mode);
592     int app_support_mode_val = package_support_mode_val |
593         GetSupportModeVal(application.app_info.support_mode());
594
595     application_x* ui_app =
596         static_cast<application_x*>(calloc(1, sizeof(application_x)));
597     if (!ui_app) {
598       LOG(ERROR) << "Out of memory";
599       return false;
600     }
601     ui_app->appid = strdup(application.app_info.appid().c_str());
602     ui_app->launch_mode = strdup(application.app_info.launch_mode().c_str());
603     ui_app->multiple = strdup(application.app_info.multiple().c_str());
604     ui_app->nodisplay = strdup(application.app_info.nodisplay().c_str());
605     ui_app->support_mode =
606         strdup((std::to_string(app_support_mode_val)).c_str());
607     ui_app->taskmanage = strdup(application.app_info.taskmanage().c_str());
608     ui_app->type = strdup(application.app_info.type().c_str());
609     ui_app->ui_gadget = strdup(application.app_info.uigadget().c_str());
610     ui_app->process_pool = strdup(application.app_info.process_pool().c_str());
611     ui_app->submode = strdup(application.app_info.submode().c_str());
612     if (!application.app_info.indicator_display().empty())
613       ui_app->indicatordisplay =
614           strdup(application.app_info.indicator_display().c_str());
615     if (!application.app_info.effectimage_type().empty())
616       ui_app->effectimage_type =
617           strdup(application.app_info.effectimage_type().c_str());
618     if (!application.app_info.portrait_image().empty()) {
619       ui_app->portraitimg =
620           strdup(application.app_info.portrait_image().c_str());
621       AppendSplashScreen(ui_app, application.app_info.portrait_image(),
622           application.app_info.effectimage_type(), {}, kPortraitOrientation,
623           application.app_info.indicator_display(), {}, {});
624     }
625     if (!application.app_info.landscape_image().empty()) {
626       ui_app->landscapeimg =
627           strdup(application.app_info.landscape_image().c_str());
628       AppendSplashScreen(ui_app, application.app_info.landscape_image(),
629           application.app_info.effectimage_type(), {}, kLandscapeOrientation,
630           application.app_info.indicator_display(), {}, {});
631     }
632     ui_app->submode_mainid =
633         strdup(application.app_info.submode_mainid().c_str());
634     ui_app->hwacceleration =
635         strdup(application.app_info.hwacceleration().c_str());
636     ui_app->onboot = strdup("false");
637     ui_app->autorestart = strdup("false");
638     ui_app->component_type = strdup("uiapp");
639     ui_app->mainapp = strdup(application.app_info.mainapp().c_str());
640     ui_app->screenreader = strdup("use-system-setting");
641     ui_app->recentimage = strdup("false");
642     ui_app->launchcondition = strdup("false");
643     ui_app->guestmode_visibility = strdup("true");
644     ui_app->permission_type = strdup("normal");
645     ui_app->support_ambient = strdup("false");
646     ui_app->package = strdup(manifest->package);
647     ui_app->support_disable = strdup(manifest->support_disable);
648     ui_app->splash_screen_display =
649         strdup(application.app_info.splash_screen_display().c_str());
650     ui_app->api_version = strdup(manifest->api_version);
651     manifest->application = g_list_append(manifest->application, ui_app);
652     if (bf::path(application.app_info.exec().c_str()).is_absolute())
653       ui_app->exec = strdup(application.app_info.exec().c_str());
654     else
655       ui_app->exec = strdup((context_->root_application_path.get()
656                             / manifest->package / "bin"
657                             / application.app_info.exec()).c_str());
658
659
660     if (!FillAppControl(ui_app, application.app_control))
661       return false;
662     if (!FillDataControl(ui_app, application.data_control))
663       return false;
664     if (!FillApplicationIconPaths(ui_app, application.app_icons))
665       return false;
666     if (!FillLabel(ui_app, application.label))
667       return false;
668     if (!FillImage(ui_app, application.app_images))
669       return false;
670     if (!FillMetadata(ui_app, application.meta_data))
671       return false;
672     if (!FillCategories(ui_app, application.categories))
673       return false;
674     if (!FillBackgroundCategoryInfo(ui_app, application.background_category))
675       return false;
676     if (!FillSplashScreen(ui_app, application.app_splashscreens))
677       return false;
678   }
679   return true;
680 }
681
682 bool StepParseManifest::FillWatchApplication(manifest_x* manifest) {
683   auto watch_application_list =
684         std::static_pointer_cast<const tpk::parse::WatchApplicationInfoList>(
685             parser_->GetManifestData(app_keys::kWatchApplicationKey));
686   if (!watch_application_list)
687     return true;
688
689   for (const auto& watch_application : watch_application_list->items) {
690     int package_support_mode_val = atoi(manifest->support_mode);
691     int app_support_mode_val = package_support_mode_val |
692         GetSupportModeVal(watch_application.app_info.support_mode());
693
694     application_x* watch_app =
695              static_cast<application_x*>(calloc(1, sizeof(application_x)));
696     if (!watch_app) {
697       LOG(ERROR) << "Out of memory";
698       return false;
699     }
700     watch_app->appid = strdup(watch_application.app_info.appid().c_str());
701
702     if (bf::path(watch_application.app_info.exec().c_str()).is_absolute())
703       watch_app->exec = strdup(watch_application.app_info.exec().c_str());
704     else
705       watch_app->exec = strdup(
706           (context_->root_application_path.get()
707                                / manifest->package / "bin" /
708                                watch_application.app_info.exec()).c_str());
709     watch_app->nodisplay = strdup("true");
710     watch_app->multiple = strdup("false");
711     watch_app->type = strdup(watch_application.app_info.type().c_str());
712     watch_app->taskmanage = strdup("false");
713     watch_app->hwacceleration = strdup("default");
714     watch_app->screenreader = strdup("use-system-setting");
715     watch_app->mainapp = strdup(watch_application.app_info.mainapp().c_str());
716     watch_app->recentimage = strdup("false");
717     watch_app->launchcondition = strdup("false");
718     watch_app->indicatordisplay = strdup("true");
719     watch_app->effectimage_type = strdup("image");
720     watch_app->guestmode_visibility = strdup("true");
721     watch_app->permission_type = strdup("normal");
722     watch_app->component_type = strdup("watchapp");
723     watch_app->preload = strdup("false");
724     watch_app->submode = strdup("false");
725     watch_app->process_pool = strdup("false");
726     watch_app->autorestart = strdup("false");
727     watch_app->onboot = strdup("false");
728     watch_app->support_mode =
729         strdup((std::to_string(app_support_mode_val)).c_str());
730     watch_app->ui_gadget = strdup("false");
731     watch_app->launch_mode = strdup("single");
732     watch_app->api_version = strdup(manifest->api_version);
733     watch_app->support_ambient =
734         strdup(watch_application.app_info.ambient_support().c_str());
735     watch_app->package = strdup(manifest->package);
736     if (!watch_application.app_info.setup_appid().empty())
737       watch_app->setup_appid =
738           strdup(watch_application.app_info.setup_appid().c_str());
739
740     if (!FillLabel(watch_app, watch_application.label))
741       return false;
742     if (!FillApplicationIconPaths(watch_app, watch_application.app_icons))
743       return false;
744     if (!FillMetadata(watch_app, watch_application.meta_data))
745       return false;
746     if (!FillCategories(watch_app, watch_application.categories))
747       return false;
748     if (!FillBackgroundCategoryInfo(watch_app,
749         watch_application.background_category))
750       return false;
751     manifest->application = g_list_append(manifest->application, watch_app);
752   }
753   return true;
754 }
755
756 bool StepParseManifest::FillTrustAnchorInfo(manifest_x* manifest) {
757   std::shared_ptr<const tpk::parse::TrustAnchorInfo> trust_anchor_info =
758       std::static_pointer_cast<const tpk::parse::TrustAnchorInfo>(
759           parser_->GetManifestData(app_keys::kTrustAnchorKey));
760   if (!trust_anchor_info)
761     return true;
762
763   if (trust_anchor_info->get_use_system_certs().empty()) {
764     LOG(ERROR) << "Invalid trust anchor data";
765     return false;
766   }
767
768   manifest->use_system_certs =
769       strdup(trust_anchor_info->get_use_system_certs().c_str());
770
771   return true;
772 }
773
774 bool StepParseManifest::CheckFeatures() {
775   auto feature_info =
776         std::static_pointer_cast<const tpk::parse::FeatureInfo>(
777             parser_->GetManifestData(tpk::parse::FeatureInfo::Key()));
778   if (!feature_info)
779     return true;
780
781   std::string error;
782   FeatureValidator validator(feature_info->features());
783   if (!validator.Validate(&error)) {
784     LOG(ERROR) << "Feature validation error. " << error;
785     return false;
786   }
787
788   return true;
789 }
790
791 template <typename T>
792 bool StepParseManifest::FillAppControl(application_x* app,
793                                        const T& app_control_list) {
794   if (app_control_list.empty())
795     return true;
796
797   for (const auto& control : app_control_list) {
798     appcontrol_x* app_control =
799           static_cast<appcontrol_x*>(calloc(1, sizeof(appcontrol_x)));
800     if (!app_control) {
801       LOG(ERROR) << "Out of memory";
802       return false;
803     }
804     app_control->operation = strdup(control.operation().c_str());
805     if (!control.mime().empty())
806       app_control->mime = strdup(control.mime().c_str());
807     if (!control.uri().empty())
808       app_control->uri = strdup(control.uri().c_str());
809     for (const auto& priv : control.privileges()) {
810       app_control->privileges = g_list_append(app_control->privileges,
811           strdup(priv.c_str()));
812     }
813     app->appcontrol = g_list_append(app->appcontrol, app_control);
814   }
815   return true;
816 }
817
818 template <typename T>
819 bool StepParseManifest::FillDataControl(application_x* app,
820                                 const T& data_control_list) {
821   if (data_control_list.empty())
822     return true;
823
824   for (const auto& control : data_control_list) {
825     datacontrol_x* data_control =
826           static_cast<datacontrol_x*>(calloc(1, sizeof(datacontrol_x)));
827     if (!data_control) {
828       LOG(ERROR) << "Out of memory";
829       return false;
830     }
831     data_control->access = strdup(control.access().c_str());
832     data_control->providerid = strdup(control.providerid().c_str());
833     data_control->type = strdup(control.type().c_str());
834     if (!control.trusted().empty())
835       data_control->trusted = strdup(control.trusted().c_str());
836     else
837       data_control->trusted = strdup("false");
838     for (const auto& priv : control.privileges())
839       data_control->privileges = g_list_append(data_control->privileges,
840           strdup(priv.c_str()));
841
842     app->datacontrol = g_list_append(app->datacontrol, data_control);
843   }
844   return true;
845 }
846
847 template <typename T>
848 bool StepParseManifest::FillApplicationIconPaths(application_x* app,
849                                          const T& icons_info) {
850   for (auto& application_icon : icons_info.icons()) {
851     icon_x* icon = reinterpret_cast<icon_x*>(calloc(1, sizeof(icon_x)));
852     if (!icon) {
853       LOG(ERROR) << "Out of memory";
854       return false;
855     }
856     bf::path text;
857     if (bf::path(application_icon.path()).is_absolute()) {
858       text = application_icon.path();
859     } else {
860       text = context_->root_application_path.get()
861           / context_->pkgid.get() / "shared" / "res" / application_icon.path();
862     }
863     // NOTE: name is an attribute, but the xml writer uses it as text.
864     // This must be fixed in whole app-installer modules, including wgt.
865     // Current implementation is just for compatibility.
866     icon->text = strdup(text.c_str());
867     if (application_icon.lang().empty())
868       icon->lang = strdup(DEFAULT_LOCALE);
869     else
870       icon->lang = strdup(application_icon.lang().c_str());
871
872     if (!application_icon.dpi().empty())
873       icon->dpi = strdup(application_icon.dpi().c_str());
874     app->icon = g_list_append(app->icon, icon);
875   }
876   return true;
877 }
878
879 template <typename T>
880 bool StepParseManifest::FillLabel(application_x* app, const T& label_list) {
881   if (label_list.empty())
882     return true;
883
884   for (const auto& control : label_list) {
885     label_x* label =
886           static_cast<label_x*>(calloc(1, sizeof(label_x)));
887     if (!label) {
888       LOG(ERROR) << "Out of memory";
889       return false;
890     }
891     // NOTE: name is an attribute, but the xml writer uses it as text.
892     // This must be fixed in whole app-installer modules, including wgt.
893     // Current implementation is just for compatibility.
894     label->text = strdup(control.text().c_str());
895     label->name = strdup(control.name().c_str());
896     label->lang = !control.xml_lang().empty() ?
897         strdup(control.xml_lang().c_str()) : strdup(DEFAULT_LOCALE);
898     app->label = g_list_append(app->label, label);
899   }
900   return true;
901 }
902
903 template <typename T>
904 bool StepParseManifest::FillMetadata(application_x* app,
905                                      const T& meta_data_list) {
906   if (meta_data_list.empty())
907     return true;
908
909   for (auto& meta : meta_data_list) {
910     metadata_x* metadata =
911         static_cast<metadata_x*>(calloc(1, sizeof(metadata_x)));
912     if (!metadata) {
913       LOG(ERROR) << "Out of memory";
914       return false;
915     }
916     metadata->key = strdup(meta.key().c_str());
917     metadata->value = strdup(meta.val().c_str());
918     app->metadata = g_list_append(app->metadata, metadata);
919
920     GetLegacySplashScreenFromMetadata(app, meta.key(), meta.val());
921   }
922   return true;
923 }
924
925 template <typename T>
926 bool StepParseManifest::FillCategories(application_x* manifest,
927                                      const T& categories) {
928   for (auto& category : categories) {
929     manifest->category = g_list_append(manifest->category,
930                                        strdup(category.c_str()));
931   }
932   return true;
933 }
934
935 void StepParseManifest::AppendSplashScreen(application_x* app,
936     const std::string& src, const std::string& type, const std::string& dpi,
937     const std::string& orientation, const std::string& indicatordisplay,
938     const std::string& operation, const std::string& color_depth) {
939   splashscreen_x* splashscreen =
940       static_cast<splashscreen_x*>(calloc(1, sizeof(splashscreen_x)));
941   if (!splashscreen) {
942     LOG(ERROR) << "Out of memory";
943     return;
944   }
945   if (bf::path(src).is_absolute()) {
946     splashscreen->src = strdup(src.c_str());
947   } else {
948     bf::path full_path = context_->pkg_path.get() / src;
949     splashscreen->src = strdup(full_path.string().c_str());
950   }
951   if (src.substr(src.find_last_of(".") + 1) == "edj")
952     splashscreen->type = strdup("edj");
953   else if (type == "edj")
954     splashscreen->type = strdup("edj");
955   else
956     splashscreen->type = strdup("img");
957   if (!dpi.empty())
958     splashscreen->dpi = strdup(dpi.c_str());
959   splashscreen->orientation = strdup(orientation.c_str());
960   if (!indicatordisplay.empty())
961     splashscreen->indicatordisplay = strdup(indicatordisplay.c_str());
962   else
963     splashscreen->indicatordisplay = strdup("true");
964   if (operation == "launch_effect")
965     splashscreen->operation = strdup("launch-effect");
966   else if (!operation.empty())
967     splashscreen->operation = strdup(operation.c_str());
968   else
969     splashscreen->operation = strdup("launch-effect");
970   if (!color_depth.empty())
971     splashscreen->color_depth = strdup(color_depth.c_str());
972   else
973     splashscreen->color_depth = strdup("24");
974   app->splashscreens = g_list_append(app->splashscreens, splashscreen);
975 }
976
977 template <typename T>
978 bool StepParseManifest::FillSplashScreen(application_x* app,
979                                      const T& splashscreens_info) {
980   for (auto& splash_screen : splashscreens_info.splashscreens()) {
981     std::string src;
982     if (context_->is_readonly_package.get())
983       src = splash_screen.src();
984     else
985       src = bf::path(context_->root_application_path.get()
986         / app->package / "shared" / "res" / splash_screen.src()).string();
987
988     AppendSplashScreen(app, src, splash_screen.type(), splash_screen.dpi(),
989         splash_screen.orientation(), splash_screen.indicatordisplay(),
990         splash_screen.operation(), splash_screen.colordepth());
991   }
992   return true;
993 }
994
995 void StepParseManifest::GetLegacySplashScreenFromMetadata(application_x* app,
996     const std::string& key, const std::string& val) {
997   std::string operation;
998   if (key.find(kOperationEffectKey) != std::string::npos) {
999     boost::char_separator<char> sep("=");
1000     boost::tokenizer<boost::char_separator<char>> tokens(key, sep);
1001     auto iter = tokens.begin();
1002     iter++;
1003     operation = *iter;
1004   } else if (key.find(kLaunchEffectKey) != std::string::npos) {
1005     operation = std::string("launch-effect");
1006   } else {
1007     // not a metadata splashscreen
1008     return;
1009   }
1010
1011   boost::char_separator<char> sep("=|");
1012   boost::tokenizer<boost::char_separator<char>> tokens(val, sep);
1013   auto iter = tokens.begin();
1014   std::string portrait_src;
1015   std::string landscape_src;
1016   std::string indicatordisplay;
1017   while (iter != tokens.end()) {
1018     if (!(*iter).compare(kPortraitEffectImageValue)) {
1019       iter++;
1020       portrait_src = *iter;
1021     } else if (!(*iter).compare(kLandscapeEffectImageValue)) {
1022       iter++;
1023       landscape_src = *iter;
1024     } else if (!(*iter).compare(kIndicatorDisplayValue)) {
1025       iter++;
1026       indicatordisplay = *iter;
1027     }
1028     iter++;
1029   }
1030   if (!portrait_src.empty())
1031     AppendSplashScreen(app, portrait_src, {}, {}, kPortraitOrientation,
1032         indicatordisplay, operation, {});
1033   if (!landscape_src.empty())
1034     AppendSplashScreen(app, landscape_src, {}, {}, kLandscapeOrientation,
1035         indicatordisplay, operation, {});
1036 }
1037
1038 bool StepParseManifest::FillImage(application_x* app,
1039                           const tpk::parse::ApplicationImagesInfo& image_list) {
1040   for (auto& app_image : image_list.images) {
1041     image_x* image =
1042         static_cast<image_x*>(calloc(1, sizeof(image_x)));
1043     if (!image) {
1044       LOG(ERROR) << "Out of memory";
1045       return false;
1046     }
1047     const std::string& lang = app_image.lang();
1048     if (!lang.empty())
1049       image->lang = strdup(lang.c_str());
1050     else
1051       image->lang = strdup(DEFAULT_LOCALE);
1052     if (!app_image.section().empty())
1053       image->section = strdup(app_image.section().c_str());
1054     app->image = g_list_append(app->image, image);
1055   }
1056   return true;
1057 }
1058
1059 template <typename T>
1060 bool StepParseManifest::FillBackgroundCategoryInfo(application_x* app,
1061     const T& background_category_data_list) {
1062   for (const auto& background_category : background_category_data_list) {
1063     app->background_category = g_list_append(
1064         app->background_category, strdup(background_category.value().c_str()));
1065   }
1066
1067   return true;
1068 }
1069
1070 bool StepParseManifest::FillExtraInfo(manifest_x* manifest) {
1071   if (manifest_location_ == ManifestLocation::INSTALLED) {
1072     // recovery of tep value for installed package
1073     PkgQueryInterface pkg_query(context_->pkgid.get(), context_->uid.get());
1074     std::string old_tep = pkg_query.TepPath();
1075     if (!old_tep.empty())
1076       manifest->tep_name = strdup(old_tep.c_str());
1077
1078     // recovery of zip mount file for installed package
1079     std::string zip_mount_file = pkg_query.ZipMountFile();
1080     if (!zip_mount_file.empty())
1081       manifest->zip_mount_file = strdup(zip_mount_file.c_str());
1082   }
1083
1084   // in case of hybrid package, main app is already set by wgt-backend
1085   application_x* mainapp = nullptr;
1086   if (!context_->cross_app_rules.get()) {
1087     // find mainapp
1088     for (const auto& app : GListRange<application_x*>(manifest->application)) {
1089       if (!strcmp(app->mainapp, "true")) {
1090         mainapp = app;
1091         break;
1092       }
1093     }
1094     if (mainapp == nullptr)
1095       mainapp = reinterpret_cast<application_x*>(
1096           g_list_first(manifest->application)->data);
1097     free(mainapp->mainapp);
1098     mainapp->mainapp = strdup("true");
1099     manifest->mainapp_id = strdup(mainapp->appid);
1100   }
1101
1102   // mark mainapp=false at other apps
1103   for (auto& app : GListRange<application_x*>(manifest->application)) {
1104     if (app == mainapp)
1105       continue;
1106     free(app->mainapp);
1107     app->mainapp = strdup("false");
1108   }
1109   return true;
1110 }
1111
1112 bool StepParseManifest::FillManifestX(manifest_x* manifest) {
1113   if (!FillPackageInfo(manifest))
1114     return false;
1115   if (!FillInstallationInfo(manifest))
1116     return false;
1117   if (!FillUIApplication(manifest))
1118     return false;
1119   if (!FillServiceApplication(manifest))
1120     return false;
1121   if (!FillWidgetApplication(manifest))
1122     return false;
1123   if (!FillWatchApplication(manifest))
1124     return false;
1125   if (!FillPrivileges(manifest))
1126     return false;
1127   if (!FillProvidesAppDefinedPrivileges(manifest))
1128     return false;
1129   if (!FillAuthorInfo(manifest))
1130     return false;
1131   if (!FillDescriptionInfo(manifest))
1132     return false;
1133   if (!FillExtraInfo(manifest))
1134     return false;
1135   if (!FillTrustAnchorInfo(manifest))
1136     return false;
1137   return true;
1138 }
1139
1140 Step::Status StepParseManifest::process() {
1141   if (context_->force_clean_from_db.get())
1142     return Step::Status::OK;
1143   if (!LocateConfigFile()) {
1144     // continue if this is recovery, manifest file may never been created
1145     if (manifest_location_ == ManifestLocation::RECOVERY) {
1146       LOG(DEBUG) << "Manifest for recovery not found";
1147       return Step::Status::OK;
1148     }
1149     LOG(ERROR) << "No manifest file exists";
1150     return Step::Status::MANIFEST_NOT_FOUND;
1151   }
1152   parser_.reset(new tpk::parse::TPKConfigParser());
1153   if (!parser_->ParseManifest(path_)) {
1154     if (manifest_location_ == ManifestLocation::RECOVERY) {
1155       LOG(DEBUG) << "Manifest for recovery is invalid";
1156       bf::remove(path_);
1157       return Step::Status::OK;
1158     }
1159     LOG(ERROR) << "[Parse] Parse failed. " <<  parser_->GetErrorMessage();
1160     return Step::Status::PARSE_ERROR;
1161   }
1162
1163   // Copy data from ManifestData to InstallerContext
1164   std::shared_ptr<const tpk::parse::PackageInfo> info =
1165       std::static_pointer_cast<const tpk::parse::PackageInfo>(
1166           parser_->GetManifestData(app_keys::kManifestKey));
1167
1168   context_->pkgid.set(info->package());
1169   context_->pkg_path.set(
1170       context_->root_application_path.get() / context_->pkgid.get());
1171
1172   manifest_x* manifest =
1173       static_cast<manifest_x*>(calloc(1, sizeof(manifest_x)));
1174   if (!manifest) {
1175     LOG(ERROR) << "Out of memory";
1176     return Step::Status::ERROR;
1177   }
1178
1179   if (!FillManifestX(const_cast<manifest_x*>(manifest))) {
1180     LOG(ERROR) << "[Parse] Storing manifest_x failed. "
1181                <<  parser_->GetErrorMessage();
1182     pkgmgr_parser_free_manifest_xml(manifest);
1183     return Step::Status::PARSE_ERROR;
1184   }
1185
1186   // write pkgid for recovery file
1187   if (context_->recovery_info.get().recovery_file) {
1188     context_->recovery_info.get().recovery_file->set_pkgid(manifest->package);
1189     context_->recovery_info.get().recovery_file->WriteAndCommitFileContent();
1190   }
1191
1192   LOG(DEBUG) << "Parsed package id: " << info->package();
1193
1194   switch (store_location_) {
1195     case StoreLocation::NORMAL:
1196       context_->manifest_data.set(manifest);
1197       break;
1198     case StoreLocation::BACKUP:
1199       context_->old_manifest_data.set(manifest);
1200       break;
1201     default:
1202       LOG(ERROR) << "Unknown store location for parsed data";
1203       return Step::Status::ERROR;
1204   }
1205   return Step::Status::OK;
1206 }
1207
1208 }  // namespace configuration
1209 }  // namespace common_installer