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/tools/tizen/xwalk_package_installer_helper.h"
9 #include <pkgmgr/pkgmgr_parser.h>
10 #include <tzplatform_config.h>
14 #include "base/files/file_path.h"
15 #include "base/file_util.h"
16 #include "xwalk/application/common/id_util.h"
20 typedef int (*PkgParser)(const char*, char* const*);
22 const base::FilePath kXWalkLauncherBinary("/usr/bin/xwalk-launcher");
23 const char kIconDir[] = "/default/small/";
24 const std::string kServicePrefix("xwalk-service.");
25 const std::string kXmlFileExt(".xml");
26 const std::string kPngFileExt(".png");
28 // Package type sent in every signal.
29 const char PKGMGR_PKG_TYPE[] = "wgt";
31 // Notification about operation start.
32 const char PKGMGR_START_KEY[] = "start";
34 // Value for new installation.
35 const char PKGMGR_START_INSTALL[] = "install";
37 // Value for uninstallation.
38 const char PKGMGR_START_UNINSTALL[] = "uninstall";
41 const char PKGMGR_START_UPDATE[] = "update";
44 const char PKGMGR_START_REINSTALL[] = "reinstall";
46 // Notification about end of installation with status.
47 const char PKGMGR_END_KEY[] = "end";
49 // Success value of end of installation.
50 const char PKGMGR_END_SUCCESS[] = "ok";
52 // Failure value of end of installation.
53 const char PKGMGR_END_FAILURE[] = "fail";
55 // Tags for pkgmgr describing package
56 const char* pkgmgr_tags[] = {"removable=true", NULL, };
58 const std::string kAppIdPrefix("xwalk.");
62 FileDeleter(const base::FilePath& path, bool recursive)
64 recursive_(recursive) {}
70 base::DeleteFile(path_, recursive_);
82 const char* ToEndStatus(bool result) {
83 return result ? PKGMGR_END_SUCCESS : PKGMGR_END_FAILURE;
86 inline base::FilePath GetDestFilePath(const base::FilePath& DirPath,
87 const std::string& appid,
88 const std::string& file_ext) {
89 return DirPath.Append(kServicePrefix + std::string(appid) + file_ext);
92 bool CopyFileToDst(const base::FilePath& file_src,
93 const base::FilePath& file_dst) {
94 base::FilePath dir = file_dst.DirName();
95 if (!base::PathExists(dir))
96 base::CreateDirectory(dir);
97 if (!base::CopyFile(file_src, file_dst)) {
98 fprintf(stdout, "Couldn't copy application file from %s to '%s'\n",
99 file_src.value().c_str(), file_dst.value().c_str());
107 PackageInstallerHelper::PackageInstallerHelper(const std::string& appid)
110 pkgid_(xwalk::application::AppIdToPkgId(appid)) {
112 fprintf(stdout, "Invalid app id is provided for pkg installer.\n");
115 PackageInstallerHelper::~PackageInstallerHelper() {
117 pkgmgr_installer_free(handle_);
120 bool PackageInstallerHelper::InitializePkgmgrSignal(int argc,
122 handle_ = pkgmgr_installer_new();
124 fprintf(stdout, "Fail to get package manager installer handle.\n");
128 return pkgmgr_installer_receive_request(handle_,
130 const_cast<char**>(argv));
133 bool PackageInstallerHelper::InstallApplication(
134 const std::string& xmlpath,
135 const std::string& iconpath) {
136 SendSignal(PKGMGR_START_KEY, PKGMGR_START_INSTALL);
137 bool ret = InstallApplicationInternal(xmlpath, iconpath);
138 SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
142 bool PackageInstallerHelper::UninstallApplication() {
143 SendSignal(PKGMGR_START_KEY, PKGMGR_START_UNINSTALL);
144 bool ret = UninstallApplicationInternal();
145 SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
149 bool PackageInstallerHelper::UpdateApplication(
150 const std::string& xmlpath,
151 const std::string& iconpath) {
152 SendSignal(PKGMGR_START_KEY, PKGMGR_START_UPDATE);
153 bool ret = UpdateApplicationInternal(xmlpath, iconpath);
154 SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
158 bool PackageInstallerHelper::ReinstallApplication() {
159 SendSignal(PKGMGR_START_KEY, PKGMGR_START_REINSTALL);
160 // FIXME not implemented, just send signal abotu failure
161 SendSignal(PKGMGR_END_KEY, ToEndStatus(false));
165 bool PackageInstallerHelper::InstallApplicationInternal(
166 const std::string& xmlpath,
167 const std::string& iconpath) {
168 if (xmlpath.empty() || iconpath.empty()) {
169 fprintf(stdout, "Invalid xml path or icon path for installation\n");
171 base::FilePath global_xml(tzplatform_mkpath(TZ_SYS_RO_PACKAGES, "/"));
172 base::FilePath global_icon(tzplatform_mkpath(TZ_SYS_RO_ICONS, kIconDir));
173 base::FilePath user_xml(tzplatform_mkpath(TZ_USER_PACKAGES, "/"));
174 base::FilePath user_icon(tzplatform_mkpath(TZ_USER_ICONS, "/"));
176 base::FilePath xml(user_xml);
177 base::FilePath icon(user_icon);
179 uid_t uid = getuid();
180 if (uid == GLOBAL_USER) {
184 // FIXME(vcgomes): Add support for more icon types
185 base::FilePath xml_dst = GetDestFilePath(xml, appid_, kXmlFileExt);
186 base::FilePath icon_dst = GetDestFilePath(icon, appid_, kPngFileExt);
187 FileDeleter xml_cleaner(xml_dst, false);
188 FileDeleter icon_cleaner(icon_dst, false);
191 if (!CopyFileToDst(base::FilePath(xmlpath), xml_dst)
192 || !CopyFileToDst(base::FilePath(iconpath), icon_dst))
195 fprintf(stdout, "uid for installation : '%d'\n", uid);
196 if (uid != GLOBAL_USER) { // For only the user that request installation
197 if (pkgmgr_parser_parse_usr_manifest_for_installation(xmlpath.c_str(),
198 uid, const_cast<char**>(pkgmgr_tags))) {
199 fprintf(stdout, "Couldn't parse manifest XML '%s', uid : '%d'\n",
200 xmlpath.c_str(), uid);
203 } else { // For all users
204 if (pkgmgr_parser_parse_manifest_for_installation(xmlpath.c_str(),
205 const_cast<char**>(pkgmgr_tags))) {
206 fprintf(stdout, "Couldn't parse manifest XML '%s', uid : '%d'\n",
207 xmlpath.c_str(), uid);
211 xml_cleaner.Dismiss();
212 icon_cleaner.Dismiss();
217 bool PackageInstallerHelper::UninstallApplicationInternal() {
218 base::FilePath global_xml(tzplatform_mkpath(TZ_SYS_RO_PACKAGES, "/"));
219 base::FilePath global_icon(tzplatform_mkpath(TZ_SYS_RO_ICONS, kIconDir));
220 base::FilePath user_xml(tzplatform_mkpath(TZ_USER_PACKAGES, "/"));
221 base::FilePath user_icon(tzplatform_mkpath(TZ_USER_ICONS, "/"));
223 base::FilePath xml(user_xml);
224 base::FilePath icon(user_icon);
226 uid_t uid = getuid();
227 if (uid == GLOBAL_USER) {
231 // FIXME(vcgomes): Add support for more icon types
232 base::FilePath iconpath = GetDestFilePath(icon, appid_, kPngFileExt);
233 base::FilePath xmlpath = GetDestFilePath(xml, appid_, kXmlFileExt);
234 FileDeleter icon_cleaner(iconpath, false);
235 FileDeleter xml_cleaner(xmlpath, false);
237 std::string xmlpath_str = xmlpath.MaybeAsASCII();
238 assert(!xmlpath_str.empty());
240 if (uid != GLOBAL_USER) { // For only the user that request installation
241 if (pkgmgr_parser_parse_usr_manifest_for_uninstallation(
242 xmlpath_str.c_str(), uid, NULL)) {
243 fprintf(stdout, "Couldn't parse manifest XML '%s'\n",
244 xmlpath_str.c_str());
245 icon_cleaner.Dismiss();
246 xml_cleaner.Dismiss();
248 } else { // For all users
249 if (pkgmgr_parser_parse_manifest_for_uninstallation(
250 xmlpath_str.c_str(), NULL)) {
251 fprintf(stdout, "Couldn't parse manifest XML '%s'\n",
252 xmlpath_str.c_str());
253 icon_cleaner.Dismiss();
254 xml_cleaner.Dismiss();
260 bool PackageInstallerHelper::UpdateApplicationInternal(
261 const std::string& xmlpath,
262 const std::string& iconpath) {
263 if (xmlpath.empty() || iconpath.empty()) {
264 fprintf(stdout, "Invalid xml path or icon path for update\n");
267 base::FilePath global_xml(tzplatform_mkpath(TZ_SYS_RO_PACKAGES, "/"));
268 base::FilePath global_icon(tzplatform_mkpath(TZ_SYS_RO_ICONS, kIconDir));
269 base::FilePath user_xml(tzplatform_mkpath(TZ_USER_PACKAGES, "/"));
270 base::FilePath user_icon(tzplatform_mkpath(TZ_USER_ICONS, "/"));
272 base::FilePath xml(user_xml);
273 base::FilePath icon(user_icon);
275 uid_t uid = getuid();
276 if (uid == GLOBAL_USER) {
281 // FIXME(vcgomes): Add support for more icon types
282 base::FilePath xml_dst = GetDestFilePath(xml, appid_, kXmlFileExt);
283 base::FilePath icon_dst = GetDestFilePath(icon, appid_, kPngFileExt);
284 FileDeleter xml_cleaner(xml_dst, false);
285 FileDeleter icon_cleaner(icon_dst, false);
288 if (!CopyFileToDst(base::FilePath(xmlpath), xml_dst)
289 || !CopyFileToDst(base::FilePath(iconpath), icon_dst))
292 if (uid != GLOBAL_USER) { // For only the user that request installation
293 if (pkgmgr_parser_parse_usr_manifest_for_upgrade(xmlpath.c_str(), uid,
294 const_cast<char**>(pkgmgr_tags))) {
295 fprintf(stdout, "Couldn't parse manifest XML '%s'\n", xmlpath.c_str());
298 } else { // For all users
299 if (pkgmgr_parser_parse_manifest_for_upgrade(xmlpath.c_str(),
300 const_cast<char**>(pkgmgr_tags))) {
301 fprintf(stdout, "Couldn't parse manifest XML '%s'\n", xmlpath.c_str());
306 xml_cleaner.Dismiss();
307 icon_cleaner.Dismiss();
312 bool PackageInstallerHelper::SendSignal(
313 const std::string& key,
314 const std::string& value) {
316 // this is installation with xwalkctl not pkgmgr
320 if (key.empty() || value.empty()) {
321 fprintf(stdout, " Fail to send signal, key/value is empty.\n");
325 if (pkgmgr_installer_send_signal(
326 handle_, PKGMGR_PKG_TYPE, pkgid_.c_str(),
327 key.c_str(), value.c_str())) {
328 fprintf(stdout, "Fail to send package manager signal.\n");