Rework dotnet executable (#204)
[platform/core/dotnet/launcher.git] / NativeLauncher / launcher / exec / loader.cc
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "dotnet_launcher.h"
18 #include "utils.h"
19 #include "log.h"
20
21 #include <cstdio>
22 #include <vector>
23 #include <memory>
24
25 #include <Ecore.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <sys/prctl.h>
29
30 #include <launchpad.h>
31 #include <aul.h>
32
33 using tizen::runtime::dotnetcore::CoreRuntime;
34
35 static Ecore_Fd_Handler *__fd_handler;
36 static loader_receiver_cb __receiver;
37
38 // To precreate window(EFL/DALI), argc and argv should be passed.
39 // But, create callback of loader doesnot pass that to parameter.
40 // So, store argc and argv and use that to precreation.
41 // If window precreation code moves to managed, removed below code.
42 static int __argc;
43 static char **__argv;
44
45 typedef struct AppInfo {
46         std::string root;
47         std::string app_path;
48         std::string appid;
49         std::string pkgid;
50 } AppInfo;
51 static AppInfo __appInfo;
52
53
54 //################## Code for running event loop for loader ####################
55
56 static Eina_Bool __process_fd_handler(void *data, Ecore_Fd_Handler *handler)
57 {
58         int fd;
59
60         fd = ecore_main_fd_handler_fd_get(handler);
61         if (fd == -1) {
62                 _ERR("[candidate] ECORE_FD_GET");
63                 exit(-1);
64         }
65
66         if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ)) {
67                 if (__receiver)
68                         __receiver(fd);
69         } else if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR)) {
70                 _ERR("[candidate] ECORE_FD_ERROR");
71                 close(fd);
72                 exit(-1);
73         }
74
75         return ECORE_CALLBACK_CANCEL;
76 }
77
78 static void __adapter_loop_begin(void *user_data)
79 {
80         ecore_main_loop_begin();
81 }
82
83 static void __adapter_loop_quit(void *user_data)
84 {
85         ecore_main_loop_quit();
86 }
87
88 static void __adapter_add_fd(void *user_data, int fd,
89                 loader_receiver_cb receiver)
90 {
91         __fd_handler = ecore_main_fd_handler_add(fd,
92                         static_cast<Ecore_Fd_Handler_Flags>(ECORE_FD_READ | ECORE_FD_ERROR),
93                         __process_fd_handler, NULL, NULL, NULL);
94         
95         if (__fd_handler == NULL) {
96                 _ERR("fd_handler is NULL");
97                 close(fd);
98                 exit(-1);
99         }
100
101         __receiver = receiver;
102 }
103
104 static void __adapter_remove_fd(void *user_data, int fd)
105 {
106         if (__fd_handler) {
107                 ecore_main_fd_handler_del(__fd_handler);
108                 __fd_handler = NULL;
109                 __receiver = NULL;
110         }
111 }
112
113 //################## Code for managing loader life-cycle #######################
114
115 static void __loader_create_cb(bundle *extra, int type, void *user_data)
116 {
117         CoreRuntime* runtime = (CoreRuntime*)user_data;
118
119         {
120                 // do native window precreation here
121         }
122
123         // initialize CoreRuntime (launchmode, dlog redirection enable, root path NULL)
124         if (runtime->initialize(LaunchMode::loader) != 0) {
125                 _ERR("Failed to initialized");
126         } else {
127                 _INFO("Success to initialized");
128         }       
129 }
130
131 static int __loader_launch_cb(int argc, char **argv, const char *app_path,
132                 const char *appid, const char *pkgid, const char *pkg_type,
133                 void *user_data)
134 {
135         const char* root_path = aul_get_app_root_path();
136         if (root_path != NULL) {
137                 __appInfo.root = root_path;
138         }
139
140         __appInfo.app_path = app_path;
141         __appInfo.appid = appid;
142         __appInfo.pkgid = pkgid;
143
144         return 0;
145 }
146         
147 static int __loader_terminate_cb(int argc, char **argv, void *user_data)
148 {
149         CoreRuntime* runtime = (CoreRuntime*)user_data;
150
151         _INFO("launch request with app path : %s", __appInfo.app_path.c_str());
152
153         // The launchpad pass the name of exe file to the first argument.
154         // For the C# spec, we have to skip this first argument.
155         if (runtime->launch(__appInfo.appid.c_str(), __appInfo.root.c_str(), 
156                                                 __appInfo.app_path.c_str(), argc - 1, argv + 1)) {
157                 _ERR("Failed to launch");
158         }
159
160         return 0;
161 }
162
163 //################## Main Code #################################################
164
165 extern "C" int realMain(int argc, char *argv[], const char* mode)
166 {
167         _INFO("##### Run in candidate mode #####");
168         
169         CoreRuntime* runtime = new CoreRuntime(mode);
170
171         // change cmdline from dotnet-hydra-loader to dotnet-loader
172         if (strcmp(argv[0], "/usr/bin/dotnet-hydra-loader") == 0) {
173                 memset(argv[0], '\0', strlen("/usr/bin/dotnet-hydra-loader"));
174                 snprintf(argv[0], strlen("/usr/bin/dotnet-loader") + 1,
175                                                 "/usr/bin/dotnet-loader");
176         }
177
178         setCmdName("dotnet-loader");
179
180         loader_lifecycle_callback_s callbacks = {
181                 .create = __loader_create_cb,
182                 .launch = __loader_launch_cb,
183                 .terminate = __loader_terminate_cb
184         };
185
186         loader_adapter_s adapter = {
187                 .loop_begin = __adapter_loop_begin,
188                 .loop_quit = __adapter_loop_quit,
189                 .add_fd = __adapter_add_fd,
190                 .remove_fd = __adapter_remove_fd
191         };
192         
193         return launchpad_loader_main(argc, argv, &callbacks, &adapter, runtime);
194 }
195
196 int main(int argc, char *argv[])
197 {
198         __argc = argc;
199         __argv = argv;
200
201         return realMain(argc, argv, "candidate");
202 }
203