Upstream version 7.36.149.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
11 #undef LOG
12 #include <string>
13 #include "base/files/file_path.h"
14 #include "base/file_util.h"
15
16 namespace {
17
18 typedef int (*PkgParser)(const char*, char* const*);
19
20 const base::FilePath kIconDir("/opt/share/icons/default/small/");
21 const base::FilePath kXmlDir("/opt/share/packages/");
22 const base::FilePath kXWalkLauncherBinary("/usr/bin/xwalk-launcher");
23 const std::string kServicePrefix("xwalk-service.");
24 const std::string kXmlFileExt(".xml");
25 const std::string kPngFileExt(".png");
26
27 // Package type sent in every signal.
28 const char PKGMGR_PKG_TYPE[] = "rpm";
29
30 // Notification about operation start.
31 const char PKGMGR_START_KEY[] = "start";
32
33 // Value for new installation.
34 const char PKGMGR_START_INSTALL[] = "install";
35
36 // Value for uninstallation.
37 const char PKGMGR_START_UNINSTALL[] = "uninstall";
38
39 // Value for update.
40 const char PKGMGR_START_UPDATE[] = "update";
41
42 // Notification about end of installation with status.
43 const char PKGMGR_END_KEY[] = "end";
44
45 // Success value of end of installation.
46 const char PKGMGR_END_SUCCESS[] = "ok";
47
48 // Failure value of end of installation.
49 const char PKGMGR_END_FAILURE[] = "fail";
50
51 const std::string kAppIdPrefix("xwalk.");
52
53 class FileDeleter {
54  public:
55   FileDeleter(const base::FilePath& path, bool recursive)
56       : path_(path),
57         recursive_(recursive) {}
58
59   ~FileDeleter() {
60     if (path_.empty())
61       return;
62
63     base::DeleteFile(path_, recursive_);
64   }
65
66   void Dismiss() {
67     path_.clear();
68   }
69
70  private:
71   base::FilePath path_;
72   bool recursive_;
73 };
74
75 const char* ToEndStatus(bool result) {
76   return result ? PKGMGR_END_SUCCESS : PKGMGR_END_FAILURE;
77 }
78
79 inline base::FilePath GetDestFilePath(const base::FilePath& DirPath,
80                                       const std::string& appid,
81                                       const std::string& file_ext) {
82   return DirPath.Append(kServicePrefix + std::string(appid) + file_ext);
83 }
84
85 bool CopyFileToDst(const base::FilePath& file_src,
86                    const base::FilePath& file_dst) {
87   if (!base::CopyFile(file_src, file_dst)) {
88     fprintf(stdout, "Couldn't copy application file to '%s'\n",
89             file_dst.value().c_str());
90     return false;
91   }
92   return true;
93 }
94
95 }  // namespace
96
97 PackageInstallerHelper::PackageInstallerHelper(const std::string& appid)
98     : appid_(appid) {
99   if (appid_.empty())
100     fprintf(stdout, "Invalid app id is provided for pkg installer.\n");
101
102   handle_ = pkgmgr_installer_new();
103   if (!handle_)
104     fprintf(stdout, "Fail to get package manager installer handle.\n");
105 }
106
107 PackageInstallerHelper::~PackageInstallerHelper() {
108   if (handle_)
109     pkgmgr_installer_free(handle_);
110 }
111
112 bool PackageInstallerHelper::InstallApplication(
113     const std::string& xmlpath,
114     const std::string& iconpath) {
115   SendSignal(PKGMGR_START_KEY, PKGMGR_START_INSTALL);
116   bool ret = InstallApplicationInternal(xmlpath, iconpath);
117   SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
118   return ret;
119 }
120
121 bool PackageInstallerHelper::UninstallApplication() {
122   SendSignal(PKGMGR_START_KEY, PKGMGR_START_UNINSTALL);
123   bool ret = UninstallApplicationInternal();
124   SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
125   return ret;
126 }
127
128 bool PackageInstallerHelper::UpdateApplication(
129     const std::string& xmlpath,
130     const std::string& iconpath) {
131   SendSignal(PKGMGR_START_KEY, PKGMGR_START_UPDATE);
132   bool ret = UpdateApplicationInternal(xmlpath, iconpath);
133   SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
134   return ret;
135 }
136
137 bool PackageInstallerHelper::InstallApplicationInternal(
138     const std::string& xmlpath,
139     const std::string& iconpath) {
140   if (xmlpath.empty() || iconpath.empty()) {
141     fprintf(stdout, "Invalid xml path or icon path for installation\n");
142   }
143
144   // FIXME(vcgomes): Add support for more icon types
145   base::FilePath xml_dst = GetDestFilePath(kXmlDir, appid_, kXmlFileExt);
146   base::FilePath icon_dst = GetDestFilePath(kIconDir, appid_, kPngFileExt);
147   FileDeleter xml_cleaner(xml_dst, false);
148   FileDeleter icon_cleaner(icon_dst, false);
149
150
151   if (!CopyFileToDst(base::FilePath(xmlpath), xml_dst)
152      || !CopyFileToDst(base::FilePath(iconpath), icon_dst))
153     return false;
154
155   if (pkgmgr_parser_parse_manifest_for_installation(xmlpath.c_str(), NULL)) {
156     fprintf(stdout, "Couldn't parse manifest XML '%s'\n", xmlpath.c_str());
157     return false;
158   }
159
160   xml_cleaner.Dismiss();
161   icon_cleaner.Dismiss();
162
163   return true;
164 }
165
166 bool PackageInstallerHelper::UninstallApplicationInternal() {
167   bool result = true;
168
169   // FIXME(vcgomes): Add support for more icon types
170   base::FilePath iconpath = GetDestFilePath(kIconDir, appid_, kPngFileExt);
171   base::FilePath xmlpath = GetDestFilePath(kXmlDir, appid_, kXmlFileExt);
172   FileDeleter icon_cleaner(iconpath, false);
173   FileDeleter xml_cleaner(xmlpath, false);
174
175   std::string xmlpath_str = xmlpath.MaybeAsASCII();
176   assert(!xmlpath_str.empty());
177   if (pkgmgr_parser_parse_manifest_for_uninstallation(
178         xmlpath_str.c_str(), NULL)) {
179     fprintf(stdout, "Couldn't parse manifest XML '%s'\n", xmlpath_str.c_str());
180     icon_cleaner.Dismiss();
181     xml_cleaner.Dismiss();
182     return false;
183   }
184   return true;
185 }
186
187 bool PackageInstallerHelper::UpdateApplicationInternal(
188     const std::string& xmlpath,
189     const std::string& iconpath) {
190   if (xmlpath.empty() || iconpath.empty()) {
191     fprintf(stdout, "Invalid xml path or icon path for update\n");
192   }
193
194   // FIXME(vcgomes): Add support for more icon types
195   base::FilePath xml_dst = GetDestFilePath(kXmlDir, appid_, kXmlFileExt);
196   base::FilePath icon_dst = GetDestFilePath(kIconDir, appid_, kPngFileExt);
197   FileDeleter xml_cleaner(xml_dst, false);
198   FileDeleter icon_cleaner(icon_dst, false);
199
200
201   if (!CopyFileToDst(base::FilePath(xmlpath), xml_dst)
202      || !CopyFileToDst(base::FilePath(iconpath), icon_dst))
203     return false;
204
205   if (pkgmgr_parser_parse_manifest_for_upgrade(xmlpath.c_str(), NULL)) {
206     fprintf(stdout, "Couldn't parse manifest XML '%s'\n", xmlpath.c_str());
207     return false;
208   }
209
210   xml_cleaner.Dismiss();
211   icon_cleaner.Dismiss();
212
213   return true;
214 }
215
216 bool PackageInstallerHelper::SendSignal(
217     const std::string& key,
218     const std::string& value) {
219   if (!handle_) {
220     fprintf(stdout, "The package install manager is not initialized.\n");
221     return false;
222   }
223
224   if (key.empty() || value.empty()) {
225     fprintf(stdout, " Fail to send signal, key/value is empty.\n");
226     return false;
227   }
228
229   if (pkgmgr_installer_send_signal(
230           handle_, PKGMGR_PKG_TYPE, appid_.c_str(),
231           key.c_str(), value.c_str())) {
232     fprintf(stdout, "Fail to send package manager signal.\n");
233   }
234
235   return true;
236 }