Temporary fix for hybrid pkg installation
[platform/core/appfw/wgt-backend.git] / src / wgt / step / pkgmgr / step_generate_xml.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/pkgmgr/step_generate_xml.h"
7
8 #include <boost/filesystem/path.hpp>
9 #include <boost/system/error_code.hpp>
10
11 #include <common/utils/file_util.h>
12 #include <common/utils/glist_range.h>
13 #include <common/privileges.h>
14
15 #include <libxml/parser.h>
16 #include <libxml/xmlreader.h>
17 #include <pkgmgr-info.h>
18 #include <pkgmgr_parser.h>
19 #include <tzplatform_config.h>
20 #include <unistd.h>
21
22 #include <cassert>
23 #include <cstring>
24 #include <string>
25
26 #include "wgt/wgt_backend_data.h"
27
28 namespace bs = boost::system;
29 namespace bf = boost::filesystem;
30
31 namespace {
32
33 const char kResWgt[] = "res/wgt";
34 const char kSharedRes[] = "shared/res";
35
36 void WriteUIApplicationAttributes(
37     xmlTextWriterPtr writer, application_x *app) {
38   if (app->taskmanage)
39     xmlTextWriterWriteAttribute(writer, BAD_CAST "taskmanage",
40         BAD_CAST app->taskmanage);
41   if (app->nodisplay)
42     xmlTextWriterWriteAttribute(writer, BAD_CAST "nodisplay",
43         BAD_CAST app->nodisplay);
44   if (app->multiple)
45     xmlTextWriterWriteAttribute(writer, BAD_CAST "multiple",
46         BAD_CAST app->multiple);
47   if (app->launch_mode && strlen(app->launch_mode))
48     xmlTextWriterWriteAttribute(writer, BAD_CAST "launch_mode",
49         BAD_CAST app->launch_mode);
50   if (app->ui_gadget && strlen(app->ui_gadget))
51     xmlTextWriterWriteAttribute(writer, BAD_CAST "ui-gadget",
52         BAD_CAST app->ui_gadget);
53   if (app->submode && strlen(app->submode))
54     xmlTextWriterWriteAttribute(writer, BAD_CAST "submode",
55         BAD_CAST app->submode);
56   if (app->submode_mainid && strlen(app->submode_mainid))
57     xmlTextWriterWriteAttribute(writer, BAD_CAST "submode-mainid",
58         BAD_CAST app->submode_mainid);
59   if (app->indicatordisplay && strlen(app->indicatordisplay))
60     xmlTextWriterWriteAttribute(writer, BAD_CAST "indicatordisplay",
61         BAD_CAST app->indicatordisplay);
62   if (app->portraitimg && strlen(app->portraitimg))
63     xmlTextWriterWriteAttribute(writer, BAD_CAST "portrait-effectimage",
64         BAD_CAST app->portraitimg);
65   if (app->landscapeimg && strlen(app->landscapeimg))
66     xmlTextWriterWriteAttribute(writer, BAD_CAST "landscape-effectimage",
67         BAD_CAST app->landscapeimg);
68   if (app->effectimage_type && strlen(app->effectimage_type))
69     xmlTextWriterWriteAttribute(writer, BAD_CAST "effectimage-type",
70         BAD_CAST app->effectimage_type);
71   if (app->hwacceleration && strlen(app->hwacceleration))
72     xmlTextWriterWriteAttribute(writer, BAD_CAST "hwacceleration",
73         BAD_CAST app->hwacceleration);
74 }
75
76 void WriteServiceApplicationAttributes(
77     xmlTextWriterPtr writer, application_x *app) {
78   xmlTextWriterWriteAttribute(writer, BAD_CAST "auto-restart",
79       BAD_CAST(app->autorestart ? app->autorestart : "false"));
80   xmlTextWriterWriteAttribute(writer, BAD_CAST "on-boot",
81       BAD_CAST(app->onboot ? app->onboot : "false"));
82   if (app->taskmanage)
83       xmlTextWriterWriteAttribute(writer, BAD_CAST "taskmanage",
84          BAD_CAST app->taskmanage);
85 }
86
87 bool WriteWidgetApplicationAttributesAndElements(
88     xmlTextWriterPtr writer, application_x *app,
89     const wgt::parse::AppWidgetInfo& widget_info,
90     const bf::path& shared_path) {
91   if (app->nodisplay)
92     xmlTextWriterWriteAttribute(writer, BAD_CAST "nodisplay",
93         BAD_CAST app->nodisplay);
94   if (app->multiple)
95     xmlTextWriterWriteAttribute(writer, BAD_CAST "multiple",
96         BAD_CAST app->multiple);
97   // FIXME: For hotfix, must be removed
98   if (app->support_sizes) {
99     for (auto& ss : GListRange<support_size_x*>(app->support_sizes)) {
100       xmlTextWriterStartElement(writer, BAD_CAST "support-size");
101       xmlTextWriterWriteAttribute(writer, BAD_CAST "preview",
102           BAD_CAST ss->preview);
103       xmlTextWriterWriteString(writer, BAD_CAST ss->size);
104       xmlTextWriterEndElement(writer);
105     }
106   }
107
108   auto& appwidgets = widget_info.app_widgets();
109   const auto& appwidget = std::find_if(appwidgets.begin(), appwidgets.end(),
110                                  [app](const wgt::parse::AppWidget& widget) {
111                                     return widget.id == app->appid;
112                                  });
113   if (appwidget == appwidgets.end()) {
114     return true;
115   }
116
117   // Add extra elements for wgt widget-application
118   xmlTextWriterWriteAttribute(writer, BAD_CAST "main",
119       BAD_CAST (appwidget->primary ? "true" : "false"));  // NOLINT
120   if (!appwidget->update_period.empty()) {
121         xmlTextWriterWriteAttribute(writer, BAD_CAST "update-period", BAD_CAST
122             std::to_string(static_cast<int>(
123                     appwidget->update_period.front())).c_str());
124   }
125
126   xmlTextWriterWriteAttribute(writer, BAD_CAST "max-instance",
127       BAD_CAST std::to_string(appwidget->max_instance).c_str());
128
129   for (auto& size : appwidget->content_size) {
130     xmlTextWriterStartElement(writer, BAD_CAST "support-size");
131
132     std::string type = wgt::parse::AppWidgetSizeTypeToString(size.type);
133     if (!size.preview.empty()) {
134       std::string icon_name = shared_path.string() + "/"
135           + appwidget->id + "." + type + "." + "preview" +
136           bf::path(size.preview).extension().string();
137       xmlTextWriterWriteAttribute(writer, BAD_CAST "preview",
138           BAD_CAST icon_name.c_str());  // NOLINT
139     }
140
141     xmlTextWriterWriteAttribute(writer, BAD_CAST "frame",
142                                 BAD_CAST "true");
143     xmlTextWriterWriteString(writer,
144         BAD_CAST type.c_str());
145     xmlTextWriterEndElement(writer);
146   }
147
148   for (auto& pair : appwidget->metadata) {
149     xmlTextWriterStartElement(writer, BAD_CAST "metadata");
150     xmlTextWriterWriteAttribute(writer, BAD_CAST "key",
151                                 BAD_CAST pair.first.c_str());
152     if (!pair.second.empty())
153       xmlTextWriterWriteAttribute(writer, BAD_CAST "value",
154                                   BAD_CAST pair.second.c_str());
155     xmlTextWriterEndElement(writer);
156   }
157   return true;
158 }
159
160 void WriteWatchApplicationAttributes(
161     xmlTextWriterPtr writer, application_x* app) {
162   if (app->ambient_support)
163     xmlTextWriterWriteAttribute(writer, BAD_CAST "ambient-support",
164         BAD_CAST app->ambient_support);
165 }
166
167 }  // namespace
168
169 namespace wgt {
170 namespace pkgmgr {
171
172 common_installer::Step::Status StepGenerateXml::GenerateApplicationCommonXml(
173     application_x* app, xmlTextWriterPtr writer, AppCompType type) {
174   xmlTextWriterWriteAttribute(writer, BAD_CAST "appid", BAD_CAST app->appid);
175
176   // binary is a symbolic link named <appid> and is located in <pkgid>/<appid>
177   bf::path exec_path = context_->pkg_path.get()
178       / bf::path("bin") / bf::path(app->appid);
179   xmlTextWriterWriteAttribute(writer, BAD_CAST "exec",
180                               BAD_CAST exec_path.string().c_str());
181   if (app->type)
182     xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST app->type);
183   else
184     xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST "capp");
185
186   if (app->process_pool && strlen(app->process_pool))
187     xmlTextWriterWriteAttribute(writer, BAD_CAST "process-pool",
188                                 BAD_CAST app->process_pool);
189   // app-specific attributes
190   switch (type) {
191   case AppCompType::UIAPP:
192     WriteUIApplicationAttributes(writer, app);
193     break;
194   case AppCompType::SVCAPP:
195     WriteServiceApplicationAttributes(writer, app);
196     break;
197   case AppCompType::WIDGETAPP:
198     if (!WriteWidgetApplicationAttributesAndElements(writer, app,
199         static_cast<WgtBackendData*>(
200             context_->backend_data.get())->appwidgets.get(),
201         context_->pkg_path.get() / "shared" / "res"))
202       return Status::MANIFEST_ERROR;
203     break;
204   case AppCompType::WATCHAPP:
205     WriteWatchApplicationAttributes(writer, app);
206     break;
207   }
208
209   for (label_x* label : GListRange<label_x*>(app->label)) {
210     if (label->name && strcmp(label->name, "") != 0) {
211       xmlTextWriterStartElement(writer, BAD_CAST "label");
212       if (label->lang && strcmp(DEFAULT_LOCALE, label->lang) != 0) {
213         xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
214                                     BAD_CAST label->lang);
215       }
216       xmlTextWriterWriteString(writer, BAD_CAST label->name);
217       xmlTextWriterEndElement(writer);
218     }
219   }
220
221   for (auto& icon : GListRange<icon_x*>(app->icon)) {
222     xmlTextWriterStartElement(writer, BAD_CAST "icon");
223     if (icon->lang && strcmp(DEFAULT_LOCALE, icon->lang) != 0) {
224       xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
225                                   BAD_CAST icon->lang);
226     }
227     xmlTextWriterWriteString(writer, BAD_CAST icon->text);
228     xmlTextWriterEndElement(writer);
229   }
230
231   for (image_x* image : GListRange<image_x*>(app->image)) {
232     xmlTextWriterStartElement(writer, BAD_CAST "image");
233     if (image->lang && strcmp(DEFAULT_LOCALE, image->lang) != 0) {
234       xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
235
236                                   BAD_CAST image->lang);
237     }
238     if (image->section)
239       xmlTextWriterWriteAttribute(writer, BAD_CAST "section",
240                                   BAD_CAST image->section);
241     xmlTextWriterEndElement(writer);
242   }
243
244   for (appcontrol_x* appc : GListRange<appcontrol_x*>(app->appcontrol)) {
245     xmlTextWriterStartElement(writer, BAD_CAST "app-control");
246
247     if (appc->operation) {
248       xmlTextWriterStartElement(writer, BAD_CAST "operation");
249       xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
250           BAD_CAST appc->operation);
251       xmlTextWriterEndElement(writer);
252     }
253
254     if (appc->uri) {
255       xmlTextWriterStartElement(writer, BAD_CAST "uri");
256       xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
257           BAD_CAST appc->uri);
258       xmlTextWriterEndElement(writer);
259     }
260
261     if (appc->mime) {
262       xmlTextWriterStartElement(writer, BAD_CAST "mime");
263       xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
264           BAD_CAST appc->mime);
265       xmlTextWriterEndElement(writer);
266     }
267
268     xmlTextWriterEndElement(writer);
269   }
270
271   for (datacontrol_x* datacontrol :
272        GListRange<datacontrol_x*>(app->datacontrol)) {
273     xmlTextWriterStartElement(writer, BAD_CAST "datacontrol");
274     if (datacontrol->access) {
275       xmlTextWriterWriteAttribute(writer, BAD_CAST "access",
276           BAD_CAST datacontrol->access);
277     }
278     if (datacontrol->providerid) {
279       xmlTextWriterWriteAttribute(writer, BAD_CAST "providerid",
280           BAD_CAST datacontrol->providerid);
281     }
282     if (datacontrol->type) {
283       xmlTextWriterWriteAttribute(writer, BAD_CAST "type",
284           BAD_CAST datacontrol->type);
285     }
286     xmlTextWriterEndElement(writer);
287   }
288
289   for (metadata_x* meta : GListRange<metadata_x*>(app->metadata)) {
290     xmlTextWriterStartElement(writer, BAD_CAST "metadata");
291     xmlTextWriterWriteAttribute(writer, BAD_CAST "key",
292         BAD_CAST meta->key);
293     if (meta->value)
294       xmlTextWriterWriteAttribute(writer, BAD_CAST "value",
295           BAD_CAST meta->value);
296     xmlTextWriterEndElement(writer);
297   }
298
299   for (const char* category : GListRange<char*>(app->category)) {
300     xmlTextWriterStartElement(writer, BAD_CAST "category");
301     xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST category);
302     xmlTextWriterEndElement(writer);
303   }
304
305   for (const char* background_category : GListRange<char*>(
306       app->background_category)) {
307     xmlTextWriterStartElement(writer, BAD_CAST "background-category");
308     xmlTextWriterWriteAttribute(writer, BAD_CAST "value",
309         BAD_CAST background_category);
310     xmlTextWriterEndElement(writer);
311   }
312
313   return Step::Status::OK;
314 }
315
316 common_installer::Step::Status StepGenerateXml::undo() {
317   bs::error_code error;
318   if (bf::exists(context_->xml_path.get()))
319     bf::remove_all(context_->xml_path.get(), error);
320   return Status::OK;
321 }
322
323 common_installer::Step::Status StepGenerateXml::precheck() {
324   if (!context_->manifest_data.get()) {
325     LOG(ERROR) << "manifest_data attribute is empty";
326     return Step::Status::INVALID_VALUE;
327   }
328   if (context_->pkgid.get().empty()) {
329     LOG(ERROR) << "pkgid attribute is empty";
330     return Step::Status::PACKAGE_NOT_FOUND;
331   }
332
333   if (!context_->manifest_data.get()->application) {
334     LOG(ERROR) << "No application in package";
335     return Step::Status::INVALID_VALUE;
336   }
337
338   return Step::Status::OK;
339 }
340
341 common_installer::Step::Status StepGenerateXml::process() {
342   bf::path xml_path =
343       bf::path(getUserManifestPath(context_->uid.get(), false))
344       / bf::path(context_->pkgid.get());
345   xml_path += ".xml";
346   context_->xml_path.set(xml_path.string());
347
348   bs::error_code error;
349   if (!bf::exists(xml_path.parent_path(), error)) {
350     if (!common_installer::CreateDir(xml_path.parent_path())) {
351       LOG(ERROR) <<
352           "Directory for manifest xml is missing and cannot be created";
353       return Status::MANIFEST_ERROR;
354     }
355   }
356
357   xmlTextWriterPtr writer;
358   writer = xmlNewTextWriterFilename(context_->xml_path.get().c_str(), 0);
359   if (!writer) {
360     LOG(ERROR) << "Failed to create new file";
361     return Step::Status::MANIFEST_ERROR;
362   }
363
364   xmlTextWriterStartDocument(writer, nullptr, nullptr, nullptr);
365   xmlTextWriterSetIndent(writer, 1);
366
367   Status status = GenerateManifestElement(writer);
368   if (status != Status::OK) {
369     return status;
370   }
371
372   xmlTextWriterEndDocument(writer);
373   xmlFreeTextWriter(writer);
374
375   if (pkgmgr_parser_check_manifest_validation(
376       context_->xml_path.get().c_str()) != 0) {
377     LOG(ERROR) << "Manifest is not valid";
378     return Step::Status::MANIFEST_ERROR;
379   }
380
381   LOG(DEBUG) << "Successfully create manifest xml "
382       << context_->xml_path.get();
383   return Status::OK;
384 }
385
386 common_installer::Step::Status StepGenerateXml::GenerateManifestElement(
387         xmlTextWriterPtr writer) {
388   xmlTextWriterStartElement(writer, BAD_CAST "manifest");
389
390   GenerateManifestElementAttributes(writer);
391   GenerateLangLabels(writer);
392   GenerateAuthor(writer);
393   GenerateDescription(writer);
394   Status status = GenerateApplications(writer);
395   if (status != Status::OK) {
396     return status;
397   }
398   GeneratePrivilege(writer);
399   GenerateAccount(writer);
400   GenerateIme(writer);
401   GenerateProfiles(writer);
402   GenerateShortcuts(writer);
403
404   xmlTextWriterEndElement(writer);
405   return Status::OK;
406 }
407
408 void StepGenerateXml::GenerateManifestElementAttributes(
409         xmlTextWriterPtr writer) {
410   xmlTextWriterWriteAttribute(writer, BAD_CAST "xmlns",
411       BAD_CAST "http://tizen.org/ns/packages");
412   xmlTextWriterWriteAttribute(writer, BAD_CAST "package",
413       BAD_CAST context_->manifest_data.get()->package);
414   xmlTextWriterWriteAttribute(writer, BAD_CAST "type",
415       BAD_CAST context_->manifest_data.get()->type);
416   xmlTextWriterWriteAttribute(writer, BAD_CAST "version",
417       BAD_CAST context_->manifest_data.get()->version);
418   xmlTextWriterWriteAttribute(writer, BAD_CAST "api-version",
419       BAD_CAST context_->manifest_data.get()->api_version);
420   xmlTextWriterWriteAttribute(writer, BAD_CAST "nodisplay-setting",
421       BAD_CAST context_->manifest_data.get()->nodisplay_setting);
422 }
423
424 void StepGenerateXml::GenerateLangLabels(xmlTextWriterPtr writer) {
425   for (label_x* label :
426        GListRange<label_x*>(context_->manifest_data.get()->label)) {
427     if (label->name && strcmp(label->name, "") != 0) {
428       xmlTextWriterStartElement(writer, BAD_CAST "label");
429       if (label->lang && strcmp(DEFAULT_LOCALE, label->lang) != 0) {
430       xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
431                                     BAD_CAST label->lang);
432       }
433       xmlTextWriterWriteString(writer, BAD_CAST label->name);
434       xmlTextWriterEndElement(writer);
435     }
436   }
437 }
438
439 void StepGenerateXml::GenerateAuthor(xmlTextWriterPtr writer) {
440   for (author_x* author :
441        GListRange<author_x*>(context_->manifest_data.get()->author)) {
442     xmlTextWriterStartElement(writer, BAD_CAST "author");
443     if (author->email && strlen(author->email)) {
444       xmlTextWriterWriteAttribute(writer, BAD_CAST "email",
445                                   BAD_CAST author->email);
446     }
447     if (author->href && strlen(author->href)) {
448       xmlTextWriterWriteAttribute(writer, BAD_CAST "href",
449                                   BAD_CAST author->href);
450     }
451     xmlTextWriterWriteString(writer, BAD_CAST author->text);
452     xmlTextWriterEndElement(writer);
453   }
454 }
455
456 void StepGenerateXml::GenerateDescription(xmlTextWriterPtr writer) {
457   for (description_x* description :
458        GListRange<description_x*>(context_->manifest_data.get()->description)) {
459     xmlTextWriterStartElement(writer, BAD_CAST "description");
460     if (description->lang && strcmp(DEFAULT_LOCALE, description->lang) != 0) {
461       xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
462                                   BAD_CAST description->lang);
463     }
464     xmlTextWriterWriteString(writer, BAD_CAST description->text);
465     xmlTextWriterEndElement(writer);
466   }
467 }
468
469 common_installer::Step::Status StepGenerateXml::GenerateApplications(
470         xmlTextWriterPtr writer) {
471   for (application_x* app :
472        GListRange<application_x*>(context_->manifest_data.get()->application)) {
473     AppCompType type;
474     if (strcmp(app->component_type, "uiapp") == 0) {
475       type = AppCompType::UIAPP;
476       xmlTextWriterStartElement(writer, BAD_CAST "ui-application");
477     } else if (strcmp(app->component_type, "svcapp") == 0) {
478       type = AppCompType::SVCAPP;
479       xmlTextWriterStartElement(writer, BAD_CAST "service-application");
480     } else if (strcmp(app->component_type, "widgetapp") == 0) {
481       type = AppCompType::WIDGETAPP;
482       xmlTextWriterStartElement(writer, BAD_CAST "widget-application");
483     } else if (strcmp(app->component_type, "watchapp") == 0) {
484       type = AppCompType::WATCHAPP;
485       xmlTextWriterStartElement(writer, BAD_CAST "watch-application");
486     } else {
487       LOG(ERROR) << "Unknown application component_type";
488       xmlFreeTextWriter(writer);
489       return Status::ERROR;
490     }
491     Status status = GenerateApplicationCommonXml(app, writer, type);
492     if (status != Status::OK) {
493       xmlFreeTextWriter(writer);
494       return status;
495     }
496     xmlTextWriterEndElement(writer);
497   }
498   return Status::OK;
499 }
500
501 void StepGenerateXml::GeneratePrivilege(xmlTextWriterPtr writer) {
502     if (context_->manifest_data.get()->privileges) {
503     xmlTextWriterStartElement(writer, BAD_CAST "privileges");
504     for (const char* priv :
505          GListRange<char*>(context_->manifest_data.get()->privileges)) {
506       xmlTextWriterWriteFormatElement(writer, BAD_CAST "privilege",
507         "%s", BAD_CAST priv);
508     }
509
510     xmlTextWriterEndElement(writer);
511   }
512 }
513
514 void StepGenerateXml::GenerateAccount(xmlTextWriterPtr writer) {
515   const auto& accounts =
516       context_->manifest_plugins_data.get().account_info.get().accounts();
517   if (!accounts.empty()) {
518     xmlTextWriterStartElement(writer, BAD_CAST "account");
519     // add account info
520     for (auto& account : accounts) {
521       xmlTextWriterStartElement(writer, BAD_CAST "account-provider");
522
523       xmlTextWriterWriteAttribute(writer, BAD_CAST "appid",
524                                   BAD_CAST account.appid.c_str());
525
526       if (!account.providerid.empty())
527         xmlTextWriterWriteAttribute(writer, BAD_CAST "providerid",
528                                     BAD_CAST account.providerid.c_str());
529
530       if (account.multiple_account_support)
531         xmlTextWriterWriteAttribute(writer,
532                                     BAD_CAST "multiple-accounts-support",
533                                     BAD_CAST "true");
534       else
535         xmlTextWriterWriteAttribute(writer,
536                                     BAD_CAST "multiple-accounts-support",
537                                     BAD_CAST "false");
538       for (auto& icon_pair : account.icon_paths) {
539         xmlTextWriterStartElement(writer, BAD_CAST "icon");
540         if (icon_pair.first == "AccountSmall")
541           xmlTextWriterWriteAttribute(writer, BAD_CAST "section",
542                                       BAD_CAST "account-small");
543         else
544           xmlTextWriterWriteAttribute(writer, BAD_CAST "section",
545                                       BAD_CAST "account");
546         xmlTextWriterWriteString(writer, BAD_CAST icon_pair.second.c_str());
547         xmlTextWriterEndElement(writer);
548       }
549
550       for (auto& name_pair : account.names) {
551         xmlTextWriterStartElement(writer, BAD_CAST "label");
552         if (!name_pair.second.empty())
553           xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
554                                       BAD_CAST name_pair.second.c_str());
555         xmlTextWriterWriteString(writer, BAD_CAST name_pair.first.c_str());
556         xmlTextWriterEndElement(writer);
557       }
558
559       for (auto& capability : account.capabilities) {
560         xmlTextWriterWriteFormatElement(writer, BAD_CAST "capability",
561           "%s", BAD_CAST capability.c_str());
562       }
563
564       xmlTextWriterEndElement(writer);
565     }
566     xmlTextWriterEndElement(writer);
567   }
568 }
569
570 void StepGenerateXml::GenerateIme(xmlTextWriterPtr writer) {
571   const auto &ime = context_->manifest_plugins_data.get().ime_info.get();
572   const auto ime_uuid = ime.uuid();
573   if (!ime_uuid.empty()) {
574     xmlTextWriterStartElement(writer, BAD_CAST "ime");
575
576     GListRange<application_x*> app_range(
577         context_->manifest_data.get()->application);
578     if (!app_range.Empty()) {
579       // wgt app have ui-application as first application element.
580       // there may be service-applications but not as first element.
581       application_x* app = *app_range.begin();
582       xmlTextWriterWriteAttribute(writer, BAD_CAST "appid",
583                                   BAD_CAST app->appid);
584     }
585
586     xmlTextWriterStartElement(writer, BAD_CAST "uuid");
587     xmlTextWriterWriteString(writer, BAD_CAST ime_uuid.c_str());
588     xmlTextWriterEndElement(writer);
589
590     xmlTextWriterStartElement(writer, BAD_CAST "languages");
591
592     for (auto it = ime.LanguagesBegin(); it != ime.LanguagesEnd(); ++it) {
593       xmlTextWriterStartElement(writer, BAD_CAST "language");
594       xmlTextWriterWriteString(writer, BAD_CAST it->c_str());
595       xmlTextWriterEndElement(writer);
596     }
597
598     xmlTextWriterEndElement(writer);
599
600     xmlTextWriterEndElement(writer);
601   }
602 }
603
604 void StepGenerateXml::GenerateProfiles(xmlTextWriterPtr writer) {
605   for (const char* profile :
606        GListRange<char*>(context_->manifest_data.get()->deviceprofile)) {
607     xmlTextWriterStartElement(writer, BAD_CAST "profile");
608     xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
609                                 BAD_CAST profile);
610     xmlTextWriterEndElement(writer);
611   }
612 }
613
614 void StepGenerateXml::GenerateShortcuts(xmlTextWriterPtr writer) {
615   const auto& shortcuts =
616       context_->manifest_plugins_data.get().shortcut_info.get();
617   if (!shortcuts.empty()) {
618     xmlTextWriterStartElement(writer, BAD_CAST "shortcut-list");
619     for (auto& shortcut : shortcuts) {
620       xmlTextWriterStartElement(writer, BAD_CAST "shortcut");
621       if (!shortcut.app_id.empty())
622         xmlTextWriterWriteAttribute(writer, BAD_CAST "appid",
623                                     BAD_CAST shortcut.app_id.c_str());
624       if (!shortcut.app_id.empty())
625         xmlTextWriterWriteAttribute(writer, BAD_CAST "extra_data",
626                                     BAD_CAST shortcut.extra_data.c_str());
627       if (!shortcut.app_id.empty())
628         xmlTextWriterWriteAttribute(writer, BAD_CAST "extra_key",
629                                     BAD_CAST shortcut.extra_key.c_str());
630       if (!shortcut.icon.empty()) {
631         xmlTextWriterStartElement(writer, BAD_CAST "icon");
632         xmlTextWriterWriteString(writer, BAD_CAST shortcut.icon.c_str());
633         xmlTextWriterEndElement(writer);
634       }
635       for (auto& label : shortcut.labels) {
636         xmlTextWriterStartElement(writer, BAD_CAST "label");
637         if (!label.first.empty())
638           xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
639                                       BAD_CAST label.first.c_str());
640         xmlTextWriterWriteString(writer, BAD_CAST label.second.c_str());
641         xmlTextWriterEndElement(writer);
642       }
643       xmlTextWriterEndElement(writer);
644     }
645     xmlTextWriterEndElement(writer);
646   }
647 }
648
649 }  // namespace pkgmgr
650 }  // namespace wgt