f0620987d832a3066f29825760c9995bb33d55f7
[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 // Notification about end of installation with status.
44 const char PKGMGR_END_KEY[] = "end";
45
46 // Success value of end of installation.
47 const char PKGMGR_END_SUCCESS[] = "ok";
48
49 // Failure value of end of installation.
50 const char PKGMGR_END_FAILURE[] = "fail";
51
52 // Tags for pkgmgr describing package
53 const char* pkgmgr_tags[] = {"removable=true", NULL, };
54
55 const std::string kAppIdPrefix("xwalk.");
56
57 class FileDeleter {
58  public:
59   FileDeleter(const base::FilePath& path, bool recursive)
60       : path_(path),
61         recursive_(recursive) {}
62
63   ~FileDeleter() {
64     if (path_.empty())
65       return;
66
67     base::DeleteFile(path_, recursive_);
68   }
69
70   void Dismiss() {
71     path_.clear();
72   }
73
74  private:
75   base::FilePath path_;
76   bool recursive_;
77 };
78
79 const char* ToEndStatus(bool result) {
80   return result ? PKGMGR_END_SUCCESS : PKGMGR_END_FAILURE;
81 }
82
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);
87 }
88
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());
97     return false;
98   }
99   return true;
100 }
101
102 }  // namespace
103
104 PackageInstallerHelper::PackageInstallerHelper(const std::string& appid)
105     : handle_(NULL),
106       appid_(appid),
107       pkgid_(xwalk::application::AppIdToPkgId(appid)) {
108   if (appid_.empty())
109     fprintf(stdout, "Invalid app id is provided for pkg installer.\n");
110 }
111
112 PackageInstallerHelper::~PackageInstallerHelper() {
113   if (handle_)
114     pkgmgr_installer_free(handle_);
115 }
116
117 bool PackageInstallerHelper::InitializePkgmgrSignal(int argc,
118                                                     const char** argv) {
119   handle_ = pkgmgr_installer_new();
120   if (!handle_) {
121     fprintf(stdout, "Fail to get package manager installer handle.\n");
122     return false;
123   }
124
125   return pkgmgr_installer_receive_request(handle_,
126                                           argc,
127                                           const_cast<char**>(argv));
128 }
129
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));
136   return ret;
137 }
138
139 bool PackageInstallerHelper::UninstallApplication() {
140   SendSignal(PKGMGR_START_KEY, PKGMGR_START_UNINSTALL);
141   bool ret = UninstallApplicationInternal();
142   SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
143   return ret;
144 }
145
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));
152   return ret;
153 }
154
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");
160   }
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, "/"));
165
166   base::FilePath xml(user_xml);
167   base::FilePath icon(user_icon);
168
169   uid_t uid = getuid();
170   if (uid == GLOBAL_USER) {
171     xml = global_xml;
172     icon = global_icon;
173   }
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);
179
180
181   if (!CopyFileToDst(base::FilePath(xmlpath), xml_dst)
182      || !CopyFileToDst(base::FilePath(iconpath), icon_dst))
183     return false;
184
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);
191       return false;
192     }
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);
198       return false;
199     }
200   }
201   xml_cleaner.Dismiss();
202   icon_cleaner.Dismiss();
203
204   return true;
205 }
206
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, "/"));
212
213   base::FilePath xml(user_xml);
214   base::FilePath icon(user_icon);
215
216   uid_t uid = getuid();
217   if (uid == GLOBAL_USER) {
218     xml = global_xml;
219     icon = global_icon;
220   }
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);
226
227   std::string xmlpath_str = xmlpath.MaybeAsASCII();
228   assert(!xmlpath_str.empty());
229
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();
237     }
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();
245     }
246   }
247   return true;
248 }
249
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");
255   }
256
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, "/"));
261
262   base::FilePath xml(user_xml);
263   base::FilePath icon(user_icon);
264
265   uid_t uid = getuid();
266   if (uid == GLOBAL_USER) {
267     xml = global_xml;
268     icon = global_icon;
269   }
270
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);
276
277
278   if (!CopyFileToDst(base::FilePath(xmlpath), xml_dst)
279      || !CopyFileToDst(base::FilePath(iconpath), icon_dst))
280     return false;
281
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());
286       return false;
287     }
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());
292       return false;
293      }
294   }
295
296   xml_cleaner.Dismiss();
297   icon_cleaner.Dismiss();
298
299   return true;
300 }
301
302 bool PackageInstallerHelper::SendSignal(
303     const std::string& key,
304     const std::string& value) {
305   if (!handle_) {
306     // this is installation with xwalkctl not pkgmgr
307     return true;
308   }
309
310   if (key.empty() || value.empty()) {
311     fprintf(stdout, " Fail to send signal, key/value is empty.\n");
312     return false;
313   }
314
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");
319   }
320
321   return true;
322 }