d234b8523e39210b2815378938ee182c7d6a2c4e
[platform/framework/web/crosswalk.git] / src / xwalk / application / tools / tizen / xwalk_pkg_helper.cc
1 // Copyright (c) 2013 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 // On Tizen installing applications requires super-user powers primarily because
6 // some pieces of information of the application are put on globally accessible
7 // locations. This helper will run with super-user powers (via suid) and will
8 // be called by Crosswalk (now running as a normal user) so all the activities
9 // that required 'root' access are done by a small code base.
10
11
12 #if defined(OS_TIZEN)
13 #include <pkgmgr/pkgmgr_parser.h>
14 #else
15 // So we can compile this on Linux Desktop
16 static int pkgmgr_parser_parse_manifest_for_installation(
17     const char* path, char *const tagv[]) {
18   return 0;
19 }
20
21 static int pkgmgr_parser_parse_manifest_for_uninstallation(
22     const char* path, char *const tagv[]) {
23   return 0;
24 }
25
26 #endif
27
28 #include "base/files/file_path.h"
29 #include "base/file_util.h"
30
31 namespace {
32
33 const base::FilePath kIconDir("/opt/share/icons/default/small/");
34 const base::FilePath kXmlDir("/opt/share/packages/");
35 const base::FilePath kXWalkLauncherBinary("/usr/bin/xwalk-launcher");
36 const std::string kServicePrefix("xwalk-service.");
37
38 class FileDeleter {
39  public:
40   FileDeleter(const base::FilePath& path, bool recursive)
41       : path_(path),
42         recursive_(recursive) {}
43
44   ~FileDeleter() {
45     if (path_.empty())
46       return;
47
48     base::DeleteFile(path_, recursive_);
49   }
50
51   void Dismiss() {
52     path_.clear();
53   }
54
55  private:
56   base::FilePath path_;
57   bool recursive_;
58 };
59
60 bool InstallApplication(const char* appid, const char* xmlpath,
61                         const char* iconpath) {
62   base::FilePath icon_src(iconpath);
63   // icon_dst == /opt/share/icons/default/small/xwalk-service.<appid>.png
64   // FIXME(vcgomes): Add support for more icon types
65   base::FilePath icon_dst = kIconDir.Append(
66       kServicePrefix + std::string(appid) + ".png");
67   if (!base::CopyFile(icon_src, icon_dst)) {
68     fprintf(stdout, "Couldn't copy application icon to '%s'\n",
69             icon_dst.value().c_str());
70     return false;
71   }
72
73   FileDeleter icon_cleaner(icon_dst, false);
74
75   base::FilePath xml_src(xmlpath);
76   base::FilePath xml_dst = kXmlDir.Append(
77       kServicePrefix + std::string(appid) + ".xml");
78   if (!base::CopyFile(xml_src, xml_dst)) {
79     fprintf(stdout, "Couldn't copy application XML metadata to '%s'\n",
80             xml_dst.value().c_str());
81     return false;
82   }
83
84   FileDeleter xml_cleaner(xml_dst, false);
85
86   if (pkgmgr_parser_parse_manifest_for_installation(xmlpath, NULL)) {
87     fprintf(stdout, "Couldn't parse manifest XML '%s'\n", xmlpath);
88     return false;
89   }
90
91   icon_cleaner.Dismiss();
92   xml_cleaner.Dismiss();
93
94   return true;
95 }
96
97 bool UninstallApplication(const char* appid) {
98   bool result = true;
99
100   // FIXME(vcgomes): Add support for more icon types
101   base::FilePath icon_dst = kIconDir.Append(
102       kServicePrefix + std::string(appid) + ".png");
103   if (!base::DeleteFile(icon_dst, false)) {
104     fprintf(stdout, "Couldn't delete '%s'\n", icon_dst.value().c_str());
105     result = false;
106   }
107
108   base::FilePath xmlpath(kXmlDir);
109   xmlpath = xmlpath.Append(kServicePrefix + std::string(appid) + ".xml");
110
111   int ret = pkgmgr_parser_parse_manifest_for_uninstallation(
112       xmlpath.value().c_str(), NULL);
113   if (ret) {
114     fprintf(stdout, "Couldn't parse manifest XML '%s'\n",
115             xmlpath.value().c_str());
116     result = false;
117   }
118
119   if (!base::DeleteFile(xmlpath, false)) {
120     fprintf(stdout, "Couldn't delete '%s'\n", xmlpath.value().c_str());
121     result = false;
122   }
123
124   return result;
125 }
126
127 int usage(const char* program) {
128   fprintf(stdout, "%s - Crosswalk Tizen Application Installation helper\n\n",
129           basename(program));
130   fprintf(stdout, "Usage: \n"
131           "\t%s --install <appid> <xml> <icon>\n"
132           "\t%s --uninstall <appid>\n",
133           program, program);
134   return 1;
135 }
136
137 }  // namespace
138
139 int main(int argc, char *argv[]) {
140   bool result = false;
141
142   if (argc <= 2)
143     return usage(argv[0]);
144
145   // When installing an application on Tizen, the libraries used require
146   // some steps to be run as root (UID 0) and fail otherwise, so we force
147   // this tool to assume the root UID.
148   if (setuid(0)) {
149     fprintf(stderr, "Make sure '%s' is set-user-ID-root\n", argv[0]);
150     return 1;;
151   }
152
153   if (!strcmp(argv[1], "--install")) {
154     if (argc != 5)
155       return usage(argv[0]);
156
157     result = InstallApplication(argv[2], argv[3], argv[4]);
158   } else if (!strcmp(argv[1], "--uninstall")) {
159     if (argc != 3)
160       return usage(argv[0]);
161
162     result = UninstallApplication(argv[2]);
163   } else {
164     return usage(argv[0]);
165   }
166
167   // Convetion is to return 0 on success.
168   return result ? 0 : 1;
169 }