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