1637c546185131f62d78b2bb69decd675e02e7fa
[platform/core/appfw/wgt-backend.git] / src / wgt / step / configuration / step_parse.cc
1 /* 2014, Copyright © Intel Coporation, license APACHE-2.0, see LICENSE file */
2 // Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3 // Use of this source code is governed by a apache 2.0 license that can be
4 // found in the LICENSE file.
5
6 #include "wgt/step/configuration/step_parse.h"
7
8 #include <boost/filesystem/path.hpp>
9
10 #include <common/app_installer.h>
11 #include <common/paths.h>
12 #include <common/installer_context.h>
13 #include <common/pkgmgr_query.h>
14 #include <common/privileges.h>
15 #include <common/step/step.h>
16 #include <common/utils/glist_range.h>
17 #include <manifest_parser/utils/version_number.h>
18 #include <wgt_manifest_handlers/account_handler.h>
19 #include <wgt_manifest_handlers/app_control_handler.h>
20 #include <wgt_manifest_handlers/appdefined_privilege_handler.h>
21 #include <wgt_manifest_handlers/application_icons_handler.h>
22 #include <wgt_manifest_handlers/application_manifest_constants.h>
23 #include <wgt_manifest_handlers/background_category_handler.h>
24 #include <wgt_manifest_handlers/category_handler.h>
25 #include <wgt_manifest_handlers/content_handler.h>
26 #include <wgt_manifest_handlers/ime_handler.h>
27 #include <wgt_manifest_handlers/metadata_handler.h>
28 #include <wgt_manifest_handlers/provides_appdefined_privilege_handler.h>
29 #include <wgt_manifest_handlers/service_handler.h>
30 #include <wgt_manifest_handlers/setting_handler.h>
31 #include <wgt_manifest_handlers/tizen_application_handler.h>
32 #include <wgt_manifest_handlers/widget_handler.h>
33 #include <wgt_manifest_handlers/w3c_pc_utils.h>
34
35 #include <pkgmgr/pkgmgr_parser.h>
36 #include <pkgmgrinfo_basic.h>
37
38 #include <string.h>
39
40 #include <chrono>
41 #include <cstdio>
42 #include <cstdlib>
43 #include <memory>
44 #include <set>
45 #include <string>
46 #include <vector>
47 #include <utility>
48
49 #include "wgt/wgt_backend_data.h"
50
51 namespace bf = boost::filesystem;
52 namespace ci = common_installer;
53
54 namespace {
55
56 const char kCategoryWearableClock[] =
57     "http://tizen.org/category/wearable_clock";
58 const char kCategoryWatchClock[] = "com.samsung.wmanager.WATCH_CLOCK";
59
60 const char kManifestVersion[] = "1.0.0";
61 const char kTizenPackageXmlNamespace[] = "http://tizen.org/ns/packages";
62 const char kImeCategoryName[] = "http://tizen.org/category/ime";
63 const char kDownloadableFontCategoryName[] =
64     "http://tizen.org/category/downloadable_font";
65 const char kTTSCategoryName[] = "http://tizen.org/category/tts";
66
67 const char kResWgt[] = "res/wgt";
68 const char kConfigFileName[] = "config.xml";
69
70 void FreeMetadataList(gpointer data) {
71   metadata_x* metadata = reinterpret_cast<metadata_x*>(data);
72   if (metadata) {
73     if (metadata->key)
74       free(const_cast<char*>(metadata->key));
75     if (metadata->value)
76       free(const_cast<char*>(metadata->value));
77     free(metadata);
78   }
79 }
80
81 GList* GenerateMetadataListX(const wgt::parse::MetaDataInfo& meta_info) {
82   GList* list = nullptr;
83   for (auto& meta : meta_info.metadata()) {
84     metadata_x* new_meta =
85         static_cast<metadata_x*>(calloc(1, sizeof(metadata_x)));
86     if (!new_meta) {
87       LOG(ERROR) << "Out of memory";
88       g_list_free_full(list, &FreeMetadataList);
89       return nullptr;
90     }
91     new_meta->key = strdup(meta.first.c_str());
92     if (!meta.second.empty())
93       new_meta->value = strdup(meta.second.c_str());
94     list = g_list_append(list, new_meta);
95   }
96   return list;
97 }
98
99 void AppendWidgetMetadata(GList** metadatas,
100     const std::vector<std::pair<std::string, std::string>> metadata) {
101   GList* list = *metadatas;
102   for (auto& meta : metadata) {
103     metadata_x* new_meta =
104         static_cast<metadata_x*>(calloc(1, sizeof(metadata_x)));
105     if (!new_meta) {
106       LOG(ERROR) << "Out of memory";
107       return;
108     }
109     new_meta->key = strdup(meta.first.c_str());
110     if (!meta.second.empty())
111       new_meta->value = strdup(meta.second.c_str());
112
113     list = g_list_append(list, new_meta);
114   }
115
116   *metadatas = list;
117 }
118
119 void SetApplicationXDefaults(application_x* application) {
120   application->effectimage_type = strdup("image");
121   application->guestmode_visibility = strdup("true");
122   application->hwacceleration = strdup("default");
123   application->indicatordisplay = strdup("true");
124   application->launchcondition = strdup("false");
125   application->permission_type = strdup("normal");
126   application->process_pool = strdup("false");
127   application->recentimage = strdup("false");
128   application->screenreader = strdup("use-system-setting");
129   application->submode = strdup("false");
130   application->support_disable = strdup("false");
131   application->ui_gadget = strdup("false");
132   application->multiple = strdup("false");
133 }
134
135 template<typename T>
136 void AppendLabel(T* root, const std::string& label,
137                  const std::string& locale) {
138   label_x* label_item = reinterpret_cast<label_x*>(calloc(1, sizeof(label_x)));
139   if (!label_item) {
140     LOG(ERROR) << "Out of memory";
141     return;
142   }
143   label_item->name = strdup(label.c_str());
144   label_item->text = strdup(label.c_str());
145   label_item->lang = !locale.empty() ?
146       strdup(locale.c_str()) : strdup(DEFAULT_LOCALE);
147   root->label = g_list_append(root->label, label_item);
148 }
149
150 }  // namespace
151
152 namespace wgt {
153 namespace configuration {
154
155 namespace app_keys = wgt::application_widget_keys;
156 namespace sc = std::chrono;
157
158 StepParse::StepParse(common_installer::InstallerContext* context,
159                      ConfigLocation config_location,
160                      bool check_start_file)
161     : Step(context),
162       config_location_(config_location),
163       check_start_file_(check_start_file) {
164 }
165
166 std::set<std::string> StepParse::ExtractPrivileges(
167     std::shared_ptr<const wgt::parse::PermissionsInfo> perm_info) const {
168   return perm_info->GetAPIPermissions();
169 }
170
171 std::string StepParse::GetPackageVersion(
172      const std::string& manifest_version) {
173   if (manifest_version.empty()) {
174     return kManifestVersion;
175   }
176   std::string version = manifest_version.substr(0,
177       manifest_version.find_first_not_of("1234567890."));
178
179   return version;
180 }
181
182 bool StepParse::FillInstallationInfo(manifest_x* manifest) {
183   manifest->root_path = strdup(
184       (context_->root_application_path.get() / manifest->package).c_str());
185   manifest->installed_time =
186       strdup(std::to_string(sc::system_clock::to_time_t(
187           sc::system_clock::now())).c_str());
188   return true;
189 }
190
191 bool StepParse::FillIconPaths(manifest_x* manifest) {
192   auto app_info =
193       GetManifestDataForKey<const wgt::parse::TizenApplicationInfo>(
194              app_keys::kTizenApplicationKey);
195   if (!app_info) {
196     LOG(ERROR) << "Application info manifest data has not been found.";
197     return false;
198   }
199   auto icons_info =
200     GetManifestDataForKey<const wgt::parse::ApplicationIconsInfo>(
201            app_keys::kIconsKey);
202   if (!icons_info) {
203     icons_info.reset(new(std::nothrow) wgt::parse::ApplicationIconsInfo());
204     if (!icons_info) {
205       LOG(ERROR) << "Out of memory";
206       return false;
207     }
208   }
209   wgt::parse::LocalizedApplicationIconsInfo localized_list =
210       wgt::parse::GetLocalizedIconList(*icons_info, widget_path_);
211   // We need to generate icon for each locale and icons are already set into
212   // lookup order. There isn't said that all icons should be received from
213   // one <icon> tag position so we iterate utils we run out of icons creating
214   // any icon element that are possible for given locale.
215   std::set<std::string> found_locales;
216   for (auto& application_icon : localized_list) {
217     const std::string& locale = application_icon.locale();
218     if (found_locales.find(locale) != found_locales.end())
219       continue;
220     found_locales.insert(locale);
221
222     icon_x* icon = reinterpret_cast<icon_x*>(calloc(1, sizeof(icon_x)));
223     if (!icon) {
224       LOG(ERROR) << "Out of memory";
225       return false;
226     }
227     bf::path icon_path = context_->root_application_path.get()
228         / app_info->package() / "res" / "wgt" / application_icon.path();
229     icon->text = strdup(icon_path.c_str());
230     if (!locale.empty())
231       icon->lang = strdup(locale.c_str());
232     else
233       icon->lang = strdup(DEFAULT_LOCALE);
234     manifest->icon = g_list_append(manifest->icon, icon);
235   }
236   return true;
237 }
238
239 bool StepParse::FillWidgetInfo(manifest_x* manifest) {
240   auto wgt_info =
241       GetManifestDataForKey<const wgt::parse::WidgetInfo>(
242              app_keys::kWidgetKey);
243
244   if (!wgt_info.get()) {
245     LOG(ERROR) << "Widget info manifest data has not been found.";
246     return false;
247   }
248
249   const std::string& version = wgt_info->version();
250
251   manifest->ns = strdup(kTizenPackageXmlNamespace);
252   manifest->version = strdup(GetPackageVersion(version).c_str());
253
254   for (auto& item : wgt_info->description_set()) {
255     description_x* description = reinterpret_cast<description_x*>
256         (calloc(1, sizeof(description_x)));
257     if (!description) {
258       LOG(ERROR) << "Out of memory";
259       return false;
260     }
261     description->text = strdup(item.second.c_str());
262     description->lang = !item.first.empty() ?
263         strdup(item.first.c_str()) : strdup(DEFAULT_LOCALE);
264     manifest->description = g_list_append(manifest->description, description);
265   }
266
267   for (auto& item : wgt_info->name_set()) {
268     AppendLabel(manifest, item.second, item.first);
269   }
270
271   manifest->type = strdup("wgt");
272   manifest->appsetting = strdup("false");
273   manifest->nodisplay_setting = strdup("false");
274   manifest->installed_storage = strdup("installed_internal");
275
276   // For wgt package use the long name
277   application_x* app =
278       reinterpret_cast<application_x*>(manifest->application->data);
279   for (auto& item : wgt_info->name_set()) {
280     AppendLabel(app, item.second, item.first);
281   }
282
283   author_x* author = reinterpret_cast<author_x*>(calloc(1, sizeof(author_x)));
284   if (!author) {
285     LOG(ERROR) << "Out of memory";
286     return false;
287   }
288   if (!wgt_info->author().empty())
289     author->text = strdup(wgt_info->author().c_str());
290   if (!wgt_info->author_email().empty())
291     author->email = strdup(wgt_info->author_email().c_str());
292   if (!wgt_info->author_href().empty())
293     author->href = strdup(wgt_info->author_href().c_str());
294   author->lang = strdup(DEFAULT_LOCALE);
295   manifest->author = g_list_append(manifest->author, author);
296
297   auto settings_info =
298       GetManifestDataForKey<const wgt::parse::SettingInfo>(
299              wgt::application_widget_keys::kTizenSettingKey);
300   if (settings_info) {
301     switch (settings_info->install_location()) {
302     case wgt::parse::SettingInfo::InstallLocation::AUTO: {
303       manifest->installlocation = strdup("auto");
304       break;
305     }
306     case wgt::parse::SettingInfo::InstallLocation::INTERNAL: {
307       manifest->installlocation = strdup("internal-only");
308       break;
309     }
310     case wgt::parse::SettingInfo::InstallLocation::EXTERNAL: {
311       manifest->installlocation = strdup("prefer-external");
312       break;
313     }
314     }
315   } else {
316     manifest->installlocation = strdup("auto");
317   }
318
319   if (!context_->pkgid.get().empty()) {
320     // set update true if package is updated preload package
321     ci::RequestType req_type = context_->request_type.get();
322     ci::PkgQueryInterface pkg_query(manifest->package, context_->uid.get());
323     if (pkg_query.IsUpdatedPackage())
324       manifest->update = strdup("true");
325     else if (pkg_query.IsPreloadPackage() &&
326             (req_type == ci::RequestType::Update ||
327             req_type == ci::RequestType::Delta ||
328             req_type == ci::RequestType::MountUpdate ||
329             req_type == ci::RequestType::ReadonlyUpdateInstall))
330       manifest->update = strdup("true");
331     else
332       manifest->update = strdup("false");
333   }
334
335   return true;
336 }
337
338 bool StepParse::FillMainApplicationInfo(manifest_x* manifest) {
339   auto app_info =
340       GetManifestDataForKey<const wgt::parse::TizenApplicationInfo>(
341              app_keys::kTizenApplicationKey);
342   if (!app_info) {
343     LOG(ERROR) << "Application info manifest data has not been found.";
344     return false;
345   }
346   bool has_watch_category = false;
347   bool has_ime = false;
348   bool has_downloadable_font = false;
349   bool has_tts = false;
350   auto category_info =
351       GetManifestDataForKey<const wgt::parse::CategoryInfoList>(
352              app_keys::kTizenCategoryKey);
353
354   if (category_info) {
355     has_watch_category = std::find_if(category_info->categories.begin(),
356                                        category_info->categories.end(),
357                                        [](const std::string& category) {
358       return category == kCategoryWearableClock ||
359              category == kCategoryWatchClock;
360     }) != category_info->categories.end();
361     has_ime = std::find(category_info->categories.begin(),
362                                        category_info->categories.end(),
363                                        kImeCategoryName)
364         != category_info->categories.end();
365     has_downloadable_font = std::find(category_info->categories.begin(),
366                                        category_info->categories.end(),
367                                        kDownloadableFontCategoryName)
368         != category_info->categories.end();
369     has_tts = std::find(category_info->categories.begin(),
370                                        category_info->categories.end(),
371                                        kTTSCategoryName)
372         != category_info->categories.end();
373   }
374
375   // application data
376   application_x* application = reinterpret_cast<application_x*>(
377       calloc(1, sizeof(application_x)));
378   if (!application) {
379     LOG(ERROR) << "Out of memory";
380     return false;
381   }
382   application->component_type =
383       has_watch_category ? strdup("watchapp") : strdup("uiapp");
384   application->mainapp = strdup("true");
385   application->appid = strdup(app_info->id().c_str());
386   auto settings_info =
387       GetManifestDataForKey<const wgt::parse::SettingInfo>(
388              wgt::application_widget_keys::kTizenSettingKey);
389
390   bool no_display = settings_info ? settings_info->no_display() : false;
391   bool has_no_display_category =
392       has_watch_category || has_ime || has_tts || has_downloadable_font;
393
394   application->nodisplay = (has_no_display_category || no_display) ?
395       strdup("true") : strdup("false");
396   application->taskmanage = has_no_display_category ? strdup("false") :
397       strdup("true");
398
399   SetApplicationXDefaults(application);
400   if (has_watch_category)
401     application->support_ambient =
402         strdup(app_info->ambient_support() ? "true" : "false");
403   else
404     application->support_ambient = strdup("false");
405   application->package = strdup(app_info->package().c_str());
406
407   application->exec =
408       strdup((context_->root_application_path.get() / app_info->package()
409               / "bin" / application->appid).c_str());
410   application->type = strdup("webapp");
411   application->onboot = strdup("false");
412   application->autorestart = strdup("false");
413
414   application->launch_mode = strdup(app_info->launch_mode().c_str());
415   application->api_version = strdup(manifest->api_version);
416   for (auto& icon : GListRange<icon_x*>(manifest->icon)) {
417     icon_x* app_icon = reinterpret_cast<icon_x*>(calloc(1, sizeof(icon_x)));
418     if (!app_icon) {
419       LOG(ERROR) << "Out of memory";
420       pkgmgrinfo_basic_free_application(application);
421       return false;
422     }
423     app_icon->text = strdup(icon->text);
424     app_icon->lang = strdup(icon->lang);
425     application->icon = g_list_append(application->icon, app_icon);
426   }
427   // guarantees that the main app will be at the begining of the list
428   manifest->application = g_list_insert(manifest->application, application, 0);
429
430   manifest->package = strdup(app_info->package().c_str());
431   manifest->mainapp_id = strdup(app_info->id().c_str());
432   return true;
433 }
434
435 bool StepParse::FillServiceApplicationInfo(manifest_x* manifest) {
436   auto service_list =
437       GetManifestDataForKey<const wgt::parse::ServiceList>(
438              app_keys::kTizenServiceKey);
439   if (!service_list)
440     return true;
441   for (auto& service_info : service_list->services) {
442     application_x* application = reinterpret_cast<application_x*>
443         (calloc(1, sizeof(application_x)));
444     if (!application) {
445       LOG(ERROR) << "Out of memory";
446       return false;
447     }
448     application->component_type = strdup("svcapp");
449     application->mainapp = strdup("false");
450     application->appid = strdup(service_info.id().c_str());
451     application->exec =
452         strdup((context_->root_application_path.get() / manifest->package
453                 / "bin" / application->appid).c_str());
454     application->type = strdup("webapp");
455     application->onboot =
456         service_info.on_boot() ? strdup("true") : strdup("false");
457     application->autorestart =
458         service_info.auto_restart() ? strdup("true") : strdup("false");
459     application->nodisplay = strdup("false");
460     application->taskmanage = strdup("true");
461     SetApplicationXDefaults(application);
462     application->support_ambient = strdup("false");
463     application->package = strdup(manifest->package);
464     application->api_version = strdup(manifest->api_version);
465     for (auto& pair : service_info.names()) {
466       AppendLabel(application, pair.second, pair.first);
467     }
468
469     if (!service_info.icon().empty()) {
470       bf::path icon_path = context_->root_application_path.get()
471           / manifest->package / "res" / "wgt" / service_info.icon();
472       icon_x* icon = reinterpret_cast<icon_x*>(calloc(1, sizeof(icon_x)));
473       if (!icon) {
474         LOG(ERROR) << "Out of memory";
475         pkgmgrinfo_basic_free_application(application);
476         return false;
477       }
478       icon->text = strdup(icon_path.c_str());
479       icon->lang = strdup(DEFAULT_LOCALE);
480       application->icon = g_list_append(application->icon, icon);
481     }
482
483     for (auto& category : service_info.categories()) {
484       application->category = g_list_append(application->category,
485                                             strdup(category.c_str()));
486     }
487
488     for (auto& pair : service_info.metadata_set()) {
489       metadata_x* item = reinterpret_cast<metadata_x*>(
490           calloc(1, sizeof(metadata_x)));
491       if (!item) {
492         LOG(ERROR) << "Out of memory";
493         pkgmgrinfo_basic_free_application(application);
494         return false;
495       }
496       item->key = strdup(pair.first.c_str());
497       if (!pair.second.empty())
498         item->value = strdup(pair.second.c_str());
499       application->metadata = g_list_append(application->metadata, item);
500     }
501
502     manifest->application = g_list_append(manifest->application, application);
503   }
504   return true;
505 }
506
507 bool StepParse::FillWidgetApplicationInfo(manifest_x* manifest) {
508   auto appwidget_info =
509       GetManifestDataForKey<const wgt::parse::AppWidgetInfo>(
510              wgt::application_widget_keys::kTizenAppWidgetFullKey);
511   if (!appwidget_info)
512     return true;
513
514   auto settings_info =
515       GetManifestDataForKey<const wgt::parse::SettingInfo>(
516               wgt::application_widget_keys::kTizenSettingKey);
517   bool no_display = settings_info ? settings_info->no_display() : false;
518
519   for (auto& app_widget : appwidget_info->app_widgets()) {
520     application_x* application = reinterpret_cast<application_x*>
521         (calloc(1, sizeof(application_x)));
522     if (!application) {
523       LOG(ERROR) << "Out of memory";
524       return false;
525     }
526     application->component_type = strdup("widgetapp");
527     application->mainapp = strdup("false");
528     application->appid = strdup(app_widget.id.c_str());
529     application->exec =
530         strdup((context_->root_application_path.get() / manifest->package
531                 / "bin" / application->appid).c_str());
532     application->type = strdup("webapp");
533     application->nodisplay = no_display ? strdup("true") : strdup("false");
534     application->taskmanage = strdup("false");
535     SetApplicationXDefaults(application);
536     application->support_ambient = strdup("false");
537     application->package = strdup(manifest->package);
538     application->api_version = strdup(manifest->api_version);
539     if (!app_widget.label.default_value.empty()) {
540       AppendLabel(application, app_widget.label.default_value, std::string());
541     }
542
543     for (auto& pair : app_widget.label.lang_value_map) {
544       AppendLabel(application, pair.second, pair.first);
545     }
546
547     if (!app_widget.icon_src.empty()) {
548       icon_x* icon = reinterpret_cast<icon_x*>(calloc(1, sizeof(icon_x)));
549       if (!icon) {
550         LOG(ERROR) << "Out of memory";
551         pkgmgrinfo_basic_free_application(application);
552         return false;
553       }
554       icon->text = strdup(app_widget.icon_src.c_str());
555       icon->lang = strdup(DEFAULT_LOCALE);
556       application->icon = g_list_append(application->icon, icon);
557     }
558
559     if (!app_widget.metadata.empty())
560       AppendWidgetMetadata(&application->metadata, app_widget.metadata);
561
562     manifest->application = g_list_append(manifest->application, application);
563   }
564   return true;
565 }
566
567
568 bool StepParse::FillBackgroundCategoryInfo(manifest_x* manifest) {
569   auto manifest_data = parser_->GetManifestData(
570       app_keys::kTizenBackgroundCategoryKey);
571   std::shared_ptr<const wgt::parse::BackgroundCategoryInfoList> bc_list =
572       std::static_pointer_cast<const wgt::parse::BackgroundCategoryInfoList>(
573           manifest_data);
574
575   if (!bc_list)
576     return true;
577
578   application_x* app =
579       reinterpret_cast<application_x*>(manifest->application->data);
580
581   for (auto& background_category : bc_list->background_categories) {
582     app->background_category = g_list_append(
583         app->background_category, strdup(background_category.value().c_str()));
584   }
585
586   return true;
587 }
588
589 bool StepParse::FillTrustAnchorInfo(manifest_x* manifest) {
590   auto trust_anchor_info = parser_->GetManifestData(
591       app_keys::kTizenTrustAnchorKey);
592
593   if (!trust_anchor_info)
594     return true;
595
596   std::shared_ptr<const parse::TrustAnchorInfo> trust_anchor =
597       std::static_pointer_cast<const parse::TrustAnchorInfo>
598       (trust_anchor_info);
599
600   if (!trust_anchor)
601     return true;
602
603   std::string use_system_certs = trust_anchor->get_use_system_certs();
604   if (!use_system_certs.empty())
605     manifest->use_system_certs = strdup(use_system_certs.c_str());
606
607   return true;
608 }
609
610 bool StepParse::FillAppControl(manifest_x* manifest) {
611   auto app_info_list =
612       GetManifestDataForKey<const wgt::parse::AppControlInfoList>(
613              app_keys::kTizenApplicationAppControlsKey);
614
615   application_x* app =
616       reinterpret_cast<application_x*>(manifest->application->data);
617   if (app_info_list) {
618     for (const auto& control : app_info_list->controls) {
619       appcontrol_x* app_control =
620           static_cast<appcontrol_x*>(calloc(1, sizeof(appcontrol_x)));
621       if (!app_control) {
622         LOG(ERROR) << "Out of memory";
623         return false;
624       }
625       app_control->operation = strdup(control.operation().c_str());
626       app_control->mime = strdup(control.mime().c_str());
627       app_control->uri = strdup(control.uri().c_str());
628       app->appcontrol = g_list_append(app->appcontrol, app_control);
629     }
630   }
631   return true;
632 }
633
634 bool StepParse::FillPrivileges(manifest_x* manifest) {
635   auto perm_info =
636       GetManifestDataForKey<const wgt::parse::PermissionsInfo>(
637              app_keys::kTizenPermissionsKey);
638   std::set<std::string> privileges;
639   if (perm_info)
640     privileges = ExtractPrivileges(perm_info);
641
642   for (auto& priv : privileges) {
643     privilege_x* privilege =
644         reinterpret_cast<privilege_x*>(calloc(1, sizeof(privilege_x)));
645     if (!privilege) {
646       LOG(ERROR) << "Out of memory";
647       return false;
648     }
649     privilege->type = strdup(common_installer::kWebPrivilegeType);
650     privilege->value = strdup(priv.c_str());
651     manifest->privileges = g_list_append(manifest->privileges, privilege);
652   }
653   return true;
654 }
655
656 bool StepParse::FillAppDefinedPrivileges(manifest_x* manifest) {
657   auto priv_info_list =
658       GetManifestDataForKey<const wgt::parse::AppDefinedPrivilegeInfoList>(
659           app_keys::kTizenAppDefinedPrivilegeKey);
660   if (!priv_info_list)
661     return true;
662
663   for (auto& priv : priv_info_list->appdefined_privileges) {
664     appdefined_privilege_x* privilege =
665         reinterpret_cast<appdefined_privilege_x*>(calloc(1,
666             sizeof(appdefined_privilege_x)));
667     if (privilege == nullptr) {
668       LOG(ERROR) << "Memory alloc failure";
669       return false;
670     }
671     privilege->value = strdup(priv.name().c_str());
672     privilege->type = strdup(common_installer::kWebPrivilegeType);
673     if (!priv.license().empty()) {
674       if (bf::path(priv.license()).is_absolute())
675         privilege->license = strdup(priv.license().c_str());
676       else
677         privilege->license = strdup((context_->root_application_path.get()
678             / manifest->package / priv.license()).c_str());
679     }
680     manifest->appdefined_privileges =
681         g_list_append(manifest->appdefined_privileges, privilege);
682   }
683   return true;
684 }
685
686 bool StepParse::FillProvidesAppDefinedPrivileges(manifest_x* manifest) {
687   auto priv_info_list =
688       GetManifestDataForKey<const wgt::parse::AppDefinedPrivilegeInfoList>(
689           app_keys::kTizenProvidesAppDefinedPrivilegeKey);
690   if (!priv_info_list)
691     return true;
692
693   for (auto& priv : priv_info_list->appdefined_privileges) {
694     appdefined_privilege_x* privilege =
695         reinterpret_cast<appdefined_privilege_x*>(calloc(1,
696             sizeof(appdefined_privilege_x)));
697     if (privilege == nullptr) {
698       LOG(ERROR) << "Memory alloc failure";
699       return false;
700     }
701     privilege->value = strdup(priv.name().c_str());
702     privilege->type = strdup(common_installer::kWebPrivilegeType);
703     if (!priv.license().empty()) {
704       if (bf::path(priv.license()).is_absolute())
705         privilege->license = strdup(priv.license().c_str());
706       else
707         privilege->license = strdup((context_->root_application_path.get()
708             / manifest->package / priv.license()).c_str());
709     }
710     manifest->provides_appdefined_privileges =
711         g_list_append(manifest->provides_appdefined_privileges, privilege);
712   }
713   return true;
714 }
715
716 bool StepParse::FillCategories(manifest_x* manifest) {
717   auto category_info =
718       GetManifestDataForKey<const wgt::parse::CategoryInfoList>(
719              app_keys::kTizenCategoryKey);
720   if (!category_info)
721     return true;
722
723   application_x* app =
724       reinterpret_cast<application_x*>(manifest->application->data);
725   // there is one app atm
726   for (auto& category : category_info->categories) {
727     app->category = g_list_append(app->category, strdup(category.c_str()));
728   }
729   return true;
730 }
731
732 bool StepParse::FillMetadata(manifest_x* manifest) {
733   auto meta_info =
734       GetManifestDataForKey<const wgt::parse::MetaDataInfo>(
735              app_keys::kTizenMetaDataKey);
736   if (!meta_info)
737     return true;
738
739   for (application_x* app : GListRange<application_x*>(manifest->application)) {
740     app->metadata = GenerateMetadataListX(*meta_info);
741   }
742   return true;
743 }
744
745 bool StepParse::FillAppWidget() {
746   // This is needed to store preview icons which are not saved into manifest_x
747   WgtBackendData* backend_data =
748       static_cast<WgtBackendData*>(context_->backend_data.get());
749
750   auto appwidget_info =
751       GetManifestDataForKey<const wgt::parse::AppWidgetInfo>(
752              wgt::application_widget_keys::kTizenAppWidgetFullKey);
753   if (appwidget_info)
754     backend_data->appwidgets.set(*appwidget_info);
755   return true;
756 }
757
758 bool StepParse::FillAccounts(manifest_x* manifest) {
759   auto account_info =
760       GetManifestDataForKey<const wgt::parse::AccountInfo>(
761              app_keys::kAccountKey);
762   if (!account_info)
763     return true;
764   common_installer::AccountInfo info;
765   for (auto& account : account_info->accounts()) {
766     common_installer::SingleAccountInfo single_info;
767     single_info.capabilities = account.capabilities;
768     single_info.icon_paths = account.icon_paths;
769     single_info.multiple_account_support = account.multiple_account_support;
770     single_info.names = account.names;
771     // wgt can contain only one app so this assumes mainapp_id is valid here
772     single_info.appid = manifest->mainapp_id;
773     info.set_account(single_info);
774   }
775   context_->manifest_plugins_data.get().account_info.set(info);
776   return true;
777 }
778
779 bool StepParse::FillImeInfo() {
780   auto ime_info =
781       GetManifestDataForKey<const wgt::parse::ImeInfo>(
782              app_keys::kTizenImeKey);
783   if (!ime_info)
784     return true;
785
786   common_installer::ImeInfo info;
787   info.setUuid(ime_info->uuid());
788
789   const auto &languages = ime_info->languages();
790   for (const auto &language : languages)
791     info.AddLanguage(language);
792
793   context_->manifest_plugins_data.get().ime_info.set(std::move(info));
794   return true;
795 }
796
797 bool StepParse::FillExtraManifestInfo(manifest_x* manifest) {
798   return FillAccounts(manifest) && FillImeInfo() && FillAppWidget();
799 }
800
801 bool StepParse::FillManifestX(manifest_x* manifest) {
802   // Fill data for main application
803   if (!FillIconPaths(manifest))
804     return false;
805   if (!FillMainApplicationInfo(manifest))
806     return false;
807   if (!FillWidgetInfo(manifest))
808     return false;
809   if (!FillInstallationInfo(manifest))
810     return false;
811   if (!FillPrivileges(manifest))
812     return false;
813   if (!FillAppDefinedPrivileges(manifest))
814     return false;
815   if (!FillProvidesAppDefinedPrivileges(manifest))
816     return false;
817   if (!FillAppControl(manifest))
818     return false;
819   if (!FillCategories(manifest))
820     return false;
821   if (!FillMetadata(manifest))
822     return false;
823   if (!FillBackgroundCategoryInfo(manifest))
824     return false;
825   if (!FillTrustAnchorInfo(manifest))
826     return false;
827
828   // Fill data for other applications
829   if (!FillAdditionalApplications(manifest))
830     return false;
831
832   // Fill extra data, other than manifest_x structure
833   if (!FillExtraManifestInfo(manifest))
834     return false;
835
836   return true;
837 }
838
839
840 bool StepParse::FillAdditionalApplications(manifest_x* manifest) {
841   if (!FillServiceApplicationInfo(manifest))
842     return false;
843   if (!FillWidgetApplicationInfo(manifest))
844     return false;
845   return true;
846 }
847
848 bool StepParse::LocateConfigFile() {
849   switch (config_location_) {
850     case ConfigLocation::PACKAGE:
851       return StepParse::Check(context_->unpacked_dir_path.get());
852     case ConfigLocation::INSTALLED:
853       return StepParse::Check(context_->GetPkgPath() / kResWgt);
854     case ConfigLocation::RECOVERY:
855       if (StepParse::Check(common_installer::GetBackupPathForPackagePath(
856           context_->GetPkgPath()) / kResWgt))
857         return true;
858       if (StepParse::Check(context_->GetPkgPath() / kResWgt))
859         return true;
860       return false;
861     case ConfigLocation::RESOURCE_WGT:
862       return StepParse::Check(context_->unpacked_dir_path.get() / kResWgt);
863     default:
864       LOG(ERROR) << "Unknown config location";
865       return false;
866   }
867 }
868
869 common_installer::Step::Status StepParse::process() {
870   if (!LocateConfigFile()) {
871     LOG(ERROR) << "No config.xml";
872     return common_installer::Step::Status::MANIFEST_NOT_FOUND;
873   }
874
875   parser_.reset(new(std::nothrow) wgt::parse::WidgetConfigParser());
876   if (!parser_) {
877     LOG(ERROR) << "Out of memory";
878     return common_installer::Step::Status::CONFIG_ERROR;
879   }
880   if (!parser_->ParseManifest(widget_path_ / kConfigFileName)) {
881     LOG(ERROR) << "[Parse] Parse failed. " <<  parser_->GetErrorMessage();
882     return common_installer::Step::Status::PARSE_ERROR;
883   }
884
885   WgtBackendData* backend_data =
886     static_cast<WgtBackendData*>(context_->backend_data.get());
887
888   if (check_start_file_) {
889     if (!parser_->CheckValidStartFile()) {
890       LOG(ERROR) << parser_->GetErrorMessage();
891       return common_installer::Step::Status::PARSE_ERROR;
892     }
893     if (!parser_->CheckValidServicesStartFiles()) {
894       LOG(ERROR) << parser_->GetErrorMessage();
895       return common_installer::Step::Status::PARSE_ERROR;
896     }
897   } else {
898     // making backup of content data and services content data
899     auto content_info =
900       GetManifestDataForKey<const wgt::parse::ContentInfo>(
901               wgt::application_widget_keys::kTizenContentKey);
902     auto service_list =
903       GetManifestDataForKey<const wgt::parse::ServiceList>(
904               wgt::application_widget_keys::kTizenServiceKey);
905     if (content_info)
906       backend_data->content.set(*content_info);
907     if (service_list)
908       backend_data->service_list.set(*service_list);
909   }
910
911   // Copy data from ManifestData to InstallerContext
912   auto info =
913       GetManifestDataForKey<const wgt::parse::TizenApplicationInfo>(
914               wgt::application_widget_keys::kTizenApplicationKey);
915   auto wgt_info =
916       GetManifestDataForKey<const wgt::parse::WidgetInfo>(
917               wgt::application_widget_keys::kTizenWidgetKey);
918
919   std::string name;
920   const auto& name_set = wgt_info->name_set();
921   if (name_set.find("") != name_set.end())
922     name = name_set.find("")->second;
923   if (name_set.begin() != name_set.end())
924     name = name_set.begin()->second;
925
926   std::string short_name;
927   const auto& short_name_set = wgt_info->short_name_set();
928   if (short_name_set.find("") != short_name_set.end())
929     short_name = short_name_set.find("")->second;
930   if (short_name_set.begin() != short_name_set.end())
931     short_name = short_name_set.begin()->second;
932
933   const std::string& package_version = wgt_info->version();
934   const std::string& required_api_version = info->required_version();
935
936   manifest_x* manifest =
937       static_cast<manifest_x*>(calloc(1, sizeof(manifest_x)));
938   if (!manifest) {
939     LOG(ERROR) << "Out of memory";
940     return common_installer::Step::Status::ERROR;
941   }
942   manifest->api_version = strdup(required_api_version.c_str());
943
944   if (!FillManifestX(manifest)) {
945     LOG(ERROR) << "[Parse] Storing manifest_x failed. "
946                <<  parser_->GetErrorMessage();
947     pkgmgr_parser_free_manifest_xml(manifest);
948     return common_installer::Step::Status::PARSE_ERROR;
949   }
950
951   context_->pkgid.set(manifest->package);
952
953   // write pkgid for recovery file
954   if (context_->recovery_info.get().recovery_file) {
955     context_->recovery_info.get().recovery_file->set_pkgid(manifest->package);
956     context_->recovery_info.get().recovery_file->WriteAndCommitFileContent();
957   }
958
959   auto perm_info =
960       GetManifestDataForKey<const wgt::parse::PermissionsInfo>(
961               wgt::application_widget_keys::kTizenPermissionsKey);
962   parser::PermissionSet permissions;
963   if (perm_info)
964      permissions = perm_info->GetAPIPermissions();
965
966   auto settings_info =
967       GetManifestDataForKey<const wgt::parse::SettingInfo>(
968               wgt::application_widget_keys::kTizenSettingKey);
969   if (settings_info)
970     backend_data->settings.set(*settings_info);
971
972   LOG(DEBUG) << " Read data -[ ";
973   LOG(DEBUG) << "App id: " << info->id();
974   LOG(DEBUG) << "  package     = " <<  info->package();
975   LOG(DEBUG) << "  id          = " <<  info->id();
976   LOG(DEBUG) << "  name        = " <<  name;
977   LOG(DEBUG) << "  short_name  = " <<  short_name;
978   LOG(DEBUG) << "  aplication version     = " <<  package_version;
979   LOG(DEBUG) << "  api_version = " <<  info->required_version();
980   LOG(DEBUG) << "  launch_mode = " <<  info->launch_mode();
981   LOG(DEBUG) << "  privileges -[";
982   for (const auto& p : permissions) {
983     LOG(DEBUG) << "    " << p;
984   }
985   LOG(DEBUG) << "  ]-";
986   LOG(DEBUG) << "]-";
987
988   if (context_->manifest_data.get())
989     pkgmgr_parser_free_manifest_xml(context_->manifest_data.get());
990
991   context_->manifest_data.set(manifest);
992   return common_installer::Step::Status::OK;
993 }
994
995 bool StepParse::Check(const boost::filesystem::path& widget_path) {
996   LOG(DEBUG) << "unpacked widget path: " << widget_path;
997
998   widget_path_ = widget_path;
999
1000   boost::filesystem::path config = widget_path / kConfigFileName;
1001   LOG(DEBUG) << "config.xml path: " << config;
1002   if (!boost::filesystem::exists(config))
1003     return false;
1004   return true;
1005 }
1006
1007 }  // namespace configuration
1008 }  // namespace wgt