refactoring launcher
[platform/core/dotnet/launcher.git] / NativeLauncher / launcher / launcher.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 "launcher.h"
18 #include "log.h"
19
20 #include <launchpad.h>
21 #include <aul.h>
22
23 #include <Ecore.h>
24 #include <Elementary.h>
25 #include <bundle_internal.h>
26
27 #include <map>
28 #include <vector>
29 #include <functional>
30
31 #include <unistd.h>
32 #include <dlfcn.h>
33
34
35 namespace tizen {
36 namespace runtime {
37
38 struct FdHandler
39 {
40   Ecore_Fd_Handler *handler;
41   loader_receiver_cb receiver;
42 };
43
44 static int __argc;
45 static char **__argv;
46 static Evas_Object *__win;
47
48 class LaunchpadAdapterImpl : public LaunchpadAdapter
49 {
50   public:
51     LaunchpadAdapterImpl() : isLaunched(false) { }
52     void LoaderMain(int argc, char* argv[]) override;
53
54     std::map<int, FdHandler> Handlers;
55
56   private:
57     AppInfo appinfo;
58     loader_lifecycle_callback_s callbacks;
59     loader_adapter_s adapter;
60     LauncherInterface* launcher;
61     bool isLaunched;
62     std::string launchPath;
63 };
64
65 LaunchpadAdapterImpl LaunchpadImpl;
66 LaunchpadAdapter& Launchpad = LaunchpadImpl;
67
68 #define WITH_SELF(data) \
69   LaunchpadAdapterImpl* self = static_cast<LaunchpadAdapterImpl*>(data); \
70   if (self == nullptr) \
71   { \
72     _ERR("No LaunchpadImplData"); \
73   } else
74
75 static Eina_Bool Fd_Handler(void *data, Ecore_Fd_Handler* handler)
76 {
77   WITH_SELF(data)
78   {
79     int fd = ecore_main_fd_handler_fd_get(handler);
80     if (fd == -1)
81     {
82       _ERR("Failed to get the Ecore FD");
83       exit(-1);
84     }
85
86     if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
87     {
88       if (self->Handlers.find(fd) != self->Handlers.end())
89       {
90         self->Handlers[fd].receiver(fd);
91       }
92     }
93     else if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
94     {
95       _ERR("Ecore FD Handler Have Error");
96       close(fd);
97       exit(-1);
98     }
99   }
100
101   return ECORE_CALLBACK_CANCEL;
102 }
103
104 static void Fd_Add(void *data, int fd, loader_receiver_cb receiver)
105 {
106   Ecore_Fd_Handler* handler = ecore_main_fd_handler_add(fd,
107       static_cast<Ecore_Fd_Handler_Flags>(ECORE_FD_READ | ECORE_FD_ERROR),
108       Fd_Handler, data, nullptr, nullptr);
109   if (handler == nullptr)
110   {
111     _ERR("Failed to add a FD handler to ecore main loop");
112     close(fd);
113     exit(-1);
114   }
115   WITH_SELF(data)
116   {
117     self->Handlers[fd] = {handler, receiver};
118   }
119 }
120
121 static void Fd_Remove(void *data, int fd)
122 {
123   WITH_SELF(data)
124   {
125     if (self->Handlers.find(fd) != self->Handlers.end())
126     {
127       Ecore_Fd_Handler* handler = self->Handlers[fd].handler;
128       ecore_main_fd_handler_del(handler);
129       self->Handlers.erase(fd);
130     }
131   }
132 }
133
134
135 static void PreloadLibsAndWindow(bundle *extra, int type, void *user_data)
136 {
137         int elm_init_cnt = 0;
138   const char **so_array;
139   int len = 0;
140   int i;
141   void *handle = NULL;
142
143   // Preload native libraries
144         if (extra == NULL) {
145                 _DBG("No extra data");
146                 return;
147         }
148
149         so_array = bundle_get_str_array(extra, "preload", &len);
150
151         if (!so_array)
152                 return;
153
154         for (i = 0; i < len; i++) {
155                 handle = dlopen(so_array[i], RTLD_NOW);
156                 _DBG("preload %s# - handle : %x", so_array[i], handle);
157         }
158
159   // Precreate window
160         elm_init_cnt = elm_init(__argc, __argv);
161         _DBG("[candidate] elm init, returned: %d", elm_init_cnt);
162
163   elm_config_accel_preference_set("hw");
164
165   __win = elm_win_add(NULL, "package_name", ELM_WIN_BASIC);
166   if (__win == NULL) {
167     _DBG("[candidate] elm_win_add() failed");
168     return;
169   }
170
171   elm_win_precreated_object_set(__win);
172 }
173
174 void LaunchpadAdapterImpl::LoaderMain(int argc, char* argv[])
175 {
176   __argc = argc;
177   __argv = argv;
178   callbacks.create = [](bundle *extra, int type, void *user_data)
179   {
180     ecore_init();
181     PreloadLibsAndWindow(extra, type, user_data);
182     WITH_SELF(user_data)
183     {
184       if (self->OnCreate != nullptr)
185         self->OnCreate();
186     }
187   };
188   callbacks.launch = [](int argc, char** argv, const char* app_path,
189       const char* appid, const char* pkgid,
190       const char* pkg_type, void* user_data) -> int
191   {
192     WITH_SELF(user_data)
193     {
194       self->appinfo.root = std::string(aul_get_app_root_path());
195       self->appinfo.path = app_path;
196       self->appinfo.id = appid;
197       self->appinfo.pkg = pkgid;
198       self->appinfo.type = pkg_type;
199       if (self->OnLaunch != nullptr)
200         self->OnLaunch(self->appinfo, argc, argv);
201     }
202
203     return 0;
204   };
205   callbacks.terminate = [](int argc, char **argv, void* user_data) -> int
206   {
207     _DBG("Terminate!!");
208     WITH_SELF(user_data)
209     {
210       if (self->OnTerminate != nullptr)
211         self->OnTerminate(self->appinfo, argc, argv);
212     }
213     return 0;
214   };
215
216   adapter.loop_begin = [](void *data)
217   {
218     ecore_main_loop_begin();
219   };
220
221   adapter.loop_quit = [](void *data)
222   {
223     ecore_main_loop_quit();
224   };
225   adapter.add_fd = Fd_Add;
226   adapter.remove_fd = Fd_Remove;
227
228   _DBG("launchpad_loader_main is start");
229   int r = launchpad_loader_main(argc, argv, &(this->callbacks), &(this->adapter), this);
230   _DBG("launchpad_loader_main is finished with [%d]", r);
231 }
232
233 #undef WITH_SELF
234
235 }  // namespace runtime
236 }  // namespace tizen