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";
43 // Notification about end of installation with status.
44 const char PKGMGR_END_KEY[] = "end";
46 // Success value of end of installation.
47 const char PKGMGR_END_SUCCESS[] = "ok";
49 // Failure value of end of installation.
50 const char PKGMGR_END_FAILURE[] = "fail";
52 // Tags for pkgmgr describing package
53 const char* pkgmgr_tags[] = {"removable=true", NULL, };
55 const std::string kAppIdPrefix("xwalk.");
59 FileDeleter(const base::FilePath& path, bool recursive)
61 recursive_(recursive) {}
67 base::DeleteFile(path_, recursive_);
79 const char* ToEndStatus(bool result) {
80 return result ? PKGMGR_END_SUCCESS : PKGMGR_END_FAILURE;
83 inline base::FilePath GetDestFilePath(const base::FilePath& DirPath,
84 const std::string& appid,
85 const std::string& file_ext) {
86 return DirPath.Append(kServicePrefix + std::string(appid) + file_ext);
89 bool CopyFileToDst(const base::FilePath& file_src,
90 const base::FilePath& file_dst) {
91 base::FilePath dir = file_dst.DirName();
92 if (!base::PathExists(dir))
93 base::CreateDirectory(dir);
94 if (!base::CopyFile(file_src, file_dst)) {
95 fprintf(stdout, "Couldn't copy application file from %s to '%s'\n",
96 file_src.value().c_str(), file_dst.value().c_str());
104 PackageInstallerHelper::PackageInstallerHelper(const std::string& appid)
107 pkgid_(xwalk::application::AppIdToPkgId(appid)) {
109 fprintf(stdout, "Invalid app id is provided for pkg installer.\n");
112 PackageInstallerHelper::~PackageInstallerHelper() {
114 pkgmgr_installer_free(handle_);
117 bool PackageInstallerHelper::InitializePkgmgrSignal(int argc,
119 handle_ = pkgmgr_installer_new();
121 fprintf(stdout, "Fail to get package manager installer handle.\n");
125 return pkgmgr_installer_receive_request(handle_,
127 const_cast<char**>(argv));
130 bool PackageInstallerHelper::InstallApplication(
131 const std::string& xmlpath,
132 const std::string& iconpath) {
133 SendSignal(PKGMGR_START_KEY, PKGMGR_START_INSTALL);
134 bool ret = InstallApplicationInternal(xmlpath, iconpath);
135 SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
139 bool PackageInstallerHelper::UninstallApplication() {
140 SendSignal(PKGMGR_START_KEY, PKGMGR_START_UNINSTALL);
141 bool ret = UninstallApplicationInternal();
142 SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
146 bool PackageInstallerHelper::UpdateApplication(
147 const std::string& xmlpath,
148 const std::string& iconpath) {
149 SendSignal(PKGMGR_START_KEY, PKGMGR_START_UPDATE);
150 bool ret = UpdateApplicationInternal(xmlpath, iconpath);
151 SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
155 bool PackageInstallerHelper::InstallApplicationInternal(
156 const std::string& xmlpath,
157 const std::string& iconpath) {
158 if (xmlpath.empty() || iconpath.empty()) {
159 fprintf(stdout, "Invalid xml path or icon path for installation\n");
161 base::FilePath global_xml(tzplatform_mkpath(TZ_SYS_RO_PACKAGES, "/"));
162 base::FilePath global_icon(tzplatform_mkpath(TZ_SYS_RO_ICONS, kIconDir));
163 base::FilePath user_xml(tzplatform_mkpath(TZ_USER_PACKAGES, "/"));
164 base::FilePath user_icon(tzplatform_mkpath(TZ_USER_ICONS, "/"));
166 base::FilePath xml(user_xml);
167 base::FilePath icon(user_icon);
169 uid_t uid = getuid();
170 if (uid == GLOBAL_USER) {
174 // FIXME(vcgomes): Add support for more icon types
175 base::FilePath xml_dst = GetDestFilePath(xml, appid_, kXmlFileExt);
176 base::FilePath icon_dst = GetDestFilePath(icon, appid_, kPngFileExt);
177 FileDeleter xml_cleaner(xml_dst, false);
178 FileDeleter icon_cleaner(icon_dst, false);
181 if (!CopyFileToDst(base::FilePath(xmlpath), xml_dst)
182 || !CopyFileToDst(base::FilePath(iconpath), icon_dst))
185 fprintf(stdout, "uid for installation : '%d'\n", uid);
186 if (uid != GLOBAL_USER) { // For only the user that request installation
187 if (pkgmgr_parser_parse_usr_manifest_for_installation(xmlpath.c_str(),
188 uid, const_cast<char**>(pkgmgr_tags))) {
189 fprintf(stdout, "Couldn't parse manifest XML '%s', uid : '%d'\n",
190 xmlpath.c_str(), uid);
193 } else { // For all users
194 if (pkgmgr_parser_parse_manifest_for_installation(xmlpath.c_str(),
195 const_cast<char**>(pkgmgr_tags))) {
196 fprintf(stdout, "Couldn't parse manifest XML '%s', uid : '%d'\n",
197 xmlpath.c_str(), uid);
201 xml_cleaner.Dismiss();
202 icon_cleaner.Dismiss();
207 bool PackageInstallerHelper::UninstallApplicationInternal() {
208 base::FilePath global_xml(tzplatform_mkpath(TZ_SYS_RO_PACKAGES, "/"));
209 base::FilePath global_icon(tzplatform_mkpath(TZ_SYS_RO_ICONS, kIconDir));
210 base::FilePath user_xml(tzplatform_mkpath(TZ_USER_PACKAGES, "/"));
211 base::FilePath user_icon(tzplatform_mkpath(TZ_USER_ICONS, "/"));
213 base::FilePath xml(user_xml);
214 base::FilePath icon(user_icon);
216 uid_t uid = getuid();
217 if (uid == GLOBAL_USER) {
221 // FIXME(vcgomes): Add support for more icon types
222 base::FilePath iconpath = GetDestFilePath(icon, appid_, kPngFileExt);
223 base::FilePath xmlpath = GetDestFilePath(xml, appid_, kXmlFileExt);
224 FileDeleter icon_cleaner(iconpath, false);
225 FileDeleter xml_cleaner(xmlpath, false);
227 std::string xmlpath_str = xmlpath.MaybeAsASCII();
228 assert(!xmlpath_str.empty());
230 if (uid != GLOBAL_USER) { // For only the user that request installation
231 if (pkgmgr_parser_parse_usr_manifest_for_uninstallation(
232 xmlpath_str.c_str(), uid, NULL)) {
233 fprintf(stdout, "Couldn't parse manifest XML '%s'\n",
234 xmlpath_str.c_str());
235 icon_cleaner.Dismiss();
236 xml_cleaner.Dismiss();
238 } else { // For all users
239 if (pkgmgr_parser_parse_manifest_for_uninstallation(
240 xmlpath_str.c_str(), NULL)) {
241 fprintf(stdout, "Couldn't parse manifest XML '%s'\n",
242 xmlpath_str.c_str());
243 icon_cleaner.Dismiss();
244 xml_cleaner.Dismiss();
250 bool PackageInstallerHelper::UpdateApplicationInternal(
251 const std::string& xmlpath,
252 const std::string& iconpath) {
253 if (xmlpath.empty() || iconpath.empty()) {
254 fprintf(stdout, "Invalid xml path or icon path for update\n");
257 base::FilePath global_xml(tzplatform_mkpath(TZ_SYS_RO_PACKAGES, "/"));
258 base::FilePath global_icon(tzplatform_mkpath(TZ_SYS_RO_ICONS, kIconDir));
259 base::FilePath user_xml(tzplatform_mkpath(TZ_USER_PACKAGES, "/"));
260 base::FilePath user_icon(tzplatform_mkpath(TZ_USER_ICONS, "/"));
262 base::FilePath xml(user_xml);
263 base::FilePath icon(user_icon);
265 uid_t uid = getuid();
266 if (uid == GLOBAL_USER) {
271 // FIXME(vcgomes): Add support for more icon types
272 base::FilePath xml_dst = GetDestFilePath(xml, appid_, kXmlFileExt);
273 base::FilePath icon_dst = GetDestFilePath(icon, appid_, kPngFileExt);
274 FileDeleter xml_cleaner(xml_dst, false);
275 FileDeleter icon_cleaner(icon_dst, false);
278 if (!CopyFileToDst(base::FilePath(xmlpath), xml_dst)
279 || !CopyFileToDst(base::FilePath(iconpath), icon_dst))
282 if (uid != GLOBAL_USER) { // For only the user that request installation
283 if (pkgmgr_parser_parse_usr_manifest_for_upgrade(xmlpath.c_str(), uid,
284 const_cast<char**>(pkgmgr_tags))) {
285 fprintf(stdout, "Couldn't parse manifest XML '%s'\n", xmlpath.c_str());
288 } else { // For all users
289 if (pkgmgr_parser_parse_manifest_for_upgrade(xmlpath.c_str(),
290 const_cast<char**>(pkgmgr_tags))) {
291 fprintf(stdout, "Couldn't parse manifest XML '%s'\n", xmlpath.c_str());
296 xml_cleaner.Dismiss();
297 icon_cleaner.Dismiss();
302 bool PackageInstallerHelper::SendSignal(
303 const std::string& key,
304 const std::string& value) {
306 // this is installation with xwalkctl not pkgmgr
310 if (key.empty() || value.empty()) {
311 fprintf(stdout, " Fail to send signal, key/value is empty.\n");
315 if (pkgmgr_installer_send_signal(
316 handle_, PKGMGR_PKG_TYPE, pkgid_.c_str(),
317 key.c_str(), value.c_str())) {
318 fprintf(stdout, "Fail to send package manager signal.\n");