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