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>
13 #include "base/file_util.h"
14 #include "base/files/file_enumerator.h"
15 #include "base/logging.h"
16 #include "base/path_service.h"
17 #include "base/command_line.h"
18 #include "base/process/launch.h"
19 #include "third_party/libxml/chromium/libxml_utils.h"
20 #include "xwalk/application/common/application_data.h"
21 #include "xwalk/application/browser/application_storage.h"
22 #include "xwalk/application/browser/installer/tizen/packageinfo_constants.h"
24 namespace info = xwalk::application_packageinfo_constants;
28 const base::FilePath kPkgHelper("/usr/bin/xwalk-pkg-helper");
30 const base::FilePath kXWalkLauncherBinary("/usr/bin/xwalk-launcher");
32 const base::FilePath kDefaultIcon(
33 "/usr/share/icons/default/small/crosswalk.png");
35 const std::string kServicePrefix("xwalk-service.");
36 const std::string kAppIdPrefix("xwalk.");
40 FileDeleter(const base::FilePath& path, bool recursive)
42 recursive_(recursive) {}
48 base::DeleteFile(path_, recursive_);
60 bool GeneratePkgInfoXml(xwalk::application::ApplicationData* application,
61 const std::string& icon_name,
62 const base::FilePath& app_dir,
63 const base::FilePath& xml_path) {
64 if (!base::PathExists(app_dir) &&
65 !base::CreateDirectory(app_dir))
68 std::string package_id = application->ID();
69 std::string tizen_app_id = kAppIdPrefix + package_id;
70 base::FilePath execute_path =
71 app_dir.AppendASCII("bin/").AppendASCII(tizen_app_id);
72 std::string stripped_name = application->Name();
74 FILE* file = base::OpenFile(xml_path, "w");
77 xml_writer.StartWriting();
78 xml_writer.StartElement("manifest");
79 xml_writer.AddAttribute("xmlns", "http://tizen.org/ns/packages");
80 xml_writer.AddAttribute("package", package_id);
81 xml_writer.AddAttribute("version", application->VersionString());
82 xml_writer.WriteElement("label", application->Name());
83 xml_writer.WriteElement("description", application->Description());
85 xml_writer.StartElement("ui-application");
86 xml_writer.AddAttribute("appid", tizen_app_id);
87 xml_writer.AddAttribute("exec", execute_path.MaybeAsASCII());
88 xml_writer.AddAttribute("type", "c++app");
89 xml_writer.AddAttribute("taskmanage", "true");
90 xml_writer.WriteElement("label", application->Name());
92 if (icon_name.empty())
93 xml_writer.WriteElement("icon", info::kDefaultIconName);
95 xml_writer.WriteElement("icon", kServicePrefix + package_id + ".png");
96 xml_writer.EndElement(); // Ends "ui-application"
98 xml_writer.EndElement(); // Ends "manifest" element.
99 xml_writer.StopWriting();
101 base::WriteFile(xml_path,
102 xml_writer.GetWrittenString().c_str(),
103 xml_writer.GetWrittenString().size());
105 base::CloseFile(file);
106 LOG(INFO) << "Converting manifest.json into "
107 << xml_path.BaseName().MaybeAsASCII()
108 << " for installation. [DONE]";
115 namespace application {
117 bool InstallApplicationForTizen(
118 ApplicationData* application, const base::FilePath& data_dir) {
119 std::string package_id = application->ID();
120 std::string tizen_app_id = kAppIdPrefix + package_id;
121 base::FilePath app_dir =
122 data_dir.AppendASCII(info::kAppDir).AppendASCII(package_id);
123 base::FilePath xml_path = data_dir.AppendASCII(info::kAppDir).AppendASCII(
124 package_id + std::string(info::kXmlExtension));
126 std::string icon_name;
127 if (!application->GetManifest()->GetString(info::kIconKey, &icon_name)) {
128 LOG(WARNING) << "'icon' not included in manifest";
130 // This will clean everything inside '<data dir>/<app id>'.
131 FileDeleter app_dir_cleaner(app_dir, true);
133 if (!GeneratePkgInfoXml(application, icon_name, app_dir, xml_path)) {
134 LOG(ERROR) << "Could not create XML metadata file '"
135 << xml_path.value() << "'.";
139 base::FilePath execute_path =
140 app_dir.AppendASCII("bin/").AppendASCII(tizen_app_id);
142 if (!base::CreateDirectory(execute_path.DirName())) {
143 LOG(ERROR) << "Could not create directory '"
144 << execute_path.DirName().value() << "'.";
148 if (!base::CreateSymbolicLink(kXWalkLauncherBinary, execute_path)) {
149 LOG(ERROR) << "Could not create symbolic link to launcher from '"
150 << execute_path.value() << "'.";
155 if (icon_name.empty())
158 icon = app_dir.AppendASCII(icon_name);
160 CommandLine cmdline(kPkgHelper);
161 cmdline.AppendSwitch("--install");
162 cmdline.AppendArg(package_id);
163 cmdline.AppendArgPath(xml_path);
164 cmdline.AppendArgPath(icon);
169 if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
170 LOG(ERROR) << "Could not launch installer helper.";
174 if (exit_code != 0) {
175 LOG(ERROR) << "Could not install application: "
176 << output << " (" << exit_code << ")";
180 app_dir_cleaner.Dismiss();
185 bool UninstallApplicationForTizen(ApplicationData* application,
186 const base::FilePath& data_dir) {
187 std::string package_id = application->ID();
190 CommandLine cmdline(kPkgHelper);
191 cmdline.AppendSwitch("--uninstall");
192 cmdline.AppendArg(package_id);
197 if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
198 LOG(ERROR) << "Could not launch installer helper";
202 if (exit_code != 0) {
203 LOG(ERROR) << "Could not uninstall application: "
204 << output << " (" << exit_code << ")";
208 base::FilePath app_dir =
209 data_dir.AppendASCII(info::kAppDir).AppendASCII(package_id);
210 if (!base::DeleteFile(app_dir, true)) {
211 LOG(ERROR) << "Could not remove directory '" << app_dir.value() << "'";
215 base::FilePath xml_path = data_dir.AppendASCII(
216 package_id + std::string(info::kXmlExtension));
217 if (!base::DeleteFile(xml_path, false)) {
218 LOG(ERROR) << "Could not remove file '" << xml_path.value() << "'";
225 } // namespace application