AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} HYBRID_SRCS)
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/step/configuration HYBRID_STEP_CONFIGURATION_SRCS)
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/step/encryption HYBRID_STEP_ENCRYPTION_SRCS)
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/step/pkgmgr HYBRID_STEP_PKGMGR_SRCS)
ADD_LIBRARY(${TARGET_LIBNAME_HYBRID} STATIC
${HYBRID_SRCS}
${HYBRID_STEP_CONFIGURATION_SRCS}
- ${HYBRID_STEP_ENCRYPTION_SRCS})
+ ${HYBRID_STEP_ENCRYPTION_SRCS}
+ ${HYBRID_STEP_PKGMGR_SRCS})
TARGET_INCLUDE_DIRECTORIES(${TARGET_LIBNAME_HYBRID} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../")
#include "hybrid/step/configuration/step_merge_tpk_config.h"
#include "hybrid/step/configuration/step_stash_tpk_config.h"
#include "hybrid/step/encryption/step_encrypt_resources.h"
+#include "hybrid/step/pkgmgr/step_generate_xml.h"
#include "wgt/step/configuration/step_parse.h"
#include "wgt/step/encryption/step_remove_encryption_data.h"
#include "wgt/step/filesystem/step_copy_preview_icons.h"
AddStep<hybrid::configuration::StepStashTpkConfig>();
AddStep<wgt::configuration::StepParse>(
wgt::configuration::StepParse::ConfigLocation::RESOURCE_WGT, true);
- AddStep<hybrid::configuration::StepMergeTpkConfig>();
AddStep<ci::configuration::StepParsePreload>();
AddStep<ci::pkgmgr::StepCheckRestriction>();
AddStep<ci::configuration::StepCheckTizenVersion>();
AddStep<wgt::filesystem::StepCreateSymbolicLink>();
AddStep<tpk::filesystem::StepCreateSymbolicLink>();
AddStep<wgt::pkgmgr::StepGenerateXml>();
+ AddStep<hybrid::pkgmgr::StepGenerateXml>();
+ AddStep<hybrid::configuration::StepMergeTpkConfig>();
AddStep<ci::security::StepRegisterSecurity>();
AddStep<ci::pkgmgr::StepRegisterApplication>();
AddStep<ci::pkgmgr::StepRunParserPlugin>(
AddStep<hybrid::configuration::StepStashTpkConfig>();
AddStep<wgt::configuration::StepParse>(
wgt::configuration::StepParse::ConfigLocation::RESOURCE_WGT, true);
- AddStep<hybrid::configuration::StepMergeTpkConfig>();
AddStep<ci::configuration::StepParsePreload>();
AddStep<ci::configuration::StepCheckTizenVersion>();
AddStep<ci::security::StepCheckSignature>();
AddStep<tpk::filesystem::StepCreateSymbolicLink>();
AddStep<ci::security::StepUpdateSecurity>();
AddStep<wgt::pkgmgr::StepGenerateXml>();
+ AddStep<hybrid::pkgmgr::StepGenerateXml>();
+ AddStep<hybrid::configuration::StepMergeTpkConfig>();
AddStep<ci::pkgmgr::StepUpdateApplication>();
AddStep<ci::pkgmgr::StepRunParserPlugin>(
ci::Plugin::ActionType::Upgrade);
AddStep<ci::filesystem::StepDisableExternalMount>();
AddStep<wgt::configuration::StepParse>(
wgt::configuration::StepParse::ConfigLocation::RESOURCE_WGT, true);
- AddStep<hybrid::configuration::StepMergeTpkConfig>();
AddStep<ci::configuration::StepParsePreload>();
AddStep<ci::configuration::StepCheckTizenVersion>();
AddStep<ci::security::StepCheckSignature>();
AddStep<tpk::filesystem::StepCreateSymbolicLink>();
AddStep<ci::security::StepUpdateSecurity>();
AddStep<wgt::pkgmgr::StepGenerateXml>();
+ AddStep<hybrid::pkgmgr::StepGenerateXml>();
+ AddStep<hybrid::configuration::StepMergeTpkConfig>();
AddStep<ci::pkgmgr::StepUpdateApplication>();
AddStep<ci::pkgmgr::StepRunParserPlugin>(
ci::Plugin::ActionType::Upgrade);
AddStep<hybrid::configuration::StepStashTpkConfig>();
AddStep<wgt::configuration::StepParse>(
wgt::configuration::StepParse::ConfigLocation::RESOURCE_WGT, true);
- AddStep<hybrid::configuration::StepMergeTpkConfig>();
AddStep<ci::configuration::StepParsePreload>();
AddStep<ci::pkgmgr::StepCheckRestriction>();
AddStep<ci::configuration::StepCheckTizenVersion>();
AddStep<wgt::filesystem::StepCreateSymbolicLink>();
AddStep<tpk::filesystem::StepCreateSymbolicLink>();
AddStep<wgt::pkgmgr::StepGenerateXml>();
+ AddStep<hybrid::pkgmgr::StepGenerateXml>();
+ AddStep<hybrid::configuration::StepMergeTpkConfig>();
AddStep<ci::security::StepRegisterSecurity>();
AddStep<ci::pkgmgr::StepRegisterApplication>();
AddStep<ci::pkgmgr::StepRunParserPlugin>(
AddStep<hybrid::configuration::StepStashTpkConfig>();
AddStep<wgt::configuration::StepParse>(
wgt::configuration::StepParse::ConfigLocation::RESOURCE_WGT, true);
- AddStep<hybrid::configuration::StepMergeTpkConfig>();
AddStep<ci::configuration::StepParsePreload>();
AddStep<ci::configuration::StepCheckTizenVersion>();
AddStep<ci::security::StepCheckSignature>();
AddStep<tpk::filesystem::StepCreateSymbolicLink>();
AddStep<ci::security::StepUpdateSecurity>();
AddStep<wgt::pkgmgr::StepGenerateXml>();
+ AddStep<hybrid::pkgmgr::StepGenerateXml>();
+ AddStep<hybrid::configuration::StepMergeTpkConfig>();
AddStep<ci::pkgmgr::StepUpdateApplication>();
AddStep<ci::pkgmgr::StepRunParserPlugin>(
ci::Plugin::ActionType::Upgrade);
AddStep<hybrid::configuration::StepStashTpkConfig>();
AddStep<wgt::configuration::StepParse>(
wgt::configuration::StepParse::ConfigLocation::INSTALLED, true);
- AddStep<hybrid::configuration::StepMergeTpkConfig>();
AddStep<ci::configuration::StepParsePreload>();
AddStep<ci::configuration::StepCheckTizenVersion>();
AddStep<ci::security::StepCheckSignature>();
AddStep<ci::security::StepRollbackInstallationSecurity>();
AddStep<ci::filesystem::StepRemoveGlobalAppSymlinks>();
AddStep<wgt::pkgmgr::StepGenerateXml>();
+ AddStep<hybrid::pkgmgr::StepGenerateXml>();
+ AddStep<hybrid::configuration::StepMergeTpkConfig>();
AddStep<ci::security::StepRegisterSecurity>();
AddStep<ci::pkgmgr::StepRegisterApplication>();
AddStep<ci::pkgmgr::StepRunParserPlugin>(
AddStep<hybrid::configuration::StepStashTpkConfig>();
AddStep<wgt::configuration::StepParse>(
wgt::configuration::StepParse::ConfigLocation::INSTALLED, true);
- AddStep<hybrid::configuration::StepMergeTpkConfig>();
AddStep<ci::configuration::StepParsePreload>();
AddStep<ci::configuration::StepCheckTizenVersion>();
AddStep<ci::security::StepCheckSignature>();
AddStep<ci::security::StepUpdateSecurity>();
AddStep<ci::filesystem::StepRemoveGlobalAppSymlinks>();
AddStep<wgt::pkgmgr::StepGenerateXml>();
+ AddStep<hybrid::pkgmgr::StepGenerateXml>();
+ AddStep<hybrid::configuration::StepMergeTpkConfig>();
AddStep<ci::pkgmgr::StepUpdateApplication>();
AddStep<ci::pkgmgr::StepRunParserPlugin>(
ci::Plugin::ActionType::Upgrade);
--- /dev/null
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#include "hybrid/step/pkgmgr/step_generate_xml.h"
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/system/error_code.hpp>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <pkgmgr_parser.h>
+
+#include <common/utils/file_util.h>
+#include <common/utils/glist_range.h>
+
+#include <string>
+#include <vector>
+
+#include "hybrid/hybrid_backend_data.h"
+
+namespace ci = common_installer;
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+
+namespace {
+
+const char kXmlXPathAppExpr[] =
+ "//*[local-name()='ui-application' or local-name()='service-application' "
+ "or local-name()='widget-application' or local-name()='watch-application']";
+const std::vector<std::string> kBlackListNodes = {
+ {"author"},
+ {"description"},
+ {"profile"},
+};
+const std::vector<std::string> kNeedMergeNodes = {
+ {"manifest"},
+ {"privileges"},
+};
+const std::vector<std::pair<std::string, std::string>> kApplicationNodeNames = {
+ {"ui-application", "uiapp"},
+ {"service-application", "svcapp"},
+ {"widget-application", "widgetapp"},
+ {"watch-application", "watchapp"},
+};
+
+} // namespace
+
+namespace hybrid {
+namespace pkgmgr {
+
+bool StepGenerateXml::LoadXmlDocument(const bf::path& wgt_xml_path,
+ const bf::path& tpk_xml_path) {
+ // trim blanks
+ xmlKeepBlanksDefault(0);
+ wgt_doc_ = xmlParseFile(wgt_xml_path.string().c_str());
+ if (!wgt_doc_) {
+ LOG(ERROR) << "Failed to parse file: " << wgt_xml_path;
+ return false;
+ }
+ tpk_doc_ = xmlParseFile(tpk_xml_path.string().c_str());
+ if (!tpk_doc_) {
+ LOG(ERROR) << "Failed to parse file: " << tpk_xml_path;
+ return false;
+ }
+ return true;
+}
+
+xmlNodePtr StepGenerateXml::GetXmlNode(const xmlDocPtr doc,
+ const std::string& name, const std::string& attr,
+ const std::string& attr_val) {
+ xmlXPathContextPtr ctxt = xmlXPathNewContext(doc);
+ if (!ctxt) {
+ LOG(ERROR) << "Failed to create XPath context";
+ return nullptr;
+ }
+
+ std::string expr = "//*[local-name()='" + name + "']";
+ if (!attr.empty() && !attr_val.empty())
+ expr.append("[@" + attr + "='" + attr_val + "']");
+
+ xmlXPathObjectPtr obj =
+ xmlXPathEvalExpression((const xmlChar*)expr.c_str(), ctxt);
+ if (!obj || !obj->nodesetval || !obj->nodesetval->nodeNr) {
+ xmlXPathFreeContext(ctxt);
+ return nullptr;
+ }
+
+ xmlNodePtr node = obj->nodesetval->nodeTab[0];
+ xmlXPathFreeObject(obj);
+ xmlXPathFreeContext(ctxt);
+
+ return node;
+}
+
+void StepGenerateXml::MergeXmlNode(xmlNodePtr node1, xmlNodePtr node2) {
+ xmlNodePtr last = xmlGetLastChild(node1);
+ xmlNodePtr next;
+ // merge node2's child into node1
+ for (xmlNodePtr cur = node2->children; cur; cur = next) {
+ next = cur->next;
+ if (std::find(kBlackListNodes.begin(), kBlackListNodes.end(),
+ reinterpret_cast<const char*>(cur->name)) != kBlackListNodes.end())
+ continue;
+ // to avoid duplicate
+ if (std::find(kNeedMergeNodes.begin(), kNeedMergeNodes.end(),
+ reinterpret_cast<const char*>(cur->name)) != kNeedMergeNodes.end())
+ continue;
+ xmlAddNextSibling(last, cur);
+ last = last->next;
+ }
+}
+
+void StepGenerateXml::SetXmlNodeAttribute(xmlNodePtr node,
+ const std::string& attr, const std::string& attr_val) {
+ xmlSetProp(node, reinterpret_cast<const xmlChar*>(attr.c_str()),
+ reinterpret_cast<const xmlChar*>(attr_val.c_str()));
+}
+
+ci::Step::Status StepGenerateXml::process() {
+ bf::path wgt_xml_path = context_->xml_path.get();
+ bf::path tpk_xml_path = context_->pkg_path.get() / "tizen-manifest.xml";
+
+ if (!LoadXmlDocument(wgt_xml_path, tpk_xml_path))
+ return Step::Status::MANIFEST_ERROR;
+
+ for (auto& entry : kNeedMergeNodes) {
+ xmlNodePtr tpk_node = GetXmlNode(tpk_doc_, entry);
+ if (tpk_node == nullptr)
+ continue;
+ // TODO(s89.jang): If cannot find node from wgt doc, merge tpk node itself
+ // instead of merging its child nodes.
+ xmlNodePtr wgt_node = GetXmlNode(wgt_doc_, entry);
+ MergeXmlNode(wgt_node, tpk_node);
+ }
+
+ // set app's executable path
+ HybridBackendData* data =
+ static_cast<HybridBackendData*>(context_->backend_data.get());
+ manifest_x* tpk_data = data->tpk_manifest_data.get();
+ for (application_x* app :
+ GListRange<application_x*>(tpk_data->application)) {
+ auto r = std::find_if(kApplicationNodeNames.begin(),
+ kApplicationNodeNames.end(),
+ [app](const std::pair<std::string, std::string>& e) {
+ return strcmp(e.second.c_str(), app->component_type) == 0;
+ });
+ if (r == kApplicationNodeNames.end()) {
+ LOG(WARNING) << "Cannot find component type!";
+ continue;
+ }
+ xmlNodePtr node = GetXmlNode(wgt_doc_, (*r).first, "appid", app->appid);
+ SetXmlNodeAttribute(node, "exec", app->exec);
+ }
+
+ if (xmlSaveFormatFile(wgt_xml_path.string().c_str(), wgt_doc_, 1) == -1) {
+ LOG(ERROR) << "Cannot write xml file";
+ return Step::Status::MANIFEST_ERROR;
+ }
+
+ if (pkgmgr_parser_check_manifest_validation(
+ wgt_xml_path.string().c_str()) != 0) {
+ LOG(ERROR) << "Merged manifest is not valid";
+ return Step::Status::MANIFEST_ERROR;
+ }
+
+ return Status::OK;
+}
+
+ci::Step::Status StepGenerateXml::precheck() {
+ bf::path wgt_xml_path = context_->xml_path.get();
+ if (!bf::exists(wgt_xml_path)) {
+ LOG(ERROR) << "Converted config file not found: " << wgt_xml_path;
+ return Step::Status::MANIFEST_ERROR;
+ }
+
+ bf::path tpk_xml_path = context_->pkg_path.get() / "tizen-manifest.xml";
+ if (!bf::exists(tpk_xml_path)) {
+ LOG(ERROR) << "Native manifest file not found: " << tpk_xml_path;
+ return Step::Status::MANIFEST_ERROR;
+ }
+
+ return Status::OK;
+}
+
+} // namespace pkgmgr
+} // namespace hybrid
--- /dev/null
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef HYBRID_STEP_PKGMGR_STEP_GENERATE_XML_H_
+#define HYBRID_STEP_PKGMGR_STEP_GENERATE_XML_H_
+
+#include <boost/filesystem.hpp>
+
+#include <common/step/step.h>
+#include <manifest_parser/utils/logging.h>
+#include <libxml/tree.h>
+
+#include <string>
+
+namespace hybrid {
+namespace pkgmgr {
+
+class StepGenerateXml : public common_installer::Step {
+ public:
+ using Step::Step;
+ Status process() override;
+ Status clean() override { return Status::OK; }
+ Status undo() override { return Status::OK; }
+ Status precheck() override;
+
+ private:
+ bool LoadXmlDocument(const boost::filesystem::path& wgt_xml_path,
+ const boost::filesystem::path& tpk_xml_path);
+ xmlNodePtr GetXmlNode(const xmlDocPtr doc, const std::string& name,
+ const std::string& attr = {}, const std::string& attr_val = {});
+ void MergeXmlNode(xmlNodePtr node1, xmlNodePtr node2);
+ void SetXmlNodeAttribute(xmlNodePtr node, const std::string& attr,
+ const std::string& attr_val);
+
+ xmlDocPtr wgt_doc_;
+ xmlDocPtr tpk_doc_;
+
+ STEP_NAME(GenerateXml2);
+};
+
+} // namespace pkgmgr
+} // namespace hybrid
+
+#endif // HYBRID_STEP_PKGMGR_STEP_GENERATE_XML_H_