Upstream version 10.38.210.0
[platform/framework/web/crosswalk.git] / src / xwalk / application / tools / tizen / xwalk_package_installer_helper.cc
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.
4
5 #include "xwalk/application/tools/tizen/xwalk_package_installer_helper.h"
6
7 #include <assert.h>
8 #include <stdio.h>
9 #include <pkgmgr/pkgmgr_parser.h>
10 #include <tzplatform_config.h>
11
12 #undef LOG
13 #include <string>
14 #include "base/files/file_path.h"
15 #include "base/file_util.h"
16 #include "xwalk/application/common/id_util.h"
17
18 namespace {
19
20 typedef int (*PkgParser)(const char*, char* const*);
21
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");
27
28 // Package type sent in every signal.
29 const char PKGMGR_PKG_TYPE[] = "wgt";
30
31 // Notification about operation start.
32 const char PKGMGR_START_KEY[] = "start";
33
34 // Value for new installation.
35 const char PKGMGR_START_INSTALL[] = "install";
36
37 // Value for uninstallation.
38 const char PKGMGR_START_UNINSTALL[] = "uninstall";
39
40 // Value for update.
41 const char PKGMGR_START_UPDATE[] = "update";
42
43 // Value for update.
44 const char PKGMGR_START_REINSTALL[] = "reinstall";
45
46 // Notification about end of installation with status.
47 const char PKGMGR_END_KEY[] = "end";
48
49 // Success value of end of installation.
50 const char PKGMGR_END_SUCCESS[] = "ok";
51
52 // Failure value of end of installation.
53 const char PKGMGR_END_FAILURE[] = "fail";
54
55 // Tags for pkgmgr describing package
56 const char* pkgmgr_tags[] = {"removable=true", NULL, };
57
58 const std::string kAppIdPrefix("xwalk.");
59
60 class FileDeleter {
61  public:
62   FileDeleter(const base::FilePath& path, bool recursive)
63       : path_(path),
64         recursive_(recursive) {}
65
66   ~FileDeleter() {
67     if (path_.empty())
68       return;
69
70     base::DeleteFile(path_, recursive_);
71   }
72
73   void Dismiss() {
74     path_.clear();
75   }
76
77  private:
78   base::FilePath path_;
79   bool recursive_;
80 };
81
82 const char* ToEndStatus(bool result) {
83   return result ? PKGMGR_END_SUCCESS : PKGMGR_END_FAILURE;
84 }
85
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);
90 }
91
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());
100     return false;
101   }
102   return true;
103 }
104
105 }  // namespace
106
107 PackageInstallerHelper::PackageInstallerHelper(const std::string& appid)
108     : handle_(NULL),
109       appid_(appid),
110       pkgid_(xwalk::application::AppIdToPkgId(appid)) {
111   if (appid_.empty())
112     fprintf(stdout, "Invalid app id is provided for pkg installer.\n");
113 }
114
115 PackageInstallerHelper::~PackageInstallerHelper() {
116   if (handle_)
117     pkgmgr_installer_free(handle_);
118 }
119
120 bool PackageInstallerHelper::InitializePkgmgrSignal(int argc,
121                                                     const char** argv) {
122   handle_ = pkgmgr_installer_new();
123   if (!handle_) {
124     fprintf(stdout, "Fail to get package manager installer handle.\n");
125     return false;
126   }
127
128   return pkgmgr_installer_receive_request(handle_,
129                                           argc,
130                                           const_cast<char**>(argv));
131 }
132
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));
139   return ret;
140 }
141
142 bool PackageInstallerHelper::UninstallApplication() {
143   SendSignal(PKGMGR_START_KEY, PKGMGR_START_UNINSTALL);
144   bool ret = UninstallApplicationInternal();
145   SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
146   return ret;
147 }
148
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));
155   return ret;
156 }
157
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));
162   return false;
163 }
164
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");
170   }
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, "/"));
175
176   base::FilePath xml(user_xml);
177   base::FilePath icon(user_icon);
178
179   uid_t uid = getuid();
180   if (uid == GLOBAL_USER) {
181     xml = global_xml;
182     icon = global_icon;
183   }
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);
189
190
191   if (!CopyFileToDst(base::FilePath(xmlpath), xml_dst)
192      || !CopyFileToDst(base::FilePath(iconpath), icon_dst))
193     return false;
194
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);
201       return false;
202     }
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);
208       return false;
209     }
210   }
211   xml_cleaner.Dismiss();
212   icon_cleaner.Dismiss();
213
214   return true;
215 }
216
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, "/"));
222
223   base::FilePath xml(user_xml);
224   base::FilePath icon(user_icon);
225
226   uid_t uid = getuid();
227   if (uid == GLOBAL_USER) {
228     xml = global_xml;
229     icon = global_icon;
230   }
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);
236
237   std::string xmlpath_str = xmlpath.MaybeAsASCII();
238   assert(!xmlpath_str.empty());
239
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();
247     }
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();
255     }
256   }
257   return true;
258 }
259
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");
265   }
266
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, "/"));
271
272   base::FilePath xml(user_xml);
273   base::FilePath icon(user_icon);
274
275   uid_t uid = getuid();
276   if (uid == GLOBAL_USER) {
277     xml = global_xml;
278     icon = global_icon;
279   }
280
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);
286
287
288   if (!CopyFileToDst(base::FilePath(xmlpath), xml_dst)
289      || !CopyFileToDst(base::FilePath(iconpath), icon_dst))
290     return false;
291
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());
296       return false;
297     }
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());
302       return false;
303      }
304   }
305
306   xml_cleaner.Dismiss();
307   icon_cleaner.Dismiss();
308
309   return true;
310 }
311
312 bool PackageInstallerHelper::SendSignal(
313     const std::string& key,
314     const std::string& value) {
315   if (!handle_) {
316     // this is installation with xwalkctl not pkgmgr
317     return true;
318   }
319
320   if (key.empty() || value.empty()) {
321     fprintf(stdout, " Fail to send signal, key/value is empty.\n");
322     return false;
323   }
324
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");
329   }
330
331   return true;
332 }