dc4dc715af21eac2f27476d0d8d161a5237540c4
[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   if (app->mainapp)
98     xmlTextWriterWriteAttribute(writer, BAD_CAST "main",
99         BAD_CAST app->mainapp);
100
101   auto& appwidgets = widget_info.app_widgets();
102   const auto& appwidget = std::find_if(appwidgets.begin(), appwidgets.end(),
103                                  [app](const wgt::parse::AppWidget& widget) {
104                                     return widget.id == app->appid;
105                                  });
106   if (appwidget == appwidgets.end())
107     return true;
108
109   // Add extra elements for wgt widget-application
110   if (!appwidget->update_period.empty()) {
111         xmlTextWriterWriteAttribute(writer, BAD_CAST "update-period", BAD_CAST
112             std::to_string(static_cast<int>(
113                     appwidget->update_period.front())).c_str());
114   }
115
116   xmlTextWriterWriteAttribute(writer, BAD_CAST "max-instance",
117       BAD_CAST std::to_string(appwidget->max_instance).c_str());
118
119   for (auto& size : appwidget->content_size) {
120     xmlTextWriterStartElement(writer, BAD_CAST "support-size");
121
122     std::string type = wgt::parse::AppWidgetSizeTypeToString(size.type);
123     if (!size.preview.empty()) {
124       std::string icon_name = shared_path.string() + "/"
125           + appwidget->id + "." + type + "." + "preview" +
126           bf::path(size.preview).extension().string();
127       xmlTextWriterWriteAttribute(writer, BAD_CAST "preview",
128           BAD_CAST icon_name.c_str());  // NOLINT
129     }
130
131     xmlTextWriterWriteAttribute(writer, BAD_CAST "frame",
132                                 BAD_CAST "true");
133     xmlTextWriterWriteString(writer,
134         BAD_CAST type.c_str());
135     xmlTextWriterEndElement(writer);
136   }
137
138   for (auto& pair : appwidget->metadata) {
139     xmlTextWriterStartElement(writer, BAD_CAST "metadata");
140     xmlTextWriterWriteAttribute(writer, BAD_CAST "key",
141                                 BAD_CAST pair.first.c_str());
142     if (!pair.second.empty())
143       xmlTextWriterWriteAttribute(writer, BAD_CAST "value",
144                                   BAD_CAST pair.second.c_str());
145     xmlTextWriterEndElement(writer);
146   }
147   return true;
148 }
149
150 void WriteWatchApplicationAttributes(
151     xmlTextWriterPtr writer, application_x* app) {
152   if (app->support_ambient)
153     xmlTextWriterWriteAttribute(writer, BAD_CAST "ambient-support",
154         BAD_CAST app->support_ambient);
155 }
156
157 }  // namespace
158
159 namespace wgt {
160 namespace pkgmgr {
161
162 common_installer::Step::Status StepGenerateXml::GenerateApplicationCommonXml(
163     application_x* app, xmlTextWriterPtr writer, AppCompType type) {
164   xmlTextWriterWriteAttribute(writer, BAD_CAST "appid", BAD_CAST app->appid);
165
166   // binary is a symbolic link named <appid> and is located in <pkgid>/<appid>
167   bf::path exec_path = context_->GetPkgPath()
168       / bf::path("bin") / bf::path(app->appid);
169   xmlTextWriterWriteAttribute(writer, BAD_CAST "exec",
170                               BAD_CAST exec_path.string().c_str());
171   if (app->type)
172     xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST app->type);
173   else
174     xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST "capp");
175
176   if (app->process_pool && strlen(app->process_pool))
177     xmlTextWriterWriteAttribute(writer, BAD_CAST "process-pool",
178                                 BAD_CAST app->process_pool);
179   // app-specific attributes
180   switch (type) {
181   case AppCompType::UIAPP:
182     WriteUIApplicationAttributes(writer, app);
183     break;
184   case AppCompType::SVCAPP:
185     WriteServiceApplicationAttributes(writer, app);
186     break;
187   case AppCompType::WIDGETAPP:
188     if (!WriteWidgetApplicationAttributesAndElements(writer, app,
189         static_cast<WgtBackendData*>(
190             context_->backend_data.get())->appwidgets.get(),
191         context_->GetPkgPath() / "shared" / "res"))
192       return Status::MANIFEST_ERROR;
193     break;
194   case AppCompType::WATCHAPP:
195     WriteWatchApplicationAttributes(writer, app);
196     break;
197   }
198
199   for (label_x* label : GListRange<label_x*>(app->label)) {
200     if (label->name && strcmp(label->name, "") != 0) {
201       xmlTextWriterStartElement(writer, BAD_CAST "label");
202       if (label->lang && strcmp(DEFAULT_LOCALE, label->lang) != 0) {
203         xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
204                                     BAD_CAST label->lang);
205       }
206       xmlTextWriterWriteString(writer, BAD_CAST label->name);
207       xmlTextWriterEndElement(writer);
208     }
209   }
210
211   for (auto& icon : GListRange<icon_x*>(app->icon)) {
212     xmlTextWriterStartElement(writer, BAD_CAST "icon");
213     if (icon->lang && strcmp(DEFAULT_LOCALE, icon->lang) != 0) {
214       xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
215                                   BAD_CAST icon->lang);
216     }
217     xmlTextWriterWriteString(writer, BAD_CAST icon->text);
218     xmlTextWriterEndElement(writer);
219   }
220
221   for (image_x* image : GListRange<image_x*>(app->image)) {
222     xmlTextWriterStartElement(writer, BAD_CAST "image");
223     if (image->lang && strcmp(DEFAULT_LOCALE, image->lang) != 0) {
224       xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
225
226                                   BAD_CAST image->lang);
227     }
228     if (image->section)
229       xmlTextWriterWriteAttribute(writer, BAD_CAST "section",
230                                   BAD_CAST image->section);
231     xmlTextWriterEndElement(writer);
232   }
233
234   for (appcontrol_x* appc : GListRange<appcontrol_x*>(app->appcontrol)) {
235     xmlTextWriterStartElement(writer, BAD_CAST "app-control");
236
237     if (appc->operation) {
238       xmlTextWriterStartElement(writer, BAD_CAST "operation");
239       xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
240           BAD_CAST appc->operation);
241       xmlTextWriterEndElement(writer);
242     }
243
244     if (appc->uri) {
245       xmlTextWriterStartElement(writer, BAD_CAST "uri");
246       xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
247           BAD_CAST appc->uri);
248       xmlTextWriterEndElement(writer);
249     }
250
251     if (appc->mime) {
252       xmlTextWriterStartElement(writer, BAD_CAST "mime");
253       xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
254           BAD_CAST appc->mime);
255       xmlTextWriterEndElement(writer);
256     }
257
258     xmlTextWriterEndElement(writer);
259   }
260
261   for (datacontrol_x* datacontrol :
262        GListRange<datacontrol_x*>(app->datacontrol)) {
263     xmlTextWriterStartElement(writer, BAD_CAST "datacontrol");
264     if (datacontrol->access) {
265       xmlTextWriterWriteAttribute(writer, BAD_CAST "access",
266           BAD_CAST datacontrol->access);
267     }
268     if (datacontrol->providerid) {
269       xmlTextWriterWriteAttribute(writer, BAD_CAST "providerid",
270           BAD_CAST datacontrol->providerid);
271     }
272     if (datacontrol->type) {
273       xmlTextWriterWriteAttribute(writer, BAD_CAST "type",
274           BAD_CAST datacontrol->type);
275     }
276     xmlTextWriterEndElement(writer);
277   }
278
279   for (metadata_x* meta : GListRange<metadata_x*>(app->metadata)) {
280     xmlTextWriterStartElement(writer, BAD_CAST "metadata");
281     xmlTextWriterWriteAttribute(writer, BAD_CAST "key",
282         BAD_CAST meta->key);
283     if (meta->value)
284       xmlTextWriterWriteAttribute(writer, BAD_CAST "value",
285           BAD_CAST meta->value);
286     xmlTextWriterEndElement(writer);
287   }
288
289   for (const char* category : GListRange<char*>(app->category)) {
290     xmlTextWriterStartElement(writer, BAD_CAST "category");
291     xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST category);
292     xmlTextWriterEndElement(writer);
293   }
294
295   for (const char* background_category : GListRange<char*>(
296       app->background_category)) {
297     xmlTextWriterStartElement(writer, BAD_CAST "background-category");
298     xmlTextWriterWriteAttribute(writer, BAD_CAST "value",
299         BAD_CAST background_category);
300     xmlTextWriterEndElement(writer);
301   }
302
303   return Step::Status::OK;
304 }
305
306 common_installer::Step::Status StepGenerateXml::undo() {
307   common_installer::RequestType req_type = context_->request_type.get();
308   if (req_type == common_installer::RequestType::ManifestDirectUpdate ||
309       req_type == common_installer::RequestType::ManifestPartialUpdate)
310     return Status::OK;
311   common_installer::RemoveAll(context_->xml_path.get());
312   return Status::OK;
313 }
314
315 common_installer::Step::Status StepGenerateXml::precheck() {
316   if (!context_->manifest_data.get()) {
317     LOG(ERROR) << "manifest_data attribute is empty";
318     return Step::Status::INVALID_VALUE;
319   }
320   if (context_->pkgid.get().empty()) {
321     LOG(ERROR) << "pkgid attribute is empty";
322     return Step::Status::PACKAGE_NOT_FOUND;
323   }
324
325   if (!context_->manifest_data.get()->application) {
326     LOG(ERROR) << "No application in package";
327     return Step::Status::INVALID_VALUE;
328   }
329
330   return Step::Status::OK;
331 }
332
333 common_installer::Step::Status StepGenerateXml::process() {
334   bf::path xml_path =
335       bf::path(getUserManifestPath(context_->uid.get(),
336                   context_->is_readonly_package.get()))
337       / bf::path(context_->pkgid.get());
338   xml_path += ".xml";
339   context_->xml_path.set(xml_path.string());
340
341   bs::error_code error;
342   if (!bf::exists(xml_path.parent_path(), error)) {
343     if (!common_installer::CreateDir(xml_path.parent_path())) {
344       LOG(ERROR) <<
345           "Directory for manifest xml is missing and cannot be created";
346       return Status::MANIFEST_ERROR;
347     }
348   }
349
350   xmlTextWriterPtr writer;
351   writer = xmlNewTextWriterFilename(context_->xml_path.get().c_str(), 0);
352   if (!writer) {
353     LOG(ERROR) << "Failed to create new file";
354     return Step::Status::MANIFEST_ERROR;
355   }
356
357   xmlTextWriterStartDocument(writer, nullptr, nullptr, nullptr);
358   xmlTextWriterSetIndent(writer, 1);
359
360   Status status = GenerateManifestElement(writer);
361   if (status != Status::OK)
362     return status;
363
364   xmlTextWriterEndDocument(writer);
365   xmlFreeTextWriter(writer);
366
367   if (pkgmgr_parser_check_manifest_validation(
368       context_->xml_path.get().c_str()) != 0) {
369     LOG(ERROR) << "Manifest is not valid";
370     return Step::Status::MANIFEST_ERROR;
371   }
372
373   LOG(DEBUG) << "Successfully create manifest xml "
374       << context_->xml_path.get();
375   return Status::OK;
376 }
377
378 common_installer::Step::Status StepGenerateXml::GenerateManifestElement(
379         xmlTextWriterPtr writer) {
380   xmlTextWriterStartElement(writer, BAD_CAST "manifest");
381
382   GenerateManifestElementAttributes(writer);
383   GenerateLangLabels(writer);
384   GenerateAuthor(writer);
385   GenerateDescription(writer);
386   Status status = GenerateApplications(writer);
387   if (status != Status::OK)
388     return status;
389
390   GeneratePrivilege(writer);
391   GenerateProvidesAppDefinedPrivilege(writer);
392   GenerateAccount(writer);
393   GenerateIme(writer);
394   GenerateProfiles(writer);
395   GenerateShortcuts(writer);
396   GenerateTrustAnchor(writer);
397   xmlTextWriterEndElement(writer);
398   return Status::OK;
399 }
400
401 void StepGenerateXml::GenerateManifestElementAttributes(
402         xmlTextWriterPtr writer) {
403   xmlTextWriterWriteAttribute(writer, BAD_CAST "xmlns",
404       BAD_CAST "http://tizen.org/ns/packages");
405   xmlTextWriterWriteAttribute(writer, BAD_CAST "package",
406       BAD_CAST context_->manifest_data.get()->package);
407   xmlTextWriterWriteAttribute(writer, BAD_CAST "type",
408       BAD_CAST context_->manifest_data.get()->type);
409   xmlTextWriterWriteAttribute(writer, BAD_CAST "version",
410       BAD_CAST context_->manifest_data.get()->version);
411   xmlTextWriterWriteAttribute(writer, BAD_CAST "api-version",
412       BAD_CAST context_->manifest_data.get()->api_version);
413   xmlTextWriterWriteAttribute(writer, BAD_CAST "nodisplay-setting",
414       BAD_CAST context_->manifest_data.get()->nodisplay_setting);
415   if (context_->is_readonly_package.get()) {
416     xmlTextWriterWriteAttribute(writer, BAD_CAST "readonly", BAD_CAST "true");
417     xmlTextWriterWriteAttribute(writer, BAD_CAST "preload", BAD_CAST "true");
418   } else if (context_->is_preload_rw_package.get()) {
419     xmlTextWriterWriteAttribute(writer, BAD_CAST "preload", BAD_CAST "true");
420   }
421 }
422
423 void StepGenerateXml::GenerateLangLabels(xmlTextWriterPtr writer) {
424   for (label_x* label :
425        GListRange<label_x*>(context_->manifest_data.get()->label)) {
426     if (label->name && strcmp(label->name, "") != 0) {
427       xmlTextWriterStartElement(writer, BAD_CAST "label");
428       if (label->lang && strcmp(DEFAULT_LOCALE, label->lang) != 0) {
429       xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
430                                     BAD_CAST label->lang);
431       }
432       xmlTextWriterWriteString(writer, BAD_CAST label->name);
433       xmlTextWriterEndElement(writer);
434     }
435   }
436 }
437
438 void StepGenerateXml::GenerateAuthor(xmlTextWriterPtr writer) {
439   for (author_x* author :
440        GListRange<author_x*>(context_->manifest_data.get()->author)) {
441     xmlTextWriterStartElement(writer, BAD_CAST "author");
442     if (author->email && strlen(author->email)) {
443       xmlTextWriterWriteAttribute(writer, BAD_CAST "email",
444                                   BAD_CAST author->email);
445     }
446     if (author->href && strlen(author->href)) {
447       xmlTextWriterWriteAttribute(writer, BAD_CAST "href",
448                                   BAD_CAST author->href);
449     }
450     xmlTextWriterWriteString(writer, BAD_CAST author->text);
451     xmlTextWriterEndElement(writer);
452   }
453 }
454
455 void StepGenerateXml::GenerateDescription(xmlTextWriterPtr writer) {
456   for (description_x* description :
457        GListRange<description_x*>(context_->manifest_data.get()->description)) {
458     xmlTextWriterStartElement(writer, BAD_CAST "description");
459     if (description->lang && strcmp(DEFAULT_LOCALE, description->lang) != 0) {
460       xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
461                                   BAD_CAST description->lang);
462     }
463     xmlTextWriterWriteString(writer, BAD_CAST description->text);
464     xmlTextWriterEndElement(writer);
465   }
466 }
467
468 common_installer::Step::Status StepGenerateXml::GenerateApplications(
469         xmlTextWriterPtr writer) {
470   for (application_x* app :
471        GListRange<application_x*>(context_->manifest_data.get()->application)) {
472     AppCompType type;
473     if (strcmp(app->component_type, "uiapp") == 0) {
474       type = AppCompType::UIAPP;
475       xmlTextWriterStartElement(writer, BAD_CAST "ui-application");
476     } else if (strcmp(app->component_type, "svcapp") == 0) {
477       type = AppCompType::SVCAPP;
478       xmlTextWriterStartElement(writer, BAD_CAST "service-application");
479     } else if (strcmp(app->component_type, "widgetapp") == 0) {
480       type = AppCompType::WIDGETAPP;
481       xmlTextWriterStartElement(writer, BAD_CAST "widget-application");
482     } else if (strcmp(app->component_type, "watchapp") == 0) {
483       type = AppCompType::WATCHAPP;
484       xmlTextWriterStartElement(writer, BAD_CAST "watch-application");
485     } else {
486       LOG(ERROR) << "Unknown application component_type";
487       xmlFreeTextWriter(writer);
488       return Status::ERROR;
489     }
490     Status status = GenerateApplicationCommonXml(app, writer, type);
491     if (status != Status::OK) {
492       xmlFreeTextWriter(writer);
493       return status;
494     }
495     xmlTextWriterEndElement(writer);
496   }
497   return Status::OK;
498 }
499
500 void StepGenerateXml::GeneratePrivilege(xmlTextWriterPtr writer) {
501   if (context_->manifest_data.get()->privileges) {
502     xmlTextWriterStartElement(writer, BAD_CAST "privileges");
503     for (privilege_x* priv :
504          GListRange<privilege_x*>(context_->manifest_data.get()->privileges)) {
505       xmlTextWriterStartElement(writer, BAD_CAST "privilege");
506       xmlTextWriterWriteAttribute(writer, BAD_CAST "type",
507                                   BAD_CAST priv->type);
508       xmlTextWriterWriteString(writer, BAD_CAST priv->value);
509       xmlTextWriterEndElement(writer);
510     }
511     if (context_->manifest_data.get()->appdefined_privileges) {
512       for (appdefined_privilege_x* priv : GListRange<appdefined_privilege_x*>(
513            context_->manifest_data.get()->appdefined_privileges)) {
514         xmlTextWriterStartElement(writer, BAD_CAST "appdefined-privilege");
515         xmlTextWriterWriteAttribute(writer, BAD_CAST "license",
516                                     BAD_CAST priv->license);
517         xmlTextWriterWriteAttribute(writer, BAD_CAST "type",
518                                     BAD_CAST priv->type);
519         xmlTextWriterWriteString(writer, BAD_CAST priv->value);
520         xmlTextWriterEndElement(writer);
521       }
522     }
523     xmlTextWriterEndElement(writer);
524   }
525 }
526
527 void StepGenerateXml::GenerateProvidesAppDefinedPrivilege(
528     xmlTextWriterPtr writer) {
529   if (context_->manifest_data.get()->provides_appdefined_privileges) {
530     xmlTextWriterStartElement(writer,
531                               BAD_CAST "provides-appdefined-privileges");
532     for (appdefined_privilege_x* priv : GListRange<appdefined_privilege_x*>(
533          context_->manifest_data.get()->provides_appdefined_privileges)) {
534       xmlTextWriterStartElement(writer, BAD_CAST "appdefined-privilege");
535       xmlTextWriterWriteAttribute(writer, BAD_CAST "license",
536                                   BAD_CAST priv->license);
537       xmlTextWriterWriteAttribute(writer, BAD_CAST "type",
538                                   BAD_CAST priv->type);
539       xmlTextWriterWriteString(writer, BAD_CAST priv->value);
540       xmlTextWriterEndElement(writer);
541     }
542     xmlTextWriterEndElement(writer);
543   }
544 }
545
546 void StepGenerateXml::GenerateAccount(xmlTextWriterPtr writer) {
547   const auto& accounts =
548       context_->manifest_plugins_data.get().account_info.get().accounts();
549   if (!accounts.empty()) {
550     xmlTextWriterStartElement(writer, BAD_CAST "account");
551     // add account info
552     for (auto& account : accounts) {
553       xmlTextWriterStartElement(writer, BAD_CAST "account-provider");
554
555       xmlTextWriterWriteAttribute(writer, BAD_CAST "appid",
556                                   BAD_CAST account.appid.c_str());
557
558       if (!account.providerid.empty())
559         xmlTextWriterWriteAttribute(writer, BAD_CAST "providerid",
560                                     BAD_CAST account.providerid.c_str());
561
562       if (account.multiple_account_support)
563         xmlTextWriterWriteAttribute(writer,
564                                     BAD_CAST "multiple-accounts-support",
565                                     BAD_CAST "true");
566       else
567         xmlTextWriterWriteAttribute(writer,
568                                     BAD_CAST "multiple-accounts-support",
569                                     BAD_CAST "false");
570       for (auto& icon_pair : account.icon_paths) {
571         xmlTextWriterStartElement(writer, BAD_CAST "icon");
572         if (icon_pair.first == "AccountSmall")
573           xmlTextWriterWriteAttribute(writer, BAD_CAST "section",
574                                       BAD_CAST "account-small");
575         else
576           xmlTextWriterWriteAttribute(writer, BAD_CAST "section",
577                                       BAD_CAST "account");
578         xmlTextWriterWriteString(writer, BAD_CAST icon_pair.second.c_str());
579         xmlTextWriterEndElement(writer);
580       }
581
582       for (auto& name_pair : account.names) {
583         xmlTextWriterStartElement(writer, BAD_CAST "label");
584         if (!name_pair.second.empty())
585           xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
586                                       BAD_CAST name_pair.second.c_str());
587         xmlTextWriterWriteString(writer, BAD_CAST name_pair.first.c_str());
588         xmlTextWriterEndElement(writer);
589       }
590
591       for (auto& capability : account.capabilities) {
592         xmlTextWriterWriteFormatElement(writer, BAD_CAST "capability",
593           "%s", BAD_CAST capability.c_str());
594       }
595
596       xmlTextWriterEndElement(writer);
597     }
598     xmlTextWriterEndElement(writer);
599   }
600 }
601
602 void StepGenerateXml::GenerateIme(xmlTextWriterPtr writer) {
603   const auto &ime = context_->manifest_plugins_data.get().ime_info.get();
604   const auto ime_uuid = ime.uuid();
605   if (!ime_uuid.empty()) {
606     xmlTextWriterStartElement(writer, BAD_CAST "ime");
607
608     GListRange<application_x*> app_range(
609         context_->manifest_data.get()->application);
610     if (!app_range.Empty()) {
611       // wgt app have ui-application as first application element.
612       // there may be service-applications but not as first element.
613       application_x* app = *app_range.begin();
614       xmlTextWriterWriteAttribute(writer, BAD_CAST "appid",
615                                   BAD_CAST app->appid);
616     }
617
618     xmlTextWriterStartElement(writer, BAD_CAST "uuid");
619     xmlTextWriterWriteString(writer, BAD_CAST ime_uuid.c_str());
620     xmlTextWriterEndElement(writer);
621
622     xmlTextWriterStartElement(writer, BAD_CAST "languages");
623
624     for (auto it = ime.LanguagesBegin(); it != ime.LanguagesEnd(); ++it) {
625       xmlTextWriterStartElement(writer, BAD_CAST "language");
626       xmlTextWriterWriteString(writer, BAD_CAST it->c_str());
627       xmlTextWriterEndElement(writer);
628     }
629
630     xmlTextWriterEndElement(writer);
631
632     xmlTextWriterEndElement(writer);
633   }
634 }
635
636 void StepGenerateXml::GenerateProfiles(xmlTextWriterPtr writer) {
637   for (const char* profile :
638        GListRange<char*>(context_->manifest_data.get()->deviceprofile)) {
639     xmlTextWriterStartElement(writer, BAD_CAST "profile");
640     xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
641                                 BAD_CAST profile);
642     xmlTextWriterEndElement(writer);
643   }
644 }
645
646 void StepGenerateXml::GenerateShortcuts(xmlTextWriterPtr writer) {
647   const auto& shortcuts =
648       context_->manifest_plugins_data.get().shortcut_info.get();
649   if (!shortcuts.empty()) {
650     xmlTextWriterStartElement(writer, BAD_CAST "shortcut-list");
651     for (auto& shortcut : shortcuts) {
652       xmlTextWriterStartElement(writer, BAD_CAST "shortcut");
653       if (!shortcut.app_id.empty())
654         xmlTextWriterWriteAttribute(writer, BAD_CAST "appid",
655                                     BAD_CAST shortcut.app_id.c_str());
656       if (!shortcut.extra_data.empty())
657         xmlTextWriterWriteAttribute(writer, BAD_CAST "extra_data",
658                                     BAD_CAST shortcut.extra_data.c_str());
659       if (!shortcut.extra_key.empty())
660         xmlTextWriterWriteAttribute(writer, BAD_CAST "extra_key",
661                                     BAD_CAST shortcut.extra_key.c_str());
662       if (!shortcut.icon.empty()) {
663         xmlTextWriterStartElement(writer, BAD_CAST "icon");
664         xmlTextWriterWriteString(writer, BAD_CAST shortcut.icon.c_str());
665         xmlTextWriterEndElement(writer);
666       }
667       for (auto& label : shortcut.labels) {
668         xmlTextWriterStartElement(writer, BAD_CAST "label");
669         if (!label.first.empty())
670           xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
671                                       BAD_CAST label.first.c_str());
672         xmlTextWriterWriteString(writer, BAD_CAST label.second.c_str());
673         xmlTextWriterEndElement(writer);
674       }
675       xmlTextWriterEndElement(writer);
676     }
677     xmlTextWriterEndElement(writer);
678   }
679 }
680
681 void StepGenerateXml::GenerateTrustAnchor(xmlTextWriterPtr writer) {
682   if (!context_->manifest_data.get()->use_system_certs)
683     return;
684
685   xmlTextWriterStartElement(writer, BAD_CAST "trust-anchor");
686   xmlTextWriterWriteAttribute(writer, BAD_CAST "use-system-certs",
687       BAD_CAST context_->manifest_data.get()->use_system_certs);
688
689   xmlTextWriterEndElement(writer);
690 }
691
692 }  // namespace pkgmgr
693 }  // namespace wgt