Support plugin without feature define
[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->readRootPlugins(widgetHandle);
243         m_pluginsSupport->readAllowedPlugins(widgetHandle);
244     }
245     auto sessionIt = m_sessions.find(context);
246
247     // Check if corresponding session if not already created
248     if (sessionIt != m_sessions.end())
249     {
250         LogWarning("Session already started!");
251         return;
252     }
253
254     auto newSession = JSPageSessionPtr(new JSPageSession(m_pluginsSupport));
255     newSession->startSession(widgetHandle,
256                              context,
257                              scaleFactor,
258                              encodedBundle,
259                              theme);
260
261     m_sessions[context] = newSession;
262 }
263
264 void PluginLogic::Impl::stopSession(JSGlobalContextRef context)
265 {
266     LogInfo("Stopping widget session...");
267
268     auto sessionIt = m_sessions.find(context);
269     if (sessionIt == m_sessions.end())
270     {
271         LogError("Session not exist!");
272         return;
273     }
274
275     sessionIt->second->stopSession();
276     m_sessions.erase(sessionIt);
277
278     LogInfo("Widget session stopped.");
279 }
280
281 bool PluginLogic::Impl::loadPluginOnDemand(
282     const WrtDB::DbPluginHandle &pluginHandle,
283     JavaScriptObject& parentObject,
284     JSGlobalContextRef context
285     )
286 {
287     LogInfo("Load plugin on demand");
288
289     auto sessionIt = m_sessions.find(context);
290     if (sessionIt == m_sessions.end())
291     {
292         LogWarning("Session not exist!");
293         return false;
294     }
295
296     return sessionIt->second->loadPluginOnDemand(pluginHandle,
297                                                  parentObject,
298                                                  context);
299 }
300
301 void PluginLogic::Impl::loadFrame(JSGlobalContextRef context)
302 {
303     LogDebug("Load a frame");
304
305     PLUGIN_LOGIC_SANITY_CHECK
306
307     auto sessionIt = m_sessions.find(context);
308     if (sessionIt == m_sessions.end())
309     {
310         LogWarning("Session not exist!");
311         return;
312     }
313
314     sessionIt->second->loadFrame(context);
315 }
316
317 void PluginLogic::Impl::unloadFrame(JSGlobalContextRef context)
318 {
319     LogDebug("Unload a frame");
320
321     PLUGIN_LOGIC_SANITY_CHECK
322
323     auto sessionIt = m_sessions.find(context);
324     if (sessionIt == m_sessions.end())
325     {
326         LogWarning("Session not exist!");
327         return;
328     }
329
330     sessionIt->second->unloadFrame(context);
331     m_sessions.erase(sessionIt);
332 }
333
334 void PluginLogic::Impl::setCustomProperties(JSGlobalContextRef context,
335                                             double scaleFactor,
336                                             const char* encodedBundle,
337                                             const char* theme)
338 {
339     LogInfo("set properties of window object " << scaleFactor << ", "
340             << encodedBundle << ", " << theme);
341
342     PLUGIN_LOGIC_SANITY_CHECK
343
344     auto sessionIt = m_sessions.find(context);
345     if (sessionIt == m_sessions.end())
346     {
347         LogWarning("Session not exist!");
348         return;
349     }
350
351     sessionIt->second->setCustomProperties(scaleFactor,
352                                            encodedBundle,
353                                            theme);
354
355 }
356
357 void PluginLogic::Impl::dispatchJavaScriptEvent(JSGlobalContextRef context,
358                                                 CustomEventType eventType,
359                                                 void* data)
360 {
361     LogDebug("Dispatch event");
362
363     PLUGIN_LOGIC_SANITY_CHECK
364
365     auto sessionIt = m_sessions.find(context);
366     if (sessionIt == m_sessions.end())
367     {
368         LogWarning("Session not exist!");
369         return;
370     }
371
372     sessionIt->second->dispatchJavaScriptEvent(eventType, data);
373
374
375 }