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