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