Replace pkg_path with GetPkgPath() method in InstallerContext
[platform/core/appfw/wgt-backend.git] / src / wgt / step / pkgmgr / step_generate_xml.cc
index 614009e..64a2303 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <common/utils/file_util.h>
 #include <common/utils/glist_range.h>
+#include <common/privileges.h>
 
 #include <libxml/parser.h>
 #include <libxml/xmlreader.h>
 #include <cstring>
 #include <string>
 
-#include "wgt/step/common/privileges.h"
+#include "wgt/wgt_backend_data.h"
 
 namespace bs = boost::system;
 namespace bf = boost::filesystem;
 
 namespace {
 
+const char kResWgt[] = "res/wgt";
+const char kSharedRes[] = "shared/res";
+
 void WriteUIApplicationAttributes(
     xmlTextWriterPtr writer, application_x *app) {
-  xmlTextWriterWriteAttribute(writer, BAD_CAST "taskmanage",
-      BAD_CAST "true");
+  if (app->taskmanage)
+    xmlTextWriterWriteAttribute(writer, BAD_CAST "taskmanage",
+        BAD_CAST app->taskmanage);
   if (app->nodisplay)
     xmlTextWriterWriteAttribute(writer, BAD_CAST "nodisplay",
         BAD_CAST app->nodisplay);
@@ -74,25 +79,80 @@ void WriteServiceApplicationAttributes(
       BAD_CAST(app->autorestart ? app->autorestart : "false"));
   xmlTextWriterWriteAttribute(writer, BAD_CAST "on-boot",
       BAD_CAST(app->onboot ? app->onboot : "false"));
-  xmlTextWriterWriteAttribute(writer, BAD_CAST "taskmanage",
-      BAD_CAST "false");
+  if (app->taskmanage)
+      xmlTextWriterWriteAttribute(writer, BAD_CAST "taskmanage",
+         BAD_CAST app->taskmanage);
 }
 
-void WriteWidgetApplicationAttributes(
-    xmlTextWriterPtr writer, application_x *app) {
+bool WriteWidgetApplicationAttributesAndElements(
+    xmlTextWriterPtr writer, application_x *app,
+    const wgt::parse::AppWidgetInfo& widget_info,
+    const bf::path& shared_path) {
   if (app->nodisplay)
     xmlTextWriterWriteAttribute(writer, BAD_CAST "nodisplay",
         BAD_CAST app->nodisplay);
   if (app->multiple)
     xmlTextWriterWriteAttribute(writer, BAD_CAST "multiple",
         BAD_CAST app->multiple);
+  if (app->mainapp)
+    xmlTextWriterWriteAttribute(writer, BAD_CAST "main",
+        BAD_CAST app->mainapp);
+
+  auto& appwidgets = widget_info.app_widgets();
+  const auto& appwidget = std::find_if(appwidgets.begin(), appwidgets.end(),
+                                 [app](const wgt::parse::AppWidget& widget) {
+                                    return widget.id == app->appid;
+                                 });
+  if (appwidget == appwidgets.end()) {
+    return true;
+  }
+
+  // Add extra elements for wgt widget-application
+  if (!appwidget->update_period.empty()) {
+        xmlTextWriterWriteAttribute(writer, BAD_CAST "update-period", BAD_CAST
+            std::to_string(static_cast<int>(
+                    appwidget->update_period.front())).c_str());
+  }
+
+  xmlTextWriterWriteAttribute(writer, BAD_CAST "max-instance",
+      BAD_CAST std::to_string(appwidget->max_instance).c_str());
+
+  for (auto& size : appwidget->content_size) {
+    xmlTextWriterStartElement(writer, BAD_CAST "support-size");
+
+    std::string type = wgt::parse::AppWidgetSizeTypeToString(size.type);
+    if (!size.preview.empty()) {
+      std::string icon_name = shared_path.string() + "/"
+          + appwidget->id + "." + type + "." + "preview" +
+          bf::path(size.preview).extension().string();
+      xmlTextWriterWriteAttribute(writer, BAD_CAST "preview",
+          BAD_CAST icon_name.c_str());  // NOLINT
+    }
+
+    xmlTextWriterWriteAttribute(writer, BAD_CAST "frame",
+                                BAD_CAST "true");
+    xmlTextWriterWriteString(writer,
+        BAD_CAST type.c_str());
+    xmlTextWriterEndElement(writer);
+  }
+
+  for (auto& pair : appwidget->metadata) {
+    xmlTextWriterStartElement(writer, BAD_CAST "metadata");
+    xmlTextWriterWriteAttribute(writer, BAD_CAST "key",
+                                BAD_CAST pair.first.c_str());
+    if (!pair.second.empty())
+      xmlTextWriterWriteAttribute(writer, BAD_CAST "value",
+                                  BAD_CAST pair.second.c_str());
+    xmlTextWriterEndElement(writer);
+  }
+  return true;
 }
 
 void WriteWatchApplicationAttributes(
-    xmlTextWriterPtr writer, application_x *app) {
-  if (app->ambient_support)
+    xmlTextWriterPtr writer, application_xapp) {
+  if (app->support_ambient)
     xmlTextWriterWriteAttribute(writer, BAD_CAST "ambient-support",
-        BAD_CAST app->ambient_support);
+        BAD_CAST app->support_ambient);
 }
 
 }  // namespace
