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