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