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_platform_installer.h"
8 #include <pkgmgr_installer.h>
9 #include <pkgmgr/pkgmgr_parser.h>
11 // logging and dlog uses same macro name
12 // to avoid warnings we need to undefine dlog's one
15 #include <tzplatform_config.h>
19 #include "base/files/file_path.h"
20 #include "base/file_util.h"
21 #include "base/logging.h"
22 #include "xwalk/application/common/id_util.h"
26 typedef int (*PkgParser)(const char*, char* const*);
28 const base::FilePath kXWalkLauncherBinary("/usr/bin/xwalk-launcher");
29 const char kIconDir[] = "/default/small/";
30 const std::string kServicePrefix("xwalk-service.");
31 const std::string kXmlFileExt(".xml");
32 const std::string kPngFileExt(".png");
34 // Package type sent in every signal.
35 const char PKGMGR_PKG_TYPE[] = "wgt";
37 // Notification about operation start.
38 const char PKGMGR_START_KEY[] = "start";
40 // Value for new installation.
41 const char PKGMGR_START_INSTALL[] = "install";
43 // Value for uninstallation.
44 const char PKGMGR_START_UNINSTALL[] = "uninstall";
47 const char PKGMGR_START_UPDATE[] = "update";
50 const char PKGMGR_START_REINSTALL[] = "reinstall";
52 // Notification about end of installation with status.
53 const char PKGMGR_END_KEY[] = "end";
55 // Success value of end of installation.
56 const char PKGMGR_END_SUCCESS[] = "ok";
58 // Failure value of end of installation.
59 const char PKGMGR_END_FAILURE[] = "fail";
61 // Tags for pkgmgr describing package
62 const char* pkgmgr_tags[] = {"removable=true", NULL, };
64 const std::string kAppIdPrefix("xwalk.");
68 FileDeleter(const base::FilePath& path, bool recursive)
70 recursive_(recursive) {}
76 base::DeleteFile(path_, recursive_);
88 const char* ToEndStatus(bool result) {
89 return result ? PKGMGR_END_SUCCESS : PKGMGR_END_FAILURE;
92 inline base::FilePath GetDestFilePath(const base::FilePath& DirPath,
93 const std::string& appid,
94 const std::string& file_ext) {
95 return DirPath.Append(kServicePrefix + std::string(appid) + file_ext);
98 bool CopyFileToDst(const base::FilePath& file_src,
99 const base::FilePath& file_dst) {
100 base::FilePath dir = file_dst.DirName();
101 if (!base::PathExists(dir))
102 base::CreateDirectory(dir);
103 if (!base::CopyFile(file_src, file_dst)) {
104 LOG(ERROR) << "Couldn't copy application file from "
105 << file_src.value() << " to " << file_dst.value();
113 PlatformInstaller::PlatformInstaller()
117 PlatformInstaller::PlatformInstaller(const std::string& appid)
120 pkgid_(xwalk::application::AppIdToPkgId(appid)) {
122 LOG(ERROR) << "Invalid app id is provided for pkg installer";
125 PlatformInstaller::~PlatformInstaller() {
127 pkgmgr_installer_free(handle_);
130 bool PlatformInstaller::InitializePkgmgrSignal(int argc,
132 handle_ = pkgmgr_installer_new();
134 LOG(ERROR) << "Fail to get package manager installer handle";
138 LOG(INFO) << "Initializing pkgmgr request...";
139 return pkgmgr_installer_receive_request(handle_,
141 const_cast<char**>(argv));
144 bool PlatformInstaller::InstallApplication(const base::FilePath& xmlpath,
145 const base::FilePath& iconpath) {
146 SendSignal(PKGMGR_START_KEY, PKGMGR_START_INSTALL);
147 bool ret = InstallApplicationInternal(xmlpath, iconpath);
148 SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
152 bool PlatformInstaller::UninstallApplication() {
153 SendSignal(PKGMGR_START_KEY, PKGMGR_START_UNINSTALL);
154 bool ret = UninstallApplicationInternal();
155 SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
159 bool PlatformInstaller::UpdateApplication(const base::FilePath& xmlpath,
160 const base::FilePath& iconpath) {
161 SendSignal(PKGMGR_START_KEY, PKGMGR_START_UPDATE);
162 bool ret = UpdateApplicationInternal(xmlpath, iconpath);
163 SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
167 bool PlatformInstaller::ReinstallApplication(const std::string& pkgid) {
168 SendSignal(PKGMGR_START_KEY, PKGMGR_START_REINSTALL);
169 bool ret = ReinstallApplicationInternal(pkgid);
170 SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
174 bool PlatformInstaller::InstallApplicationInternal(
175 const base::FilePath& xmlpath,
176 const base::FilePath& iconpath) {
177 if (xmlpath.empty() || iconpath.empty()) {
178 LOG(ERROR) << "Invalid xml path or icon path for installation";
180 base::FilePath global_xml(tzplatform_mkpath(TZ_SYS_RO_PACKAGES, "/"));
181 base::FilePath global_icon(tzplatform_mkpath(TZ_SYS_RO_ICONS, kIconDir));
182 base::FilePath user_xml(tzplatform_mkpath(TZ_USER_PACKAGES, "/"));
183 base::FilePath user_icon(tzplatform_mkpath(TZ_USER_ICONS, "/"));
185 base::FilePath xml(user_xml);
186 base::FilePath icon(user_icon);
188 uid_t uid = getuid();
189 if (uid == GLOBAL_USER) {
193 // FIXME(vcgomes): Add support for more icon types
194 base::FilePath xml_dst = GetDestFilePath(xml, appid_, kXmlFileExt);
195 base::FilePath icon_dst = GetDestFilePath(icon, appid_, kPngFileExt);
196 FileDeleter xml_cleaner(xml_dst, false);
197 FileDeleter icon_cleaner(icon_dst, false);
199 if (!CopyFileToDst(xmlpath, xml_dst)
200 || !CopyFileToDst(iconpath, icon_dst))
203 LOG(INFO) << "UID of installation : " << uid;
204 if (uid != GLOBAL_USER) { // For only the user that request installation
205 if (pkgmgr_parser_parse_usr_manifest_for_installation(
206 xmlpath.value().c_str(), uid, const_cast<char**>(pkgmgr_tags))) {
207 LOG(ERROR) << "Couldn't parse manifest XML '"
208 << xmlpath.value().c_str() << "', uid : " << uid;
211 } else { // For all users
212 if (pkgmgr_parser_parse_manifest_for_installation(
213 xmlpath.value().c_str(), const_cast<char**>(pkgmgr_tags))) {
214 LOG(ERROR) << "Couldn't parse manifest XML '"
215 << xmlpath.value().c_str() << "' for global installation";
219 xml_cleaner.Dismiss();
220 icon_cleaner.Dismiss();
225 bool PlatformInstaller::UninstallApplicationInternal() {
226 base::FilePath global_xml(tzplatform_mkpath(TZ_SYS_RO_PACKAGES, "/"));
227 base::FilePath global_icon(tzplatform_mkpath(TZ_SYS_RO_ICONS, kIconDir));
228 base::FilePath user_xml(tzplatform_mkpath(TZ_USER_PACKAGES, "/"));
229 base::FilePath user_icon(tzplatform_mkpath(TZ_USER_ICONS, "/"));
231 base::FilePath xml(user_xml);
232 base::FilePath icon(user_icon);
234 uid_t uid = getuid();
235 if (uid == GLOBAL_USER) {
239 // FIXME(vcgomes): Add support for more icon types
240 base::FilePath iconpath = GetDestFilePath(icon, appid_, kPngFileExt);
241 base::FilePath xmlpath = GetDestFilePath(xml, appid_, kXmlFileExt);
242 FileDeleter icon_cleaner(iconpath, false);
243 FileDeleter xml_cleaner(xmlpath, false);
245 std::string xmlpath_str = xmlpath.MaybeAsASCII();
246 assert(!xmlpath_str.empty());
248 if (uid != GLOBAL_USER) { // For only the user that request installation
249 if (pkgmgr_parser_parse_usr_manifest_for_uninstallation(xmlpath_str.c_str(),
251 LOG(ERROR) << "Couldn't parse manifest XML '" << xmlpath_str << "', uid"
253 icon_cleaner.Dismiss();
254 xml_cleaner.Dismiss();
256 } else { // For all users
257 if (pkgmgr_parser_parse_manifest_for_uninstallation(xmlpath_str.c_str(),
259 LOG(ERROR) << "Couldn't parse manifest XML '" << xmlpath_str
260 << "' for global uninstallation";
261 icon_cleaner.Dismiss();
262 xml_cleaner.Dismiss();
268 bool PlatformInstaller::UpdateApplicationInternal(
269 const base::FilePath& xmlpath, const base::FilePath& iconpath) {
270 if (xmlpath.empty() || iconpath.empty()) {
271 LOG(ERROR) << "Invalid xml path or icon path for update";
273 base::FilePath global_xml(tzplatform_mkpath(TZ_SYS_RO_PACKAGES, "/"));
274 base::FilePath global_icon(tzplatform_mkpath(TZ_SYS_RO_ICONS, kIconDir));
275 base::FilePath user_xml(tzplatform_mkpath(TZ_USER_PACKAGES, "/"));
276 base::FilePath user_icon(tzplatform_mkpath(TZ_USER_ICONS, "/"));
278 base::FilePath xml(user_xml);
279 base::FilePath icon(user_icon);
281 uid_t uid = getuid();
282 if (uid == GLOBAL_USER) {
286 // FIXME(vcgomes): Add support for more icon types
287 base::FilePath xml_dst = GetDestFilePath(xml, appid_, kXmlFileExt);
288 base::FilePath icon_dst = GetDestFilePath(icon, appid_, kPngFileExt);
289 FileDeleter xml_cleaner(xml_dst, false);
290 FileDeleter icon_cleaner(icon_dst, false);
292 if (!CopyFileToDst(xmlpath, xml_dst) || !CopyFileToDst(iconpath, icon_dst))
295 if (uid != GLOBAL_USER) { // For only the user that request installation
296 if (pkgmgr_parser_parse_usr_manifest_for_upgrade(xmlpath.value().c_str(),
297 uid, const_cast<char**>(pkgmgr_tags))) {
298 LOG(ERROR) << "Couldn't parse manifest XML '" << xmlpath.value()
299 << "', uid: " << uid;
302 } else { // For all users
303 if (pkgmgr_parser_parse_manifest_for_upgrade(xmlpath.value().c_str(),
304 const_cast<char**>(pkgmgr_tags))) {
305 LOG(ERROR) << "Couldn't parse manifest XML '"
306 << xmlpath.value() << "' for global update installation";
310 xml_cleaner.Dismiss();
311 icon_cleaner.Dismiss();
316 bool PlatformInstaller::ReinstallApplicationInternal(const std::string& pkgid) {
318 LOG(ERROR) << "Invalid package ID for reinstallation!";
324 bool PlatformInstaller::SendSignal(const std::string& key,
325 const std::string& value) {
327 // this is installation with xwalkctl not pkgmgr
331 if (key.empty() || value.empty()) {
332 LOG(ERROR) << "Fail to send signal, key/value is empty";
336 if (pkgmgr_installer_send_signal(handle_, PKGMGR_PKG_TYPE, pkgid_.c_str(),
337 key.c_str(), value.c_str())) {
338 LOG(ERROR) << "Fail to send package manager signal";