[M120 Migration][MM] Handle live stream duration and currenttime
[platform/framework/web/chromium-efl.git] / tizen_src / downloadable / chromium_efl_install.cc
1 // Copyright 2019 Samsung Electronics. 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 <dirent.h>
6 #include <fcntl.h>
7 #include <glib.h>
8 #include <lwipc.h>
9 #include <privileged-service/PS_API.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/stat.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15 #include <vconf/vconf.h>
16 #include <vconf/vconf_rtc.h>
17 #include <iostream>
18 #include <string>
19
20 #include "chromium_impl/build/tizen_version.h"
21
22 #define FILE_LOG_OUT
23 #include "dlog_util.h"
24
25 // Check if path is real path(not symbolic link) or does not exist.
26 static bool is_real_path(const char* path) {
27   struct stat ls;
28   if (lstat(path, &ls) == -1) {
29     // not exist
30     if (errno == ENOENT)
31       return true;
32     LOG(ERROR) << "Failed lstat(" << path << ") : " << errno;
33   } else {
34     // not symbolic link
35     if (!S_ISLNK(ls.st_mode))
36       return true;
37     LOG(ERROR) << path << " is symbolic link.";
38   }
39   return false;
40 }
41
42 #ifdef FILE_LOG_OUT
43 std::ofstream TizenDlogWrapper::fstream_ = []() {
44   const char* file_log_path = "/tmp/chromium-efl-install.log";
45   return is_real_path(file_log_path)
46              ? std::ofstream(file_log_path, std::ios::out | std::ios::app)
47              : std::ofstream();
48 }();
49 __attribute__((destructor)) void close_log_file() {
50   TizenDlogWrapper::fstream_.close();
51 }
52 #endif
53
54 #define PATH_PRELOAD_CHROMIUM_EFL_IMG APP_RO_ROOT_DIR "/res/chromium-efl.img"
55 #define PATH_UPDATED_CHROMIUM_EFL_IMG APP_RW_ROOT_DIR "/res/chromium-efl.img"
56
57 // tv has 3-package 2-lib policy. Upgraded engine is used optionally.
58 // 1) preload package /ro/... -> /usr/share/.../lib
59 // 2) updated package /rw/... -> /usr/share/.../lib
60 // 3) upgrade package /rw/...-upgrade ->  /usr/share/.../lib/upgrade
61 #define PATH_UPGRADE_CHROMIUM_EFL_IMG \
62   APP_UPGRADE_ROOT_DIR "/res/chromium-efl.img"
63
64 #define MOUNT_ARGS_PRELOAD_CHROMIUM \
65   PATH_PRELOAD_CHROMIUM_EFL_IMG " " LIB_RO_ROOT_DIR " -t squashfs -o loop,ro"
66 #define MOUNT_ARGS_UPDATED_CHROMIUM \
67   PATH_UPDATED_CHROMIUM_EFL_IMG " " LIB_RO_ROOT_DIR " -t squashfs -o loop,ro"
68 #define MOUNT_ARGS_UPGRADE_CHROMIUM                      \
69   PATH_UPGRADE_CHROMIUM_EFL_IMG " " LIB_UPGRADE_ROOT_DIR \
70                                 " -t squashfs -o loop,ro"
71
72 #define UMOUNT_ARGS_PREFIX "-dl "
73 #define SUCCESS 0
74 #define FAIL -1
75
76 const char* kChromiumMountReady = "/tmp/.chromium_mount.ready";
77 const char* kColdBootRequester = "chromium-efl";
78 const char* kLaunchFail = "rtc/memory/WebApp/LaunchFail";
79 const char* kPSAgentReady = "/run/ps_agent.pid";
80 const char* kSetColdBoot = "memory/boot/cold_poweroff_request_pkg";
81 std::string kTargetTPK;
82 const unsigned int kPSAgentTimeout = 30000;
83
84 static bool ps_agent_ready = false;
85 static bool WaitPSAgentReady() {
86   if (ps_agent_ready)
87     return true;
88
89   int maxRetry = 20;
90   LOG(INFO) << "Waiting the ps_agent ready";
91   while (maxRetry != 0) {
92     int ret = LwipcWaitEvent(kPSAgentReady, kPSAgentTimeout);
93     if (ret == 0) {
94       LOG(INFO) << "ps_agent is ready";
95       ps_agent_ready = true;
96       return true;
97     }
98
99     --maxRetry;
100     LOG(ERROR) << "ps_agent is not ready : " << (ret > 0 ? "timeout" : "fail")
101                << ", remain retry [" << maxRetry << "]";
102   }
103
104   return false;
105 }
106
107 static void SetErrMsg(const std::string& mount_error) {
108   std::string vconfValue = kTargetTPK + mount_error;
109   LOG(ERROR) << "vconf : " << kLaunchFail << " value : " << vconfValue;
110   vconf_set_str_rtc(kLaunchFail, vconfValue.c_str());
111 }
112
113 static void RequestColdBoot() {
114   LOG(INFO) << "Request Cold Boot";
115   if (vconf_set_str(kSetColdBoot, kColdBootRequester) != 0)
116     LOG(ERROR) << "Request Cold Boot Fail";
117 }
118
119 // tv has different mount method and no tpk self-installation
120 static int mount(bool mount, const char* args, bool use_system = false) {
121 #define DEBUG_LOG_SMACK_LABEL 0
122 #if DEBUG_LOG_SMACK_LABEL
123   FILE* fd = fopen("/proc/self/attr/current", "r");
124   if (fd) {
125     char line[100];
126     if (fgets(line, sizeof(line), fd))
127       LOG(INFO) << "SMACK Label:" << line;
128     fclose(fd);
129   }
130 #endif
131
132   if (WaitPSAgentReady() == false)
133     LOG(ERROR) << "Chromium-efl mount may not work.";
134
135   LOG(INFO) << "mount:" << mount << ", args: \"" << args << "\"";
136   int rv = SUCCESS;
137   int result = SUCCESS;
138
139   if (mount) {
140 #if TIZEN_VERSION_AT_LEAST(7, 0, 0)
141     rv = PS_Mount_Fast(args, strlen(args) + 1, 1, &result);
142 #else
143     rv = PS_Mount(args, strlen(args) + 1, 1, &result);
144 #endif
145   }
146   else
147     rv = PS_Umount(args, strlen(args) + 1, 1, &result);
148   LOG(INFO) << "result = " << rv << ", " << result;
149   if (rv != SUCCESS || result != SUCCESS) {
150     std::string mount_error = "mount failed. (" + std::to_string(rv) + ", " +
151                               std::to_string(result) + ")";
152     SetErrMsg(mount_error);
153     return FAIL;
154   }
155
156   if (LwipcEventDone(kChromiumMountReady) < 0) {
157     // The Lwipc api simply calls the ioctl() inside the function.
158     // Failure of this API means that there are some kernel issues.
159     LOG(ERROR) << kChromiumMountReady << " Event Failed.";
160   }
161
162   return SUCCESS;
163 }
164
165 static int MountPatchedTPK() {
166   int result = FAIL;
167   if (!access(LIB_RO_ROOT_DIR "/version", F_OK)) {
168     LOG(INFO) << LIB_RO_ROOT_DIR "/version file already exists.";
169     if (LwipcEventDone(kChromiumMountReady) < 0) {
170       // The Lwipc api simply calls the ioctl() inside the function.
171       // Failure of this API means that there are some kernel issues.
172       LOG(ERROR) << kChromiumMountReady << " Event Failed.";
173     }
174     return SUCCESS;
175   }
176
177   if (!access(PATH_UPDATED_CHROMIUM_EFL_IMG, F_OK)) {
178     LOG(INFO) << PATH_UPDATED_CHROMIUM_EFL_IMG << " exists.";
179     kTargetTPK = "WebEngine Updated TPK ";
180     result = mount(true, MOUNT_ARGS_UPDATED_CHROMIUM);
181   }
182
183   if (result != SUCCESS && !access(PATH_PRELOAD_CHROMIUM_EFL_IMG, F_OK)) {
184     LOG(INFO) << PATH_PRELOAD_CHROMIUM_EFL_IMG << " exists.";
185     kTargetTPK = "WebEngine Preload TPK ";
186     result = mount(true, MOUNT_ARGS_PRELOAD_CHROMIUM);
187   }
188
189   return result;
190 }
191
192 static void MountUpgradeTPK() {
193   if (!access(LIB_UPGRADE_ROOT_DIR "/version", F_OK)) {
194     RequestColdBoot();
195     LOG(INFO) << LIB_UPGRADE_ROOT_DIR "/version file already exists.";
196   }
197
198   if (!access(PATH_UPGRADE_CHROMIUM_EFL_IMG, F_OK)) {
199     LOG(INFO) << PATH_UPGRADE_CHROMIUM_EFL_IMG << " exists.";
200     kTargetTPK = "WebEngine Upgrade TPK ";
201     mount(true, MOUNT_ARGS_UPGRADE_CHROMIUM);
202   } else {
203     LOG(INFO) << "No WebEngine Upgrade TPK found";
204   }
205 }
206
207 enum Options {
208   InstallTpk,
209   Mount,
210   Umount,
211   UmountAll,
212 };
213
214 int main(int argc, char* argv[]) {
215   LOG(INFO) << argv[0] << " started.";
216   bool result = 0;
217   bool is_remove_tpk = false;
218   std::string args;
219   Options option = InstallTpk;
220
221   for (int i = 1; i < argc; i++) {
222     if (!strcmp(argv[i], "--mount")) {
223       option = Mount;
224     } else if (!strcmp(argv[i], "--umount")) {
225       option = Umount;
226     } else if (!strcmp(argv[i], "--umount-all")) {
227       option = UmountAll;
228     } else if (option == InstallTpk) {
229       if (!strcmp(argv[i], "-d")) {
230         is_remove_tpk = true;
231       } else {
232         args.append(argv[i]);
233       }
234     } else if (option == Mount || option == Umount) {
235       if (args.length() > 0)
236         args.append(" ");
237       args.append(argv[i]);
238     } else {
239       LOG(WARN) << "Unknown Argument : " << argv[i];
240     }
241   }
242
243   if (option == InstallTpk) {  // InstallTpk
244     // TV does not install tpk. Built-in installer installs.
245     // To avoid concurrency problem, a lock must be shared with installer.
246     //
247     // Mount patched/preload chromium-efl.img (Mandatory)
248     result = MountPatchedTPK();
249     if (result != SUCCESS)
250       return FAIL;
251
252     // Mount upgrade chromium-efl.img (Optional)
253     MountUpgradeTPK();
254     if (is_remove_tpk) {
255       LOG(WARN) << "'-d' option is not supported for tv";
256     }
257   } else {
258     if (option == Mount || option == Umount) {
259       result = mount(option == Mount, args.c_str());
260     } else if (option == UmountAll) {
261       if (!access(LIB_UPGRADE_ROOT_DIR "/version", F_OK)) {
262         mount(false, UMOUNT_ARGS_PREFIX LIB_UPGRADE_ROOT_DIR);
263       }
264       if (!access(LIB_RO_ROOT_DIR "/version", F_OK)) {
265         mount(false, UMOUNT_ARGS_PREFIX LIB_RO_ROOT_DIR);
266       }
267     }
268   }
269
270   LOG(INFO) << argv[0] << " ended. result:" << result;
271   return result;
272 }