Tizen 2.1 base
[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         PluginPtr pluginLib = pluginModel->LibraryInstance.Get();
254
255         if (!pluginLib)
256         {
257             std::string path = pluginModel->LibraryPath.Get() +
258                                std::string(LIBRARY_PATH_SEPARATOR) +
259                                pluginModel->LibraryName.Get();
260
261             pluginLib = Plugin::LoadFromFile(path);
262
263             if (!pluginLib)
264             {
265                 LogError("Loading library failed");
266             } else
267             {
268                 pluginModel->LibraryInstance.Set(pluginLib);
269
270                 LogDebug("pluginModel->LibraryInstance.Set() : " << pluginLib->GetFileName());
271             }
272         }
273         else
274         {
275             LogDebug("Already loaded");
276         }
277     }
278
279     LogDebug("Preload plugins so file_done");
280 }
281
282 void PluginLogic::Impl::startSession(int widgetHandle,
283                                      JSGlobalContextRef context,
284                                      double scaleFactor,
285                                      const char* encodedBundle,
286                                      const char* theme)
287 {
288     LogInfo("Starting widget session...");
289
290     if (!m_pluginsSupport->isInitialized())
291     {
292         m_pluginsSupport->Initialize(widgetHandle);
293     }
294     auto sessionIt = m_sessions.find(context);
295
296     // Check if corresponding session if not already created
297     if (sessionIt != m_sessions.end())
298     {
299         LogWarning("Session already started!");
300         return;
301     }
302
303     auto newSession = JSPageSessionPtr(new JSPageSession(m_pluginsSupport));
304     newSession->startSession(widgetHandle,
305                              context,
306                              scaleFactor,
307                              encodedBundle,
308                              theme);
309
310     m_sessions[context] = newSession;
311 }
312
313 void PluginLogic::Impl::stopSession(JSGlobalContextRef context)
314 {
315     LogInfo("Stopping widget session...");
316
317     auto sessionIt = m_sessions.find(context);
318     if (sessionIt == m_sessions.end())
319     {
320         LogError("Session not exist!");
321         return;
322     }
323
324     sessionIt->second->stopSession();
325     m_sessions.erase(sessionIt);
326
327     LogInfo("Widget session stopped.");
328 }
329
330 bool PluginLogic::Impl::loadPluginOnDemand(
331     const WrtDB::DbPluginHandle &pluginHandle,
332     JavaScriptObject& parentObject,
333     JSGlobalContextRef context
334     )
335 {
336     LogInfo("Load plugin on demand");
337
338     auto sessionIt = m_sessions.find(context);
339     if (sessionIt == m_sessions.end())
340     {
341         LogWarning("Session not exist!");
342         return false;
343     }
344
345     return sessionIt->second->loadPluginOnDemand(pluginHandle,
346                                                  parentObject,
347                                                  context);
348 }
349
350 void PluginLogic::Impl::loadFrame(JSGlobalContextRef context)
351 {
352     LogDebug("Load a frame");
353
354     PLUGIN_LOGIC_SANITY_CHECK
355
356     auto sessionIt = m_sessions.find(context);
357     if (sessionIt == m_sessions.end())
358     {
359         LogWarning("Session not exist!");
360         return;
361     }
362
363     sessionIt->second->loadFrame(context);
364 }
365
366 void PluginLogic::Impl::unloadFrame(JSGlobalContextRef context)
367 {
368     LogDebug("Unload a frame");
369
370     PLUGIN_LOGIC_SANITY_CHECK
371
372     auto sessionIt = m_sessions.find(context);
373     if (sessionIt == m_sessions.end())
374     {
375         LogWarning("Session not exist!");
376         return;
377     }
378
379     sessionIt->second->unloadFrame(context);
380     m_sessions.erase(sessionIt);
381 }
382
383 void PluginLogic::Impl::setCustomProperties(JSGlobalContextRef context,
384                                             double scaleFactor,
385                                             const char* encodedBundle,
386                                             const char* theme)
387 {
388     LogInfo("set properties of window object " << scaleFactor << ", "
389             << encodedBundle << ", " << theme);
390
391     PLUGIN_LOGIC_SANITY_CHECK
392
393     auto sessionIt = m_sessions.find(context);
394     if (sessionIt == m_sessions.end())
395     {
396         LogWarning("Session not exist!");
397         return;
398     }
399
400     sessionIt->second->setCustomProperties(scaleFactor,
401                                            encodedBundle,
402                                            theme);
403
404 }
405
406 void PluginLogic::Impl::dispatchJavaScriptEvent(JSGlobalContextRef context,
407                                                 CustomEventType eventType,
408                                                 void* data)
409 {
410     LogDebug("Dispatch event");
411
412     PLUGIN_LOGIC_SANITY_CHECK
413
414     auto sessionIt = m_sessions.find(context);
415     if (sessionIt == m_sessions.end())
416     {
417         LogWarning("Session not exist!");
418         return;
419     }
420
421     sessionIt->second->dispatchJavaScriptEvent(eventType, data);
422
423
424 }