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