Upstream version 6.35.131.0
[platform/framework/web/crosswalk.git] / src / xwalk / application / tools / tizen / xwalk_pkg_installer.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_pkg_installer.h"
6
7 #include <assert.h>
8 #include <stdio.h>
9 #if defined(OS_TIZEN)
10 #include <pkgmgr/pkgmgr_parser.h>
11 #endif
12
13 #undef LOG
14 #include <string>
15 #include "base/files/file_path.h"
16 #include "base/file_util.h"
17
18 namespace {
19
20 typedef int (*PkgParser)(const char*, char* const*);
21
22 const base::FilePath kIconDir("/opt/share/icons/default/small/");
23 const base::FilePath kXmlDir("/opt/share/packages/");
24 const base::FilePath kXWalkLauncherBinary("/usr/bin/xwalk-launcher");
25 const std::string kServicePrefix("xwalk-service.");
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 // Notification about end of installation with status.
40 const char PKGMGR_END_KEY[] = "end";
41
42 // Success value of end of installation.
43 const char PKGMGR_END_SUCCESS[] = "ok";
44
45 // Failure value of end of installation.
46 const char PKGMGR_END_FAILURE[] = "fail";
47
48 const std::string kAppIdPrefix("xwalk.");
49
50 class FileDeleter {
51  public:
52   FileDeleter(const base::FilePath& path, bool recursive)
53       : path_(path),
54         recursive_(recursive) {}
55
56   ~FileDeleter() {
57     if (path_.empty())
58       return;
59
60     base::DeleteFile(path_, recursive_);
61   }
62
63   void Dismiss() {
64     path_.clear();
65   }
66
67  private:
68   base::FilePath path_;
69   bool recursive_;
70 };
71
72 }  // namespace
73
74 PkgInstaller::PkgInstaller(const std::string& appid)
75     : appid_(appid) {
76   if (appid_.empty())
77     fprintf(stdout, "Invalid app id is provided for pkg installer.\n");
78
79 #if defined(OS_TIZEN)
80   handle_ = pkgmgr_installer_new();
81   if (!handle_)
82     fprintf(stdout, "Fail to get package manager installer handle.\n");
83 #endif
84 }
85
86 PkgInstaller::~PkgInstaller() {
87 #if defined(OS_TIZEN)
88   if (handle_)
89     pkgmgr_installer_free(handle_);
90 #endif
91 }
92
93 bool PkgInstaller::InstallApplication(const std::string& xmlpath,
94                                       const std::string& iconpath) {
95   if (xmlpath.empty() || iconpath.empty()) {
96     fprintf(stdout, "Invalid xml path or icon path for installation\n");
97   }
98
99   base::FilePath icon_src(iconpath);
100   // icon_dst == /opt/share/icons/default/small/xwalk-service.<appid>.png
101   // FIXME(vcgomes): Add support for more icon types
102   base::FilePath icon_dst = kIconDir.Append(
103       kServicePrefix + std::string(appid_) + ".png");
104   if (!base::CopyFile(icon_src, icon_dst)) {
105     fprintf(stdout, "Couldn't copy application icon to '%s'\n",
106             icon_dst.value().c_str());
107     return false;
108   }
109
110   FileDeleter icon_cleaner(icon_dst, false);
111
112   base::FilePath xml_src(xmlpath);
113   base::FilePath xml_dst = kXmlDir.Append(
114       kServicePrefix + std::string(appid_) + ".xml");
115   if (!base::CopyFile(xml_src, xml_dst)) {
116     fprintf(stdout, "Couldn't copy application XML metadata to '%s'\n",
117             xml_dst.value().c_str());
118     return false;
119   }
120
121 #if defined(OS_TIZEN)
122   if (!ParseManifest(PkgInstaller::INSTALL, xmlpath)) {
123     fprintf(stdout, "Couldn't install %s'\n", appid_.c_str());
124     return false;
125   }
126 #endif
127
128   FileDeleter xml_cleaner(xml_dst, false);
129   icon_cleaner.Dismiss();
130   xml_cleaner.Dismiss();
131
132   return true;
133 }
134
135 bool PkgInstaller::UninstallApplication() {
136   bool result = true;
137
138   // FIXME(vcgomes): Add support for more icon types
139   base::FilePath icon_dst = kIconDir.Append(
140       kServicePrefix + appid_ + ".png");
141   if (!base::DeleteFile(icon_dst, false)) {
142     fprintf(stdout, "Couldn't delete '%s'\n", icon_dst.value().c_str());
143     result = false;
144   }
145
146   base::FilePath xmlpath(kXmlDir);
147   xmlpath = xmlpath.Append(kServicePrefix + std::string(appid_) + ".xml");
148
149 #if defined(OS_TIZEN)
150   if (!ParseManifest(PkgInstaller::UNINSTALL, xmlpath.MaybeAsASCII())) {
151     fprintf(stdout, "Couldn't uninstall %s'\n", appid_.c_str());
152     result = false;
153   }
154 #endif
155
156   if (!base::DeleteFile(xmlpath, false)) {
157     fprintf(stdout, "Couldn't delete '%s'\n", xmlpath.value().c_str());
158     result = false;
159   }
160
161   return result;
162 }
163
164 #if defined(OS_TIZEN)
165 bool PkgInstaller::ParseManifest(PkgInstaller::RequestType type,
166                                  const std::string& xmlpath) {
167   std::string pkgmgr_cmd;
168   PkgParser parser;
169   switch (type) {
170     case PkgInstaller::INSTALL:
171       pkgmgr_cmd = PKGMGR_START_INSTALL;
172       parser = pkgmgr_parser_parse_manifest_for_installation;
173       break;
174
175     case PkgInstaller::UNINSTALL:
176       pkgmgr_cmd = PKGMGR_START_UNINSTALL;
177       parser = pkgmgr_parser_parse_manifest_for_uninstallation;
178       break;
179
180     default:
181       assert(false);
182       fprintf(stdout, "Setting unknown command for package manager.");
183       return false;
184   }
185
186   SendSignal(PKGMGR_START_KEY, pkgmgr_cmd);
187
188   bool result = parser(xmlpath.c_str(), NULL);
189
190   if (result) {
191     fprintf(stdout, "Couldn't parse manifest XML '%s'\n", xmlpath.c_str());
192     SendSignal(PKGMGR_END_KEY, PKGMGR_END_FAILURE);
193     return false;
194   } else {
195     SendSignal(PKGMGR_END_KEY, PKGMGR_END_SUCCESS);
196   }
197
198   return true;
199 }
200
201 bool PkgInstaller::SendSignal(
202     const std::string& key,
203     const std::string& value) {
204   if (!handle_) {
205     fprintf(stdout, "The package install manager is not initialized.\n");
206     return false;
207   }
208
209   if (key.empty() || value.empty()) {
210     fprintf(stdout, " Fail to send signal, key/value is empty.\n");
211     return false;
212   }
213
214   if (pkgmgr_installer_send_signal(
215           handle_, PKGMGR_PKG_TYPE, appid_.c_str(),
216           key.c_str(), value.c_str())) {
217     fprintf(stdout, "Fail to send package manager signal.\n");
218   }
219
220   return true;
221 }
222 #endif