215e69e10ffc7bb949fab742ec1781fb9df2883d
[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   }
376   return true;
377 }
378
379 bool StepParseManifest::FillServiceApplication(manifest_x* manifest) {
380   auto service_application_list =
381       std::static_pointer_cast<const tpk::parse::ServiceApplicationInfoList>(
382           parser_->GetManifestData(app_keys::kServiceApplicationKey));
383   if (!service_application_list)
384     return true;
385
386   for (const auto& application : service_application_list->items) {
387     // if there is no app yet, set this app as mainapp
388     bool main_app = manifest->application == nullptr;
389
390     application_x* service_app =
391         static_cast<application_x*>(calloc(1, sizeof(application_x)));
392     service_app->appid = strdup(application.app_info.appid().c_str());
393     service_app->multiple = strdup(application.app_info.multiple().c_str());
394     service_app->taskmanage = strdup(application.app_info.taskmanage().c_str());
395     service_app->autorestart =
396         strdup(application.app_info.auto_restart().c_str());
397     service_app->onboot = strdup(application.app_info.on_boot().c_str());
398     service_app->type = strdup(application.app_info.type().c_str());
399     service_app->process_pool =
400         strdup(application.app_info.process_pool().c_str());
401     service_app->component_type = strdup("svcapp");
402     service_app->mainapp = main_app ? strdup("true") : strdup("false");
403     service_app->enabled = strdup("true");
404     service_app->nodisplay = strdup("true");
405     service_app->hwacceleration = strdup("default");
406     service_app->screenreader = strdup("use-system-setting");
407     service_app->recentimage = strdup("false");
408     service_app->launchcondition = strdup("false");
409     service_app->indicatordisplay = strdup("true");
410     service_app->effectimage_type = strdup("image");
411     service_app->guestmode_visibility = strdup("true");
412     service_app->permission_type = strdup("normal");
413     service_app->submode = strdup("false");
414     service_app->process_pool = strdup("false");
415     service_app->ambient_support = strdup("false");
416     service_app->package = strdup(manifest->package);
417     service_app->support_disable = strdup(manifest->support_disable);
418     manifest->application = g_list_append(manifest->application, service_app);
419     if (bf::path(application.app_info.exec().c_str()).is_absolute())
420       service_app->exec = strdup(application.app_info.exec().c_str());
421     else
422       service_app->exec = strdup((context_->root_application_path.get()
423                             / manifest->package / "bin"
424                             / application.app_info.exec()).c_str());
425
426     if (!FillAppControl(service_app,  application.app_control))
427       return false;
428     if (!FillDataControl(service_app, application.data_control))
429       return false;
430     if (!FillApplicationIconPaths(service_app, application.app_icons))
431       return false;
432     if (!FillLabel(service_app, application.label))
433       return false;
434     if (!FillMetadata(service_app, application.meta_data))
435       return false;
436     if (!FillCategories(service_app, application.categories))
437       return false;
438     if (!FillBackgroundCategoryInfo(service_app,
439         application.background_category))
440       return false;
441   }
442   return true;
443 }
444
445 bool StepParseManifest::FillUIApplication(manifest_x* manifest) {
446   std::shared_ptr<const tpk::parse::UIApplicationInfoList> ui_application_list =
447       std::static_pointer_cast<const tpk::parse::UIApplicationInfoList>(
448           parser_->GetManifestData(app_keys::kUIApplicationKey));
449   if (!ui_application_list)
450     return true;
451
452   for (const auto& application : ui_application_list->items) {
453     // if there is no app yet, set this app as mainapp
454     bool main_app = manifest->application == nullptr;
455
456     application_x* ui_app =
457         static_cast<application_x*>(calloc(1, sizeof(application_x)));
458     ui_app->appid = strdup(application.app_info.appid().c_str());
459     ui_app->launch_mode = strdup(application.app_info.launch_mode().c_str());
460     ui_app->multiple = strdup(application.app_info.multiple().c_str());
461     ui_app->nodisplay = strdup(application.app_info.nodisplay().c_str());
462     ui_app->taskmanage = strdup(application.app_info.taskmanage().c_str());
463     ui_app->type = strdup(application.app_info.type().c_str());
464     ui_app->ui_gadget = strdup(application.app_info.uigadget().c_str());
465     ui_app->process_pool = strdup(application.app_info.process_pool().c_str());
466     ui_app->submode = strdup(application.app_info.submode().c_str());
467     if (!application.app_info.indicator_display().empty())
468       ui_app->indicatordisplay =
469           strdup(application.app_info.indicator_display().c_str());
470     if (!application.app_info.effectimage_type().empty())
471       ui_app->effectimage_type =
472           strdup(application.app_info.effectimage_type().c_str());
473     if (!application.app_info.portrait_image().empty())
474       ui_app->portraitimg =
475           strdup(application.app_info.portrait_image().c_str());
476     if (!application.app_info.landscape_image().empty())
477       ui_app->landscapeimg =
478           strdup(application.app_info.landscape_image().c_str());
479     ui_app->submode_mainid =
480         strdup(application.app_info.submode_mainid().c_str());
481     ui_app->hwacceleration =
482         strdup(application.app_info.hwacceleration().c_str());
483     ui_app->onboot = strdup("false");
484     ui_app->autorestart = strdup("false");
485     ui_app->component_type = strdup("uiapp");
486     ui_app->mainapp = main_app ? strdup("true") : strdup("false");
487     ui_app->enabled = strdup("true");
488     ui_app->screenreader = strdup("use-system-setting");
489     ui_app->recentimage = strdup("false");
490     ui_app->launchcondition = strdup("false");
491     ui_app->guestmode_visibility = strdup("true");
492     ui_app->permission_type = strdup("normal");
493     ui_app->ambient_support = strdup("false");
494     ui_app->package = strdup(manifest->package);
495     ui_app->support_disable = strdup(manifest->support_disable);
496     ui_app->splash_screen_display =
497         strdup(application.app_info.splash_screen_display().c_str());
498     manifest->application = g_list_append(manifest->application, ui_app);
499     if (bf::path(application.app_info.exec().c_str()).is_absolute())
500       ui_app->exec = strdup(application.app_info.exec().c_str());
501     else
502       ui_app->exec = strdup((context_->root_application_path.get()
503                             / manifest->package / "bin"
504                             / application.app_info.exec()).c_str());
505
506
507     if (!FillAppControl(ui_app, application.app_control))
508       return false;
509     if (!FillDataControl(ui_app, application.data_control))
510       return false;
511     if (!FillApplicationIconPaths(ui_app, application.app_icons))
512       return false;
513     if (!FillLabel(ui_app, application.label))
514       return false;
515     if (!FillImage(ui_app, application.app_images))
516       return false;
517     if (!FillMetadata(ui_app, application.meta_data))
518       return false;
519     if (!FillCategories(ui_app, application.categories))
520       return false;
521     if (!FillBackgroundCategoryInfo(ui_app, application.background_category))
522       return false;
523     if (!FillSplashScreen(ui_app, application.app_splashscreens))
524       return false;
525   }
526   return true;
527 }
528
529 bool StepParseManifest::FillWatchApplication(manifest_x* manifest) {
530   auto watch_application_list =
531         std::static_pointer_cast<const tpk::parse::WatchApplicationInfoList>(
532             parser_->GetManifestData(app_keys::kWatchApplicationKey));
533   if (!watch_application_list)
534     return true;
535
536   for (const auto& watch_application : watch_application_list->items) {
537     bool main_app = manifest->application == nullptr;
538
539     application_x* watch_app =
540              static_cast<application_x*>(calloc(1, sizeof(application_x)));
541     watch_app->appid = strdup(watch_application.app_info.appid().c_str());
542
543     if (bf::path(watch_application.app_info.exec().c_str()).is_absolute())
544       watch_app->exec = strdup(watch_application.app_info.exec().c_str());
545     else
546       watch_app->exec = strdup(
547           (context_->root_application_path.get()
548                                / manifest->package / "bin" /
549                                watch_application.app_info.exec()).c_str());
550     watch_app->nodisplay = strdup("true");
551     watch_app->multiple = strdup("false");
552     watch_app->type = strdup(watch_application.app_info.type().c_str());
553     watch_app->taskmanage = strdup("false");
554     watch_app->enabled = strdup("true");
555     watch_app->hwacceleration = strdup("default");
556     watch_app->screenreader = strdup("use-system-setting");
557     watch_app->mainapp = main_app ? strdup("true") : strdup("false");
558     watch_app->recentimage = strdup("false");
559     watch_app->launchcondition = strdup("false");
560     watch_app->indicatordisplay = strdup("true");
561     watch_app->effectimage_type = strdup("image");
562     watch_app->guestmode_visibility = strdup("true");
563     watch_app->permission_type = strdup("normal");
564     watch_app->component_type = strdup("watchapp");
565     watch_app->preload = strdup("false");
566     watch_app->submode = strdup("false");
567     watch_app->process_pool = strdup("false");
568     watch_app->autorestart = strdup("false");
569     watch_app->onboot = strdup("false");
570     watch_app->support_disable = strdup(manifest->support_disable);
571     watch_app->ui_gadget = strdup("false");
572     watch_app->launch_mode = strdup("single");
573     watch_app->ambient_support =
574         strdup(watch_application.app_info.ambient_support().c_str());
575     watch_app->package = strdup(manifest->package);
576     if (!FillLabel(watch_app, watch_application.label))
577       return false;
578     if (!FillApplicationIconPaths(watch_app, watch_application.app_icons))
579       return false;
580     if (!FillMetadata(watch_app, watch_application.meta_data))
581       return false;
582     if (!FillCategories(watch_app, watch_application.categories))
583       return false;
584     if (!FillBackgroundCategoryInfo(watch_app,
585         watch_application.background_category))
586       return false;
587     manifest->application = g_list_append(manifest->application, watch_app);
588   }
589   return true;
590 }
591
592 bool StepParseManifest::CheckFeatures() {
593   auto feature_info =
594         std::static_pointer_cast<const tpk::parse::FeatureInfo>(
595             parser_->GetManifestData(tpk::parse::FeatureInfo::Key()));
596   if (!feature_info)
597     return true;
598
599   std::string error;
600   FeatureValidator validator(feature_info->features());
601   if (!validator.Validate(&error)) {
602     LOG(ERROR) << "Feature validation error. " << error;
603     return false;
604   }
605
606   return true;
607 }
608
609 template <typename T>
610 bool StepParseManifest::FillAppControl(application_x* app,
611                                        const T& app_control_list) {
612   if (app_control_list.empty())
613     return true;
614
615   for (const auto& control : app_control_list) {
616     appcontrol_x* app_control =
617           static_cast<appcontrol_x*>(calloc(1, sizeof(appcontrol_x)));
618     app_control->operation = strdup(control.operation().c_str());
619     if (!control.mime().empty())
620       app_control->mime = strdup(control.mime().c_str());
621     if (!control.uri().empty())
622       app_control->uri = strdup(control.uri().c_str());
623     app->appcontrol = g_list_append(app->appcontrol, app_control);
624   }
625   return true;
626 }
627
628 template <typename T>
629 bool StepParseManifest::FillDataControl(application_x* app,
630                                 const T& data_control_list) {
631   if (data_control_list.empty())
632     return true;
633
634   for (const auto& control : data_control_list) {
635     datacontrol_x* data_control =
636           static_cast<datacontrol_x*>(calloc(1, sizeof(datacontrol_x)));
637     data_control->access = strdup(control.access().c_str());
638     data_control->providerid = strdup(control.providerid().c_str());
639     data_control->type = strdup(control.type().c_str());
640     app->datacontrol = g_list_append(app->datacontrol, data_control);
641   }
642   return true;
643 }
644
645 template <typename T>
646 bool StepParseManifest::FillApplicationIconPaths(application_x* app,
647                                          const T& icons_info) {
648   for (auto& application_icon : icons_info.icons()) {
649     icon_x* icon = reinterpret_cast<icon_x*> (calloc(1, sizeof(icon_x)));
650     bf::path text;
651     if (bf::path(application_icon.path()).is_absolute()) {
652       text = application_icon.path();
653     } else {
654       text = context_->root_application_path.get()
655           / context_->pkgid.get() / "shared" / "res" / application_icon.path();
656     }
657     // NOTE: name is an attribute, but the xml writer uses it as text.
658     // This must be fixed in whole app-installer modules, including wgt.
659     // Current implementation is just for compatibility.
660     icon->text = strdup(text.c_str());
661     if (application_icon.lang().empty())
662       icon->lang = strdup(DEFAULT_LOCALE);
663     else
664       icon->lang = strdup(application_icon.lang().c_str());
665
666     if (!application_icon.dpi().empty())
667       icon->dpi = strdup(application_icon.dpi().c_str());
668     app->icon = g_list_append(app->icon, icon);
669   }
670   return true;
671 }
672
673 template <typename T>
674 bool StepParseManifest::FillLabel(application_x* app, const T& label_list) {
675   if (label_list.empty())
676     return true;
677
678   for (const auto& control : label_list) {
679     label_x* label =
680           static_cast<label_x*>(calloc(1, sizeof(label_x)));
681     // NOTE: name is an attribute, but the xml writer uses it as text.
682     // This must be fixed in whole app-installer modules, including wgt.
683     // Current implementation is just for compatibility.
684     label->text = strdup(control.text().c_str());
685     label->name = strdup(control.name().c_str());
686     label->lang = !control.xml_lang().empty() ?
687         strdup(control.xml_lang().c_str()) : strdup(DEFAULT_LOCALE);
688     app->label = g_list_append(app->label, label);
689   }
690   return true;
691 }
692
693 template <typename T>
694 bool StepParseManifest::FillMetadata(application_x* app,
695                                      const T& meta_data_list) {
696   if (meta_data_list.empty())
697     return true;
698
699   for (auto& meta : meta_data_list) {
700     metadata_x* metadata =
701         static_cast<metadata_x*>(calloc(1, sizeof(metadata_x)));
702     metadata->key = strdup(meta.key().c_str());
703     metadata->value = strdup(meta.val().c_str());
704     app->metadata = g_list_append(app->metadata, metadata);
705   }
706   return true;
707 }
708
709 template <typename T>
710 bool StepParseManifest::FillCategories(application_x* manifest,
711                                      const T& categories) {
712   for (auto& category : categories) {
713     manifest->category = g_list_append(manifest->category,
714                                        strdup(category.c_str()));
715   }
716   return true;
717 }
718
719 template <typename T>
720 bool StepParseManifest::FillSplashScreen(application_x* app,
721                                      const T& splashscreens_info) {
722   for (auto& splash_screen : splashscreens_info.splashscreens()) {
723     splashscreen_x* splashscreen =
724         static_cast<splashscreen_x*>(calloc(1, sizeof(splashscreen_x)));
725     if (context_->is_preload_request.get())
726       splashscreen->src = strdup(splash_screen.src().c_str());
727     else
728       splashscreen->src = strdup((context_->root_application_path.get()
729         / app->package / "shared" / "res" / splash_screen.src()).c_str());
730
731     splashscreen->type = strdup(splash_screen.type().c_str());
732     if (!splash_screen.dpi().empty())
733       splashscreen->dpi = strdup(splash_screen.dpi().c_str());
734     splashscreen->orientation = strdup(splash_screen.orientation().c_str());
735     if (!splash_screen.indicatordisplay().empty())
736       splashscreen->indicatordisplay = strdup(
737           splash_screen.indicatordisplay().c_str());
738     else
739       splashscreen->indicatordisplay = strdup("true");
740
741     if (!splash_screen.operation().empty())
742       splashscreen->operation = strdup(splash_screen.operation().c_str());
743     else
744       splashscreen->operation = strdup("launch-effect");
745
746     if (!splash_screen.colordepth().empty())
747       splashscreen->color_depth = strdup(splash_screen.colordepth().c_str());
748     else
749       splashscreen->color_depth = strdup("24");
750
751     app->splashscreens = g_list_append(app->splashscreens, splashscreen);
752   }
753   return true;
754 }
755
756 bool StepParseManifest::FillImage(application_x* app,
757                           const tpk::parse::ApplicationImagesInfo& image_list) {
758   for (auto& app_image : image_list.images) {
759     image_x* image =
760         static_cast<image_x*>(calloc(1, sizeof(image_x)));
761     const std::string& lang = app_image.lang();
762     if (!lang.empty())
763       image->lang = strdup(lang.c_str());
764     else
765       image->lang = strdup(DEFAULT_LOCALE);
766     if (!app_image.section().empty())
767       image->section = strdup(app_image.section().c_str());
768     app->image = g_list_append(app->image, image);
769   }
770   return true;
771 }
772
773 template <typename T>
774 bool StepParseManifest::FillBackgroundCategoryInfo(application_x* app,
775     const T& background_category_data_list) {
776   for (const auto& background_category : background_category_data_list) {
777     app->background_category = g_list_append(
778         app->background_category, strdup(background_category.value().c_str()));
779   }
780
781   return true;
782 }
783
784 bool StepParseManifest::FillManifestX(manifest_x* manifest) {
785   if (!FillPackageInfo(manifest))
786     return false;
787   if (!FillInstallationInfo(manifest))
788     return false;
789   if (!FillUIApplication(manifest))
790     return false;
791   if (!FillServiceApplication(manifest))
792     return false;
793   if (!FillWidgetApplication(manifest))
794     return false;
795   if (!FillWatchApplication(manifest))
796     return false;
797   if (!FillPrivileges(manifest))
798     return false;
799   if (!FillAuthorInfo(manifest))
800     return false;
801   if (!FillDescriptionInfo(manifest))
802     return false;
803   return true;
804 }
805
806 Step::Status StepParseManifest::process() {
807   if (!LocateConfigFile()) {
808     // continue if this is recovery, manifest file may never been created
809     if (manifest_location_ == ManifestLocation::RECOVERY) {
810       LOG(DEBUG) << "Manifest for recovery not found";
811       return Step::Status::OK;
812     }
813     LOG(ERROR) << "No manifest file exists";
814     return Step::Status::MANIFEST_NOT_FOUND;
815   }
816   parser_.reset(new tpk::parse::TPKConfigParser());
817   if (!parser_->ParseManifest(path_)) {
818     LOG(ERROR) << "[Parse] Parse failed. " <<  parser_->GetErrorMessage();
819     return Step::Status::PARSE_ERROR;
820   }
821
822   // Copy data from ManifestData to InstallerContext
823   std::shared_ptr<const tpk::parse::PackageInfo> info =
824       std::static_pointer_cast<const tpk::parse::PackageInfo>(
825           parser_->GetManifestData(app_keys::kManifestKey));
826
827   context_->pkgid.set(info->package());
828   context_->pkg_path.set(
829       context_->root_application_path.get() / context_->pkgid.get());
830
831   manifest_x* manifest =
832       static_cast<manifest_x*>(calloc(1, sizeof(manifest_x)));
833
834   if (!FillManifestX(const_cast<manifest_x*>(manifest))) {
835     LOG(ERROR) << "[Parse] Storing manifest_x failed. "
836                <<  parser_->GetErrorMessage();
837     return Step::Status::PARSE_ERROR;
838   }
839
840   if (manifest_location_ == ManifestLocation::INSTALLED) {
841     // recovery of tep value for installed package
842     std::string old_tep =
843         QueryTepPath(context_->pkgid.get(), context_->uid.get());
844     if (!old_tep.empty())
845       manifest->tep_name = strdup(old_tep.c_str());
846
847     // recovery of zip mount file for installed package
848     std::string zip_mount_file =
849         QueryZipMountFile(context_->pkgid.get(), context_->uid.get());
850     if (!zip_mount_file.empty())
851       manifest->zip_mount_file = strdup(zip_mount_file.c_str());
852   }
853
854   // write pkgid for recovery file
855   if (context_->recovery_info.get().recovery_file) {
856     context_->recovery_info.get().recovery_file->set_pkgid(manifest->package);
857     context_->recovery_info.get().recovery_file->WriteAndCommitFileContent();
858   }
859
860   LOG(DEBUG) << "Parsed package id: " << info->package();
861
862   switch (store_location_) {
863     case StoreLocation::NORMAL:
864       context_->manifest_data.set(manifest);
865       break;
866     case StoreLocation::BACKUP:
867       context_->old_manifest_data.set(manifest);
868       break;
869     default:
870       LOG(ERROR) << "Unknown store location for parsed data";
871       return Step::Status::ERROR;
872   }
873   return Step::Status::OK;
874 }
875
876 }  // namespace configuration
877 }  // namespace common_installer