1 // Copyright (c) 2014 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "xwalk/application/browser/installer/tizen/service_package_installer.h"
10 #include <pkgmgr/pkgmgr_parser.h>
14 #include "base/file_util.h"
15 #include "base/files/file_enumerator.h"
16 #include "base/logging.h"
17 #include "base/path_service.h"
18 #include "base/command_line.h"
19 #include "base/process/launch.h"
20 #include "third_party/libxml/chromium/libxml_utils.h"
21 #include "xwalk/application/common/application_data.h"
22 #include "xwalk/application/common/application_manifest_constants.h"
23 #include "xwalk/application/common/manifest_handlers/tizen_metadata_handler.h"
24 #include "xwalk/application/browser/application_storage.h"
25 #include "xwalk/application/browser/installer/tizen/packageinfo_constants.h"
27 namespace info = xwalk::application_packageinfo_constants;
31 namespace widget_keys = xwalk::application_widget_keys;
33 const base::FilePath kPkgHelper("/usr/bin/xwalk-pkg-helper");
35 const base::FilePath kXWalkLauncherBinary("/usr/bin/xwalk-launcher");
37 const base::FilePath kDefaultIcon(
38 "/usr/share/icons/default/small/crosswalk.png");
40 const std::string kServicePrefix("xwalk-service.");
41 const std::string kAppIdPrefix("xwalk.");
45 FileDeleter(const base::FilePath& path, bool recursive)
47 recursive_(recursive) {}
53 base::DeleteFile(path_, recursive_);
65 void WriteMetaDataElement(
67 xwalk::application::TizenMetaDataInfo* info) {
71 const std::map<std::string, std::string>& metadata = info->metadata();
72 std::map<std::string, std::string>::const_iterator it;
73 for (it = metadata.begin(); it != metadata.end(); ++it) {
74 writer.StartElement("metadata");
75 writer.AddAttribute("key", it->first);
76 writer.AddAttribute("value", it->second);
81 bool GeneratePkgInfoXml(xwalk::application::ApplicationData* application,
82 const std::string& icon_name,
83 const base::FilePath& app_dir,
84 const base::FilePath& xml_path) {
85 if (!base::PathExists(app_dir) &&
86 !base::CreateDirectory(app_dir))
89 std::string package_id = application->ID();
90 std::string tizen_app_id = kAppIdPrefix + package_id;
91 base::FilePath execute_path =
92 app_dir.AppendASCII("bin/").AppendASCII(tizen_app_id);
93 std::string stripped_name = application->Name();
95 FILE* file = base::OpenFile(xml_path, "w");
98 xml_writer.StartWriting();
99 xml_writer.StartElement("manifest");
100 xml_writer.AddAttribute("xmlns", "http://tizen.org/ns/packages");
101 xml_writer.AddAttribute("package", package_id);
102 xml_writer.AddAttribute("version", application->VersionString());
103 xml_writer.WriteElement("label", application->Name());
104 xml_writer.WriteElement("description", application->Description());
106 xml_writer.StartElement("ui-application");
107 xml_writer.AddAttribute("appid", tizen_app_id);
108 xml_writer.AddAttribute("exec", execute_path.MaybeAsASCII());
109 xml_writer.AddAttribute("type", "c++app");
110 xml_writer.AddAttribute("taskmanage", "true");
111 xml_writer.WriteElement("label", application->Name());
113 xwalk::application::TizenMetaDataInfo* info =
114 static_cast<xwalk::application::TizenMetaDataInfo*>(
115 application->GetManifestData(widget_keys::kTizenMetaDataKey));
116 WriteMetaDataElement(xml_writer, info);
118 if (icon_name.empty())
119 xml_writer.WriteElement("icon", info::kDefaultIconName);
121 xml_writer.WriteElement("icon", kServicePrefix + package_id + ".png");
122 xml_writer.EndElement(); // Ends "ui-application"
124 xml_writer.EndElement(); // Ends "manifest" element.
125 xml_writer.StopWriting();
127 base::WriteFile(xml_path,
128 xml_writer.GetWrittenString().c_str(),
129 xml_writer.GetWrittenString().size());
131 base::CloseFile(file);
132 LOG(INFO) << "Converting manifest.json into "
133 << xml_path.BaseName().MaybeAsASCII()
134 << " for installation. [DONE]";
141 namespace application {
143 bool InstallApplicationForTizen(
144 ApplicationData* application, const base::FilePath& data_dir) {
145 std::string package_id = application->ID();
146 std::string tizen_app_id = kAppIdPrefix + package_id;
147 base::FilePath app_dir =
148 data_dir.AppendASCII(info::kAppDir).AppendASCII(package_id);
149 base::FilePath xml_path = data_dir.AppendASCII(info::kAppDir).AppendASCII(
150 package_id + std::string(info::kXmlExtension));
152 std::string icon_name;
153 if (!application->GetManifest()->GetString(info::kIconKey, &icon_name)) {
154 LOG(WARNING) << "'icon' not included in manifest";
156 // This will clean everything inside '<data dir>/<app id>'.
157 FileDeleter app_dir_cleaner(app_dir, true);
159 if (!GeneratePkgInfoXml(application, icon_name, app_dir, xml_path)) {
160 LOG(ERROR) << "Could not create XML metadata file '"
161 << xml_path.value() << "'.";
165 base::FilePath execute_path =
166 app_dir.AppendASCII("bin/").AppendASCII(tizen_app_id);
168 if (!base::CreateDirectory(execute_path.DirName())) {
169 LOG(ERROR) << "Could not create directory '"
170 << execute_path.DirName().value() << "'.";
174 if (!base::CreateSymbolicLink(kXWalkLauncherBinary, execute_path)) {
175 LOG(ERROR) << "Could not create symbolic link to launcher from '"
176 << execute_path.value() << "'.";
181 if (icon_name.empty())
184 icon = app_dir.AppendASCII(icon_name);
186 CommandLine cmdline(kPkgHelper);
187 cmdline.AppendSwitch("--install");
188 cmdline.AppendArg(package_id);
189 cmdline.AppendArgPath(xml_path);
190 cmdline.AppendArgPath(icon);
195 if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
196 LOG(ERROR) << "Could not launch installer helper.";
200 if (exit_code != 0) {
201 LOG(ERROR) << "Could not install application: "
202 << output << " (" << exit_code << ")";
206 app_dir_cleaner.Dismiss();
211 bool UninstallApplicationForTizen(ApplicationData* application,
212 const base::FilePath& data_dir) {
213 std::string package_id = application->ID();
216 CommandLine cmdline(kPkgHelper);
217 cmdline.AppendSwitch("--uninstall");
218 cmdline.AppendArg(package_id);
223 if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
224 LOG(ERROR) << "Could not launch installer helper";
228 if (exit_code != 0) {
229 LOG(ERROR) << "Could not uninstall application: "
230 << output << " (" << exit_code << ")";
234 base::FilePath app_dir =
235 data_dir.AppendASCII(info::kAppDir).AppendASCII(package_id);
236 if (!base::DeleteFile(app_dir, true)) {
237 LOG(ERROR) << "Could not remove directory '" << app_dir.value() << "'";
241 base::FilePath xml_path = data_dir.AppendASCII(
242 package_id + std::string(info::kXmlExtension));
243 if (!base::DeleteFile(xml_path, false)) {
244 LOG(ERROR) << "Could not remove file '" << xml_path.value() << "'";
251 } // namespace application