Initialize Tizen 2.3
[framework/web/wrt-plugins-common.git] / src_wearable / plugin-loading / plugin_logic.cpp
1 /*
2  * Copyright (c) 2011 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  * @file        plugin_logic.cpp
18  * @author      Piotr Fatyga (p.fatyga@samsung.com)
19  * @author      Grzegorz Krawczyk (g.krawczyk@samsung.com)
20  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
21  * @version     1.0
22  * @brief       This file is the implementation file of plugin and
23  *              feature loading routines
24  * @brief       This code is intended to work behind view controller
25  */
26
27 #include "plugin_logic.h"
28
29 #include <dpl/assert.h>
30 #include <dpl/scoped_array.h>
31 #include <dpl/log/secure_log.h>
32 #include <dpl/foreach.h>
33 #include <dpl/singleton_impl.h>
34 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
35 #include <dpl/wrt-dao-ro/common_dao_types.h>
36 #include <dpl/wrt-dao-ro/global_config.h>
37
38 #include <JavaScriptCore/JavaScript.h>
39
40 #include <string>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <dirent.h>
44 #include <errno.h>
45 #include <fstream>
46 #include <map>
47 #include <list>
48 #include <vector>
49 #include <algorithm>
50 #include <cstring>
51
52 #include <wrt_plugin_export.h>
53 #include <js_overlay_types.h>
54
55 #include "explorer.h"
56 #include "plugin.h"
57 #include "plugin_model.h"
58 #include "javascript_interface.h"
59 #include "js_function_manager.h"
60 #include "plugin_container_support.h"
61
62 #include "js_page_session.h"
63
64 using namespace std;
65 using namespace WrtDB;
66 using namespace WrtPlugins::W3C;
67
68 namespace {
69 const char *LIBRARY_PATH_SEPARATOR = "/";
70 }
71
72 class PluginLogic::Impl
73 {
74     PluginContainerSupportPtr m_pluginsSupport;
75
76     typedef std::map<JSContextRef, JSPageSessionPtr> PagesSessionsSet;
77     PagesSessionsSet m_sessions;
78     unsigned int m_windowHandle;
79
80   public:
81     Impl();
82     ~Impl();
83
84     // Widget session
85     void initSession(int widgetHandle);
86     void startSession(int widgetHandle,
87                       JSGlobalContextRef context,
88                       double scaleFactor,
89                       const char* encodedBundle,
90                       const char* theme);
91
92     void stopSession(JSGlobalContextRef context);
93
94     void performLibrariesUnload();
95
96     bool loadPluginOnDemand(const WrtDB::DbPluginHandle &pluginHandle,
97                             JavaScriptObject& parentObject,
98                             JSGlobalContextRef context);
99
100     void loadFrame(JSGlobalContextRef context);
101     void unloadFrame(JSGlobalContextRef context);
102
103     void setCustomProperties(JSGlobalContextRef ctx,
104                              double scaleFactor,
105                              const char* encodedBundle,
106                              const char* theme);
107
108     void dispatchJavaScriptEvent(JSGlobalContextRef ctx,
109                                  CustomEventType eventType,
110                                  void* data);
111
112     unsigned int windowHandle() const;
113     void setWindowHandle(unsigned int handle);
114
115     static bool s_sanityCheck;
116 };
117
118 IMPLEMENT_SINGLETON(PluginLogic);
119
120 bool PluginLogic::Impl::s_sanityCheck = false;
121
122 #define PLUGIN_LOGIC_SANITY_CHECK \
123     if (!s_sanityCheck) \
124     { \
125         _E("Object is not available. Wrong flow occured"); \
126         return; \
127     }
128
129 PluginLogic::Impl::Impl() :
130     m_windowHandle(0)
131 {
132     s_sanityCheck = true;
133
134     DPL::Log::LogSystemSingleton::Instance().SetTag("WRT_PLUGINS");
135     _D("Initializing Plugin Logic...");
136     m_pluginsSupport = PluginContainerSupportPtr(new PluginContainerSupport());
137
138     // explicit call to keep singleton's lifetime until calling destructor.
139     JsFunctionManagerSingleton::Instance();
140     JavaScriptInterfaceSingleton::Instance();
141 }
142
143 PluginLogic::Impl::~Impl()
144 {
145     _D("called");
146
147     s_sanityCheck = false;
148
149     FOREACH(it, m_sessions)
150     {
151         _W("Must stop widget session before exit!");
152         it->second->stopSession();
153     }
154 }
155
156 void PluginLogic::initSession(int widgetHandle)
157 {
158     m_impl->initSession(widgetHandle);
159 }
160
161 void PluginLogic::startSession(int widgetHandle,
162                                JSGlobalContextRef ctx,
163                                double scaleFactor,
164                                const char* encodedBundle,
165                                const char* theme)
166 {
167     m_impl->startSession(widgetHandle, ctx, scaleFactor, encodedBundle, theme);
168 }
169
170 void PluginLogic::stopSession(JSGlobalContextRef context)
171 {
172     m_impl->stopSession(context);
173 }
174
175 void PluginLogic::performLibrariesUnload()
176 {
177     _W("This function is DEPRECATED");
178     //    m_impl->performLibrariesUnload();
179 }
180
181 bool PluginLogic::loadPluginOnDemand(
182     const WrtDB::DbPluginHandle &pluginHandle,
183     JavaScriptObject& parentObject,
184     JSGlobalContextRef context)
185 {
186     return m_impl->loadPluginOnDemand(pluginHandle, parentObject, context);
187 }
188
189 void PluginLogic::loadPluginsIntoIframes(JSGlobalContextRef /*context*/)
190 {
191     _W("This function is DEPRECATED");
192 }
193
194 void PluginLogic::setCustomProperties(double /*scaleFactor*/,
195                                       const char* /*encodedBundle*/,
196                                       const char* /*theme*/)
197 {
198     _W("This function is DEPRECATED");
199 }
200
201 void PluginLogic::setCustomProperties(JSGlobalContextRef context,
202                                       double scaleFactor,
203                                       const char* encodedBundle,
204                                       const char* theme)
205 {
206     m_impl->setCustomProperties(context, scaleFactor, encodedBundle, theme);
207 }
208
209 void PluginLogic::dispatchJavaScriptEvent(CustomEventType /*eventType*/)
210 {
211     _W("This function is DEPRECATED");
212 }
213
214 void PluginLogic::dispatchJavaScriptEvent(JSGlobalContextRef context,
215                                           CustomEventType eventType,
216                                           void *data)
217 {
218     m_impl->dispatchJavaScriptEvent(context, eventType, data);
219 }
220
221 void PluginLogic::loadFrame(JSGlobalContextRef context)
222 {
223     m_impl->loadFrame(context);
224 }
225
226 void PluginLogic::unloadFrame(JSGlobalContextRef context)
227 {
228     m_impl->unloadFrame(context);
229 }
230
231 unsigned int PluginLogic::windowHandle() const
232 {
233     return m_impl->windowHandle();
234 }
235
236 void PluginLogic::setWindowHandle(unsigned int handle)
237 {
238     m_impl->setWindowHandle(handle);
239 }
240
241 PluginLogic::PluginLogic() : m_impl(new PluginLogic::Impl())
242 {}
243
244 PluginLogic::~PluginLogic()
245 {}
246
247 void PluginLogic::Impl::initSession(int widgetHandle)
248 {
249     _D(">---------------------[init session START]---------------------<");
250
251     m_pluginsSupport->Initialize(widgetHandle);
252     PluginContainerSupport::PluginsList rootPluginList =
253         m_pluginsSupport->getRootPlugins();
254
255     FOREACH(it, rootPluginList)
256     {
257         PluginModelPtr& pluginModel = *it;
258         PluginPtr pluginLib = pluginModel->LibraryInstance.Get();
259
260         if (!pluginLib) {
261             std::string path = pluginModel->LibraryPath.Get() +
262                 std::string(LIBRARY_PATH_SEPARATOR) +
263                 pluginModel->LibraryName.Get();
264
265             pluginLib = Plugin::LoadFromFile(path);
266
267             if (!pluginLib) {
268                 _W("Loading library failed");
269             } else {
270                 pluginModel->LibraryInstance.Set(pluginLib);
271                 _D("pluginModel->LibraryInstance.Set() : %s",
272                    pluginLib->GetFileName().c_str());
273             }
274         } else {
275             _D("Already loaded");
276         }
277     }
278     _D("========== init session END ==========");
279 }
280
281 void PluginLogic::Impl::startSession(int widgetHandle,
282                                      JSGlobalContextRef context,
283                                      double scaleFactor,
284                                      const char* encodedBundle,
285                                      const char* theme)
286 {
287     _D("========== start session START ==========");
288
289     if (!m_pluginsSupport->isInitialized(widgetHandle)) {
290         m_pluginsSupport->Initialize(widgetHandle);
291     }
292     auto sessionIt = m_sessions.find(context);
293
294     // Check if corresponding session if not already created
295     if (sessionIt != m_sessions.end()) {
296         _W("Session already started!");
297     } else {
298         auto newSession = JSPageSessionPtr(new JSPageSession(m_pluginsSupport));
299         newSession->startSession(widgetHandle,
300                                  context,
301                                  scaleFactor,
302                                  encodedBundle,
303                                  theme);
304
305         m_sessions[context] = newSession;
306     }
307     _D("========== start session END ==========");
308 }
309
310 void PluginLogic::Impl::stopSession(JSGlobalContextRef context)
311 {
312     _D("========== stop session START ==========");
313
314     auto sessionIt = m_sessions.find(context);
315     if (sessionIt == m_sessions.end()) {
316         _W("Session not exist!");
317     } else {
318         sessionIt->second->stopSession();
319         m_sessions.erase(sessionIt);
320     }
321     _D("========== stop session END ==========");
322 }
323
324 bool PluginLogic::Impl::loadPluginOnDemand(
325     const WrtDB::DbPluginHandle &pluginHandle,
326     JavaScriptObject& parentObject,
327     JSGlobalContextRef context
328     )
329 {
330     _D("========== load ondemand plugin ==========");
331
332     auto sessionIt = m_sessions.find(context);
333     if (sessionIt == m_sessions.end()) {
334         _W("Session not exist!");
335         return false;
336     }
337
338     return sessionIt->second->loadPluginOnDemand(pluginHandle,
339                                                  parentObject,
340                                                  context);
341 }
342
343 void PluginLogic::Impl::loadFrame(JSGlobalContextRef context)
344 {
345     _D("========== load frame START ==========");
346     PLUGIN_LOGIC_SANITY_CHECK
347
348     auto sessionIt = m_sessions.find(context);
349     if (sessionIt == m_sessions.end()) {
350         _W("Session not exist!");
351     } else {
352         sessionIt->second->loadFrame(context);
353     }
354     _D("========== load frame END ==========");
355 }
356
357 void PluginLogic::Impl::unloadFrame(JSGlobalContextRef context)
358 {
359     _D("========== unload frame START ==========");
360     PLUGIN_LOGIC_SANITY_CHECK
361
362     auto sessionIt = m_sessions.find(context);
363     if (sessionIt == m_sessions.end()) {
364         LogWarning("Session not exist!");
365     } else {
366         sessionIt->second->unloadFrame(context);
367
368         // I don't know why this session should be removed here.
369         // session list is removed also from stopSession().
370         //m_sessions.erase(sessionIt);
371         }
372     _D("========== unload frame END ==========");
373 }
374
375 void PluginLogic::Impl::setCustomProperties(JSGlobalContextRef context,
376                                             double scaleFactor,
377                                             const char* encodedBundle,
378                                             const char* theme)
379 {
380     PLUGIN_LOGIC_SANITY_CHECK
381
382     auto sessionIt = m_sessions.find(context);
383     if (sessionIt == m_sessions.end()) {
384         _W("Session not exist!");
385         return;
386     }
387
388     sessionIt->second->setCustomProperties(scaleFactor,
389                                            encodedBundle,
390                                            theme);
391 }
392
393 void PluginLogic::Impl::dispatchJavaScriptEvent(JSGlobalContextRef context,
394                                                 CustomEventType eventType,
395                                                 void* data)
396 {
397     PLUGIN_LOGIC_SANITY_CHECK
398
399     auto sessionIt = m_sessions.find(context);
400     if (sessionIt == m_sessions.end()) {
401         _W("Session not exist!");
402         return;
403     }
404
405     sessionIt->second->dispatchJavaScriptEvent(eventType, data);
406 }
407
408 unsigned int PluginLogic::Impl::windowHandle() const
409 {
410     if (!s_sanityCheck) {
411         LogError("Object is not available. Wrong flow occured");
412     }
413     return m_windowHandle;
414 }
415
416 void PluginLogic::Impl::setWindowHandle(unsigned int handle)
417 {
418     PLUGIN_LOGIC_SANITY_CHECK
419     m_windowHandle = handle;
420 }