315bb74d707d45062b1b0f7c6e6deee0df71e171
[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 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     static bool s_sanityCheck;
113 };
114
115 IMPLEMENT_SINGLETON(PluginLogic);
116
117 bool PluginLogic::Impl::s_sanityCheck = false;
118
119 #define PLUGIN_LOGIC_SANITY_CHECK \
120     if(!s_sanityCheck)\
121     {\
122         LogError("Object is not available. Wrong flow occured");\
123         return;\
124     }
125
126 PluginLogic::Impl::Impl()
127 {
128     s_sanityCheck = true;
129
130     DPL::Log::LogSystemSingleton::Instance().SetTag("WRT_PLUGINS");
131     LogDebug("Initializing Plugin Logic...");
132     m_pluginsSupport = PluginContainerSupportPtr(new PluginContainerSupport());
133
134     // explicit call to keep singleton's lifetime until calling destructor.
135     JsFunctionManagerSingleton::Instance();
136     JavaScriptInterfaceSingleton::Instance();
137 }
138
139 PluginLogic::Impl::~Impl()
140 {
141     LogDebug("");
142
143     s_sanityCheck = false;
144
145     FOREACH(it, m_sessions)
146     {
147         LogError("Must stop widget session before exit!");
148         it->second->stopSession();
149     }
150
151     LogDebug("Deinitializing plugin Logic...");
152 }
153
154
155 void PluginLogic::startSession(int widgetHandle,
156                                JSGlobalContextRef ctx,
157                                double scaleFactor,
158                                const char* encodedBundle,
159                                const char* theme)
160 {
161     m_impl->startSession(widgetHandle, ctx, scaleFactor, encodedBundle, theme);
162 }
163
164 void PluginLogic::stopSession(JSGlobalContextRef context)
165 {
166     m_impl->stopSession(context);
167 }
168
169 void PluginLogic::performLibrariesUnload()
170 {
171     LogError("Libraries unload TURNED OFF");
172 //    m_impl->performLibrariesUnload();
173 }
174
175 bool PluginLogic::loadPluginOnDemand(
176     const WrtDB::DbPluginHandle &pluginHandle,
177     JavaScriptObject& parentObject,
178     JSGlobalContextRef context)
179 {
180     return m_impl->loadPluginOnDemand(pluginHandle, parentObject, context);
181 }
182
183 void PluginLogic::loadPluginsIntoIframes(JSGlobalContextRef context)
184 {
185     LogError("This function is Deprecated");
186 }
187
188 void PluginLogic::setCustomProperties(double scaleFactor,
189                                       const char* encodedBundle,
190                                       const char* theme)
191 {
192     LogError("This function is DEPRECATED");
193 }
194
195 void PluginLogic::setCustomProperties(JSGlobalContextRef context,
196                                       double scaleFactor,
197                                       const char* encodedBundle,
198                                       const char* theme)
199 {
200     m_impl->setCustomProperties(context, scaleFactor, encodedBundle, theme);
201 }
202
203 void PluginLogic::dispatchJavaScriptEvent(CustomEventType eventType)
204 {
205     LogError("This function is DEPRECATED");
206 }
207
208 void PluginLogic::dispatchJavaScriptEvent(JSGlobalContextRef context,
209                                           CustomEventType eventType,
210                                           void *data)
211 {
212     m_impl->dispatchJavaScriptEvent(context, eventType, data);
213 }
214
215 void PluginLogic::loadFrame(JSGlobalContextRef context)
216 {
217     m_impl->loadFrame(context);
218 }
219
220 void PluginLogic::unloadFrame(JSGlobalContextRef context)
221 {
222     m_impl->unloadFrame(context);
223 }
224
225 PluginLogic::PluginLogic() : m_impl(new PluginLogic::Impl())
226 {
227 }
228
229 PluginLogic::~PluginLogic()
230 {
231 }
232
233 void PluginLogic::Impl::startSession(int widgetHandle,
234                                      JSGlobalContextRef context,
235                                      double scaleFactor,
236                                      const char* encodedBundle,
237                                      const char* theme)
238 {
239     LogInfo("Starting widget session...");
240
241     if (!m_pluginsSupport->isInitialized())
242         m_pluginsSupport->readAllowedPlugins(widgetHandle);
243
244     auto sessionIt = m_sessions.find(context);
245
246     // Check if corresponding session if not already created
247     if (sessionIt != m_sessions.end())
248     {
249         LogWarning("Session already started!");
250         return;
251     }
252
253     auto newSession = JSPageSessionPtr(new JSPageSession(m_pluginsSupport));
254     newSession->startSession(widgetHandle,
255                              context,
256                              scaleFactor,
257                              encodedBundle,
258                              theme);
259
260     m_sessions[context] = newSession;
261 }
262
263 void PluginLogic::Impl::stopSession(JSGlobalContextRef context)
264 {
265     LogInfo("Stopping widget session...");
266
267     auto sessionIt = m_sessions.find(context);
268     if (sessionIt == m_sessions.end())
269     {
270         LogError("Session not exist!");
271         return;
272     }
273
274     sessionIt->second->stopSession();
275     m_sessions.erase(sessionIt);
276
277     LogInfo("Widget session stopped.");
278 }
279
280 bool PluginLogic::Impl::loadPluginOnDemand(
281     const WrtDB::DbPluginHandle &pluginHandle,
282     JavaScriptObject& parentObject,
283     JSGlobalContextRef context
284     )
285 {
286     LogInfo("Load plugin on demand");
287
288     auto sessionIt = m_sessions.find(context);
289     if (sessionIt == m_sessions.end())
290     {
291         LogWarning("Session not exist!");
292         return false;
293     }
294
295     return sessionIt->second->loadPluginOnDemand(pluginHandle,
296                                                  parentObject,
297                                                  context);
298 }
299
300 void PluginLogic::Impl::loadFrame(JSGlobalContextRef context)
301 {
302     LogDebug("Load a frame");
303
304     PLUGIN_LOGIC_SANITY_CHECK
305
306     auto sessionIt = m_sessions.find(context);
307     if (sessionIt == m_sessions.end())
308     {
309         LogWarning("Session not exist!");
310         return;
311     }
312
313     sessionIt->second->loadFrame(context);
314 }
315
316 void PluginLogic::Impl::unloadFrame(JSGlobalContextRef context)
317 {
318     LogDebug("Unload a frame");
319
320     PLUGIN_LOGIC_SANITY_CHECK
321
322     auto sessionIt = m_sessions.find(context);
323     if (sessionIt == m_sessions.end())
324     {
325         LogWarning("Session not exist!");
326         return;
327     }
328
329     sessionIt->second->unloadFrame(context);
330     m_sessions.erase(sessionIt);
331 }
332
333 void PluginLogic::Impl::setCustomProperties(JSGlobalContextRef context,
334                                             double scaleFactor,
335                                             const char* encodedBundle,
336                                             const char* theme)
337 {
338     LogInfo("set properties of window object " << scaleFactor << ", "
339             << encodedBundle << ", " << theme);
340
341     PLUGIN_LOGIC_SANITY_CHECK
342
343     auto sessionIt = m_sessions.find(context);
344     if (sessionIt == m_sessions.end())
345     {
346         LogWarning("Session not exist!");
347         return;
348     }
349
350     sessionIt->second->setCustomProperties(scaleFactor,
351                                            encodedBundle,
352                                            theme);
353
354 }
355
356 void PluginLogic::Impl::dispatchJavaScriptEvent(JSGlobalContextRef context,
357                                                 CustomEventType eventType,
358                                                 void* data)
359 {
360     LogDebug("Dispatch event");
361
362     PLUGIN_LOGIC_SANITY_CHECK
363
364     auto sessionIt = m_sessions.find(context);
365     if (sessionIt == m_sessions.end())
366     {
367         LogWarning("Session not exist!");
368         return;
369     }
370
371     sessionIt->second->dispatchJavaScriptEvent(eventType, data);
372
373
374 }