@@ -105,7 +165,7 @@ common_installer::Step::Status StepGenerateXml::GenerateApplicationCommonXml(
   xmlTextWriterWriteAttribute(writer, BAD_CAST "appid", BAD_CAST app->appid);
 
   // binary is a symbolic link named <appid> and is located in <pkgid>/<appid>
-  bf::path exec_path = context_->pkg_path.get()
+  bf::path exec_path = context_->GetPkgPath()
       / bf::path("bin") / bf::path(app->appid);
   xmlTextWriterWriteAttribute(writer, BAD_CAST "exec",
                               BAD_CAST exec_path.string().c_str());
@@ -126,7 +186,11 @@ common_installer::Step::Status StepGenerateXml::GenerateApplicationCommonXml(
     WriteServiceApplicationAttributes(writer, app);
     break;
   case AppCompType::WIDGETAPP:
-    WriteWidgetApplicationAttributes(writer, app);
+    if (!WriteWidgetApplicationAttributesAndElements(writer, app,
+        static_cast<WgtBackendData*>(
+            context_->backend_data.get())->appwidgets.get(),
+        context_->GetPkgPath() / "shared" / "res"))
+      return Status::MANIFEST_ERROR;
     break;
   case AppCompType::WATCHAPP:
     WriteWatchApplicationAttributes(writer, app);
@@ -134,22 +198,25 @@ common_installer::Step::Status StepGenerateXml::GenerateApplicationCommonXml(
   }
 
   for (label_x* label : GListRange<label_x*>(app->label)) {
-    xmlTextWriterStartElement(writer, BAD_CAST "label");
-    if (label->lang && strcmp(DEFAULT_LOCALE, label->lang) != 0) {
-      xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
-                                  BAD_CAST label->lang);
+    if (label->name && strcmp(label->name, "") != 0) {
+      xmlTextWriterStartElement(writer, BAD_CAST "label");
+      if (label->lang && strcmp(DEFAULT_LOCALE, label->lang) != 0) {
+        xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
+                                    BAD_CAST label->lang);
+      }
+      xmlTextWriterWriteString(writer, BAD_CAST label->name);
+      xmlTextWriterEndElement(writer);
     }
-    xmlTextWriterWriteString(writer, BAD_CAST label->name);
-    xmlTextWriterEndElement(writer);
   }
 
-  if (app->icon) {
-    icon_x* iconx = reinterpret_cast<icon_x*>(app->icon->data);
-    xmlTextWriterWriteFormatElement(
-        writer, BAD_CAST "icon", "%s", BAD_CAST iconx->text);
-  } else {
-    // Default icon setting is role of the platform
-    LOG(DEBUG) << "Icon was not found in application";
+  for (auto& icon : GListRange<icon_x*>(app->icon)) {
+    xmlTextWriterStartElement(writer, BAD_CAST "icon");
+    if (icon->lang && strcmp(DEFAULT_LOCALE, icon->lang) != 0) {
+      xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
+                                  BAD_CAST icon->lang);
+    }
+    xmlTextWriterWriteString(writer, BAD_CAST icon->text);
+    xmlTextWriterEndElement(writer);
   }
 
   for (image_x* image : GListRange<image_x*>(app->image)) {
@@ -237,6 +304,11 @@ common_installer::Step::Status StepGenerateXml::GenerateApplicationCommonXml(
   return Step::Status::OK;
 }
 
+common_installer::Step::Status StepGenerateXml::undo() {
+  common_installer::RemoveAll(context_->xml_path.get());
+  return Status::OK;
+}
+
 common_installer::Step::Status StepGenerateXml::precheck() {
   if (!context_->manifest_data.get()) {
     LOG(ERROR) << "manifest_data attribute is empty";
@@ -244,20 +316,21 @@ common_installer::Step::Status StepGenerateXml::precheck() {
   }
   if (context_->pkgid.get().empty()) {
     LOG(ERROR) << "pkgid attribute is empty";
-    return Step::Status::PACKAGE_NOT_FOUND;   }
+    return Step::Status::PACKAGE_NOT_FOUND;
+  }
 
   if (!context_->manifest_data.get()->application) {
     LOG(ERROR) << "No application in package";
     return Step::Status::INVALID_VALUE;
   }
-  // TODO(p.sikorski) check context_->uid.get()
 
   return Step::Status::OK;
 }
 
 common_installer::Step::Status StepGenerateXml::process() {
   bf::path xml_path =
-      bf::path(getUserManifestPath(context_->uid.get(), false))
+      bf::path(getUserManifestPath(context_->uid.get(),
+                  context_->is_readonly_package.get()))
       / bf::path(context_->pkgid.get());
   xml_path += ".xml";
   context_->xml_path.set(xml_path.string());
@@ -272,7 +345,6 @@ common_installer::Step::Status StepGenerateXml::process() {
   }
 
   xmlTextWriterPtr writer;
-
   writer = xmlNewTextWriterFilename(context_->xml_path.get().c_str(), 0);
   if (!writer) {
     LOG(ERROR) << "Failed to create new file";
@@ -280,12 +352,52 @@ common_installer::Step::Status StepGenerateXml::process() {
   }
 
   xmlTextWriterStartDocument(writer, nullptr, nullptr, nullptr);
-
   xmlTextWriterSetIndent(writer, 1);
 
-  // add manifest Element
+  Status status = GenerateManifestElement(writer);
+  if (status != Status::OK) {
+    return status;
+  }
+
+  xmlTextWriterEndDocument(writer);
+  xmlFreeTextWriter(writer);
+
+  if (pkgmgr_parser_check_manifest_validation(
+      context_->xml_path.get().c_str()) != 0) {
+    LOG(ERROR) << "Manifest is not valid";
+    return Step::Status::MANIFEST_ERROR;
+  }
+
+  LOG(DEBUG) << "Successfully create manifest xml "
+      << context_->xml_path.get();
+  return Status::OK;
+}
+
+common_installer::Step::Status StepGenerateXml::GenerateManifestElement(
+        xmlTextWriterPtr writer) {
   xmlTextWriterStartElement(writer, BAD_CAST "manifest");
 
+  GenerateManifestElementAttributes(writer);
+  GenerateLangLabels(writer);
+  GenerateAuthor(writer);
+  GenerateDescription(writer);
+  Status status = GenerateApplications(writer);
+  if (status != Status::OK) {
+    return status;
+  }
+  GeneratePrivilege(writer);
+  GenerateProvidesAppDefinedPrivilege(writer);
+  GenerateAccount(writer);
+  GenerateIme(writer);
+  GenerateProfiles(writer);
+  GenerateShortcuts(writer);
+  GenerateTrustAnchor(writer);
+  xmlTextWriterEndElement(writer);
+  return Status::OK;
+}
+
+void StepGenerateXml::GenerateManifestElementAttributes(
+        xmlTextWriterPtr writer) {
   xmlTextWriterWriteAttribute(writer, BAD_CAST "xmlns",
       BAD_CAST "http://tizen.org/ns/packages");
   xmlTextWriterWriteAttribute(writer, BAD_CAST "package",
@@ -298,18 +410,30 @@ common_installer::Step::Status StepGenerateXml::process() {
       BAD_CAST context_->manifest_data.get()->api_version);
   xmlTextWriterWriteAttribute(writer, BAD_CAST "nodisplay-setting",
       BAD_CAST context_->manifest_data.get()->nodisplay_setting);
+  if (context_->is_readonly_package.get()) {
+    xmlTextWriterWriteAttribute(writer, BAD_CAST "readonly", BAD_CAST "true");
+    xmlTextWriterWriteAttribute(writer, BAD_CAST "preload", BAD_CAST "true");
+  } else if (context_->is_preload_rw_package.get()) {
+    xmlTextWriterWriteAttribute(writer, BAD_CAST "preload", BAD_CAST "true");
+  }
+}
 
+void StepGenerateXml::GenerateLangLabels(xmlTextWriterPtr writer) {
   for (label_x* label :
        GListRange<label_x*>(context_->manifest_data.get()->label)) {
-    xmlTextWriterStartElement(writer, BAD_CAST "label");
-    if (label->lang && strcmp(DEFAULT_LOCALE, label->lang) != 0) {
+    if (label->name && strcmp(label->name, "") != 0) {
+      xmlTextWriterStartElement(writer, BAD_CAST "label");
+      if (label->lang && strcmp(DEFAULT_LOCALE, label->lang) != 0) {
       xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
-                                  BAD_CAST label->lang);
+                                    BAD_CAST label->lang);
+      }
+      xmlTextWriterWriteString(writer, BAD_CAST label->name);
+      xmlTextWriterEndElement(writer);
     }
-    xmlTextWriterWriteString(writer, BAD_CAST label->name);
-    xmlTextWriterEndElement(writer);
   }
+}
 
+void StepGenerateXml::GenerateAuthor(xmlTextWriterPtr writer) {
   for (author_x* author :
        GListRange<author_x*>(context_->manifest_data.get()->author)) {
     xmlTextWriterStartElement(writer, BAD_CAST "author");
@@ -324,7 +448,9 @@ common_installer::Step::Status StepGenerateXml::process() {
     xmlTextWriterWriteString(writer, BAD_CAST author->text);
     xmlTextWriterEndElement(writer);
   }
+}
 
+void StepGenerateXml::GenerateDescription(xmlTextWriterPtr writer) {
   for (description_x* description :
        GListRange<description_x*>(context_->manifest_data.get()->description)) {
     xmlTextWriterStartElement(writer, BAD_CAST "description");
@@ -335,8 +461,10 @@ common_installer::Step::Status StepGenerateXml::process() {
     xmlTextWriterWriteString(writer, BAD_CAST description->text);
     xmlTextWriterEndElement(writer);
   }
+}
 
-  // add application
+common_installer::Step::Status StepGenerateXml::GenerateApplications(
+        xmlTextWriterPtr writer) {
   for (application_x* app :
        GListRange<application_x*>(context_->manifest_data.get()->application)) {
     AppCompType type;
@@ -357,25 +485,63 @@ common_installer::Step::Status StepGenerateXml::process() {
       xmlFreeTextWriter(writer);
       return Status::ERROR;
     }
-    GenerateApplicationCommonXml(app, writer, type);
+    Status status = GenerateApplicationCommonXml(app, writer, type);
+    if (status != Status::OK) {
+      xmlFreeTextWriter(writer);
+      return status;
+    }
     xmlTextWriterEndElement(writer);
   }
+  return Status::OK;
+}
 
-  const auto &ime = context_->manifest_plugins_data.get().ime_info.get();
-  const auto ime_uuid = ime.uuid();
-
-  // add privilege element
+void StepGenerateXml::GeneratePrivilege(xmlTextWriterPtr writer) {
   if (context_->manifest_data.get()->privileges) {
     xmlTextWriterStartElement(writer, BAD_CAST "privileges");
-    for (const char* priv :
-         GListRange<char*>(context_->manifest_data.get()->privileges)) {
-      xmlTextWriterWriteFormatElement(writer, BAD_CAST "privilege",
-        "%s", BAD_CAST priv);
+    for (privilege_x* priv :
+         GListRange<privilege_x*>(context_->manifest_data.get()->privileges)) {
+      xmlTextWriterStartElement(writer, BAD_CAST "privilege");
+      xmlTextWriterWriteAttribute(writer, BAD_CAST "type",
+                                  BAD_CAST priv->type);
+      xmlTextWriterWriteString(writer, BAD_CAST priv->value);
+      xmlTextWriterEndElement(writer);
     }
+    if (context_->manifest_data.get()->appdefined_privileges) {
+      for (appdefined_privilege_x* priv : GListRange<appdefined_privilege_x*>(
+           context_->manifest_data.get()->appdefined_privileges)) {
+        xmlTextWriterStartElement(writer, BAD_CAST "appdefined-privilege");
+        xmlTextWriterWriteAttribute(writer, BAD_CAST "license",
+                                    BAD_CAST priv->license);
+        xmlTextWriterWriteAttribute(writer, BAD_CAST "type",
+                                    BAD_CAST priv->type);
+        xmlTextWriterWriteString(writer, BAD_CAST priv->value);
+        xmlTextWriterEndElement(writer);
+      }
+    }
+    xmlTextWriterEndElement(writer);
+  }
+}
 
+void StepGenerateXml::GenerateProvidesAppDefinedPrivilege(
+    xmlTextWriterPtr writer) {
+  if (context_->manifest_data.get()->provides_appdefined_privileges) {
+    xmlTextWriterStartElement(writer,
+                              BAD_CAST "provides-appdefined-privileges");
+    for (appdefined_privilege_x* priv : GListRange<appdefined_privilege_x*>(
+         context_->manifest_data.get()->provides_appdefined_privileges)) {
+      xmlTextWriterStartElement(writer, BAD_CAST "appdefined-privilege");
+      xmlTextWriterWriteAttribute(writer, BAD_CAST "license",
+                                  BAD_CAST priv->license);
+      xmlTextWriterWriteAttribute(writer, BAD_CAST "type",
+                                  BAD_CAST priv->type);
+      xmlTextWriterWriteString(writer, BAD_CAST priv->value);
+      xmlTextWriterEndElement(writer);
+    }
     xmlTextWriterEndElement(writer);
   }
+}
 
+void StepGenerateXml::GenerateAccount(xmlTextWriterPtr writer) {
   const auto& accounts =
       context_->manifest_plugins_data.get().account_info.get().accounts();
   if (!accounts.empty()) {
@@ -395,6 +561,10 @@ common_installer::Step::Status StepGenerateXml::process() {
         xmlTextWriterWriteAttribute(writer,
                                     BAD_CAST "multiple-accounts-support",
                                     BAD_CAST "true");
+      else
+        xmlTextWriterWriteAttribute(writer,
+                                    BAD_CAST "multiple-accounts-support",
+                                    BAD_CAST "false");
       for (auto& icon_pair : account.icon_paths) {
         xmlTextWriterStartElement(writer, BAD_CAST "icon");
         if (icon_pair.first == "AccountSmall")
@@ -425,7 +595,11 @@ common_installer::Step::Status StepGenerateXml::process() {
     }
     xmlTextWriterEndElement(writer);
   }
+}
 
+void StepGenerateXml::GenerateIme(xmlTextWriterPtr writer) {
+  const auto &ime = context_->manifest_plugins_data.get().ime_info.get();
+  const auto ime_uuid = ime.uuid();
   if (!ime_uuid.empty()) {
     xmlTextWriterStartElement(writer, BAD_CAST "ime");
 
@@ -455,7 +629,9 @@ common_installer::Step::Status StepGenerateXml::process() {
 
     xmlTextWriterEndElement(writer);
   }
+}
 
+void StepGenerateXml::GenerateProfiles(xmlTextWriterPtr writer) {
   for (const char* profile :
        GListRange<char*>(context_->manifest_data.get()->deviceprofile)) {
     xmlTextWriterStartElement(writer, BAD_CAST "profile");
@@ -463,7 +639,9 @@ common_installer::Step::Status StepGenerateXml::process() {
                                 BAD_CAST profile);
     xmlTextWriterEndElement(writer);
   }
+}
 
+void StepGenerateXml::GenerateShortcuts(xmlTextWriterPtr writer) {
   const auto& shortcuts =
       context_->manifest_plugins_data.get().shortcut_info.get();
   if (!shortcuts.empty()) {
@@ -473,10 +651,10 @@ common_installer::Step::Status StepGenerateXml::process() {
       if (!shortcut.app_id.empty())
         xmlTextWriterWriteAttribute(writer, BAD_CAST "appid",
                                     BAD_CAST shortcut.app_id.c_str());
-      if (!shortcut.app_id.empty())
+      if (!shortcut.extra_data.empty())
         xmlTextWriterWriteAttribute(writer, BAD_CAST "extra_data",
                                     BAD_CAST shortcut.extra_data.c_str());
-      if (!shortcut.app_id.empty())
+      if (!shortcut.extra_key.empty())
         xmlTextWriterWriteAttribute(writer, BAD_CAST "extra_key",
                                     BAD_CAST shortcut.extra_key.c_str());
       if (!shortcut.icon.empty()) {
@@ -496,28 +674,17 @@ common_installer::Step::Status StepGenerateXml::process() {
     }
     xmlTextWriterEndElement(writer);
   }
+}
 
-  xmlTextWriterEndElement(writer);
+void StepGenerateXml::GenerateTrustAnchor(xmlTextWriterPtr writer) {
+  if (!context_->manifest_data.get()->use_system_certs)
+    return;
 
-  xmlTextWriterEndDocument(writer);
-  xmlFreeTextWriter(writer);
+  xmlTextWriterStartElement(writer, BAD_CAST "trust-anchor");
+  xmlTextWriterWriteAttribute(writer, BAD_CAST "use-system-certs",
+      BAD_CAST context_->manifest_data.get()->use_system_certs);
 
-  if (pkgmgr_parser_check_manifest_validation(
-      context_->xml_path.get().c_str()) != 0) {
-    LOG(ERROR) << "Manifest is not valid";
-    return Step::Status::MANIFEST_ERROR;
-  }
-
-  LOG(DEBUG) << "Successfully create manifest xml "
-      << context_->xml_path.get();
-  return Status::OK;
-}
-
-common_installer::Step::Status StepGenerateXml::undo() {
-  bs::error_code error;
-  if (bf::exists(context_->xml_path.get()))
-    bf::remove_all(context_->xml_path.get(), error);
-  return Status::OK;
+  xmlTextWriterEndElement(writer);
 }
 
 }  // namespace pkgmgr