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