Preloading plugin so file was changed to work only for root object.
[platform/framework/web/wrt-plugins-common.git] / src / 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/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 const char* FEATURE_WAC20_DEVICAPIS_NAME = "http://wacapps.net/api/deviceapis";
71 }
72
73 class PluginLogic::Impl
74 {
75     PluginContainerSupportPtr m_pluginsSupport;
76
77     typedef std::map<JSContextRef, JSPageSessionPtr> PagesSessionsSet;
78     PagesSessionsSet m_sessions;
79
80
81   public:
82     Impl();
83     ~Impl();
84
85     // Widget session
86     void initSession(int widgetHandle);
87     void startSession(int widgetHandle,
88                       JSGlobalContextRef context,
89                       double scaleFactor,
90                       const char* encodedBundle,
91                       const char* theme);
92
93     void stopSession(JSGlobalContextRef context);
94
95     void performLibrariesUnload();
96
97     bool loadPluginOnDemand(const WrtDB::DbPluginHandle &pluginHandle,
98                             JavaScriptObject& parentObject,
99                             JSGlobalContextRef context);
100
101     void loadFrame(JSGlobalContextRef context);
102     void unloadFrame(JSGlobalContextRef context);
103
104     void setCustomProperties(JSGlobalContextRef ctx,
105                              double scaleFactor,
106                              const char* encodedBundle,
107                              const char* theme);
108
109     void dispatchJavaScriptEvent(JSGlobalContextRef ctx,
110                                  CustomEventType eventType,
111                                  void* data);
112
113     static bool s_sanityCheck;
114 };
115
116 IMPLEMENT_SINGLETON(PluginLogic);
117
118 bool PluginLogic::Impl::s_sanityCheck = false;
119
120 #define PLUGIN_LOGIC_SANITY_CHECK \
121     if(!s_sanityCheck)\
122     {\
123         LogError("Object is not available. Wrong flow occured");\
124         return;\
125     }
126
127 PluginLogic::Impl::Impl()
128 {
129     s_sanityCheck = true;
130
131     DPL::Log::LogSystemSingleton::Instance().SetTag("WRT_PLUGINS");
132     LogDebug("Initializing Plugin Logic...");
133     m_pluginsSupport = PluginContainerSupportPtr(new PluginContainerSupport());
134
135     // explicit call to keep singleton's lifetime until calling destructor.
136     JsFunctionManagerSingleton::Instance();
137     JavaScriptInterfaceSingleton::Instance();
138 }
139
140 PluginLogic::Impl::~Impl()
141 {
142     LogDebug("");
143
144     s_sanityCheck = false;
145
146     FOREACH(it, m_sessions)
147     {
148         LogError("Must stop widget session before exit!");
149         it->second->stopSession();
150     }
151
152     LogDebug("Deinitializing plugin Logic...");
153 }
154
155 void PluginLogic::initSession(int widgetHandle)
156 {
157     m_impl->initSession(widgetHandle);
158 }
159
160 void PluginLogic::startSession(int widgetHandle,
161                                JSGlobalContextRef ctx,
162                                double scaleFactor,
163                                const char* encodedBundle,
164                                const char* theme)
165 {
166     m_impl->startSession(widgetHandle, ctx, scaleFactor, encodedBundle, theme);
167 }
168
169 void PluginLogic::stopSession(JSGlobalContextRef context)
170 {
171     m_impl->stopSession(context);
172 }
173
174 void PluginLogic::performLibrariesUnload()
175 {
176     LogError("Libraries unload TURNED OFF");
177 //    m_impl->performLibrariesUnload();
178 }
179
180 bool PluginLogic::loadPluginOnDemand(
181     const WrtDB::DbPluginHandle &pluginHandle,
182     JavaScriptObject& parentObject,
183     JSGlobalContextRef context)
184 {
185     return m_impl->loadPluginOnDemand(pluginHandle, parentObject, context);
186 }
187
188 void PluginLogic::loadPluginsIntoIframes(JSGlobalContextRef context)
189 {
190     LogError("This function is Deprecated");
191 }
192
193 void PluginLogic::setCustomProperties(double scaleFactor,
194                                       const char* encodedBundle,
195                                       const char* theme)
196 {
197     LogError("This function is DEPRECATED");
198 }
199
200 void PluginLogic::setCustomProperties(JSGlobalContextRef context,
201                                       double scaleFactor,
202                                       const char* encodedBundle,
203                                       const char* theme)
204 {
205     m_impl->setCustomProperties(context, scaleFactor, encodedBundle, theme);
206 }
207
208 void PluginLogic::dispatchJavaScriptEvent(CustomEventType eventType)
209 {
210     LogError("This function is DEPRECATED");
211 }
212
213 void PluginLogic::dispatchJavaScriptEvent(JSGlobalContextRef context,
214                                           CustomEventType eventType,
215                                           void *data)
216 {
217     m_impl->dispatchJavaScriptEvent(context, eventType, data);
218 }
219
220 void PluginLogic::loadFrame(JSGlobalContextRef context)
221 {
222     m_impl->loadFrame(context);
223 }
224
225 void PluginLogic::unloadFrame(JSGlobalContextRef context)
226 {
227     m_impl->unloadFrame(context);
228 }
229
230 PluginLogic::PluginLogic() : m_impl(new PluginLogic::Impl())
231 {
232 }
233
234 PluginLogic::~PluginLogic()
235 {
236 }
237
238 void PluginLogic::Impl::initSession(int widgetHandle)
239 {
240     LogInfo("init pluginLogic...");
241
242     m_pluginsSupport->Initialize(widgetHandle);
243
244     //add standard objects
245     LogDebug("Preload plugins so file");
246
247     PluginContainerSupport::PluginsList pluginList =
248                                           m_pluginsSupport->getPluginsList();
249
250     FOREACH(it, pluginList)
251     {
252         PluginModelPtr& pluginModel = *it;
253
254         if (!pluginModel->LibraryDependencies.Get()->empty())
255         {
256             // Only Root Object
257             continue;
258         }
259
260         PluginPtr pluginLib = pluginModel->LibraryInstance.Get();
261
262         if (!pluginLib)
263         {
264             std::string path = pluginModel->LibraryPath.Get() +
265                                std::string(LIBRARY_PATH_SEPARATOR) +
266                                pluginModel->LibraryName.Get();
267
268             pluginLib = Plugin::LoadFromFile(path);
269
270             if (!pluginLib)
271             {
272                 LogError("Loading library failed");
273             } else
274             {
275                 pluginModel->LibraryInstance.Set(pluginLib);
276
277                 LogDebug("pluginModel->LibraryInstance.Set() : " << pluginLib->GetFileName());
278             }
279         }
280         else
281         {
282             LogDebug("Already loaded");
283         }
284     }
285
286     LogDebug("Preload plugins so file_done");
287 }
288
289 void PluginLogic::Impl::startSession(int widgetHandle,
290                                      JSGlobalContextRef context,
291                                      double scaleFactor,
292                                      const char* encodedBundle,
293                                      const char* theme)
294 {
295     LogInfo("Starting widget session...");
296
297     if (!m_pluginsSupport->isInitialized())
298     {
299         m_pluginsSupport->Initialize(widgetHandle);
300     }
301     auto sessionIt = m_sessions.find(context);
302
303     // Check if corresponding session if not already created
304     if (sessionIt != m_sessions.end())
305     {
306         LogWarning("Session already started!");
307         return;
308     }
309
310     auto newSession = JSPageSessionPtr(new JSPageSession(m_pluginsSupport));
311     newSession->startSession(widgetHandle,
312                              context,
313                              scaleFactor,
314                              encodedBundle,
315                              theme);
316
317     m_sessions[context] = newSession;
318 }
319
320 void PluginLogic::Impl::stopSession(JSGlobalContextRef context)
321 {
322     LogInfo("Stopping widget session...");
323
324     auto sessionIt = m_sessions.find(context);
325     if (sessionIt == m_sessions.end())
326     {
327         LogError("Session not exist!");
328         return;
329     }
330
331     sessionIt->second->stopSession();
332     m_sessions.erase(sessionIt);
333
334     LogInfo("Widget session stopped.");
335 }
336
337 bool PluginLogic::Impl::loadPluginOnDemand(
338     const WrtDB::DbPluginHandle &pluginHandle,
339     JavaScriptObject& parentObject,
340     JSGlobalContextRef context
341     )
342 {
343     LogInfo("Load plugin on demand");
344
345     auto sessionIt = m_sessions.find(context);
346     if (sessionIt == m_sessions.end())
347     {
348         LogWarning("Session not exist!");
349         return false;
350     }
351
352     return sessionIt->second->loadPluginOnDemand(pluginHandle,
353                                                  parentObject,
354                                                  context);
355 }
356
357 void PluginLogic::Impl::loadFrame(JSGlobalContextRef context)
358 {
359     LogDebug("Load a frame");
360
361     PLUGIN_LOGIC_SANITY_CHECK
362
363     auto sessionIt = m_sessions.find(context);
364     if (sessionIt == m_sessions.end())
365     {
366         LogWarning("Session not exist!");
367         return;
368     }
369
370     sessionIt->second->loadFrame(context);
371 }
372
373 void PluginLogic::Impl::unloadFrame(JSGlobalContextRef context)
374 {
375     LogDebug("Unload a frame");
376
377     PLUGIN_LOGIC_SANITY_CHECK
378
379     auto sessionIt = m_sessions.find(context);
380     if (sessionIt == m_sessions.end())
381     {
382         LogWarning("Session not exist!");
383         return;
384     }
385
386     sessionIt->second->unloadFrame(context);
387     m_sessions.erase(sessionIt);
388 }
389
390 void PluginLogic::Impl::setCustomProperties(JSGlobalContextRef context,
391                                             double scaleFactor,
392                                             const char* encodedBundle,
393                                             const char* theme)
394 {
395     LogInfo("set properties of window object " << scaleFactor << ", "
396             << encodedBundle << ", " << theme);
397
398     PLUGIN_LOGIC_SANITY_CHECK
399
400     auto sessionIt = m_sessions.find(context);
401     if (sessionIt == m_sessions.end())
402     {
403         LogWarning("Session not exist!");
404         return;
405     }
406
407     sessionIt->second->setCustomProperties(scaleFactor,
408                                            encodedBundle,
409                                            theme);
410
411 }
412
413 void PluginLogic::Impl::dispatchJavaScriptEvent(JSGlobalContextRef context,
414                                                 CustomEventType eventType,
415                                                 void* data)
416 {
417     LogDebug("Dispatch event");
418
419     PLUGIN_LOGIC_SANITY_CHECK
420
421     auto sessionIt = m_sessions.find(context);
422     if (sessionIt == m_sessions.end())
423     {
424         LogWarning("Session not exist!");
425         return;
426     }
427
428     sessionIt->second->dispatchJavaScriptEvent(eventType, data);
429
430
431 }