Source code formating unification
[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   public:
81     Impl();
82     ~Impl();
83
84     // Widget session
85     void initSession(int widgetHandle);
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 void PluginLogic::initSession(int widgetHandle)
155 {
156     m_impl->initSession(widgetHandle);
157 }
158
159 void PluginLogic::startSession(int widgetHandle,
160                                JSGlobalContextRef ctx,
161                                double scaleFactor,
162                                const char* encodedBundle,
163                                const char* theme)
164 {
165     m_impl->startSession(widgetHandle, ctx, scaleFactor, encodedBundle, theme);
166 }
167
168 void PluginLogic::stopSession(JSGlobalContextRef context)
169 {
170     m_impl->stopSession(context);
171 }
172
173 void PluginLogic::performLibrariesUnload()
174 {
175     LogError("Libraries unload TURNED OFF");
176     //    m_impl->performLibrariesUnload();
177 }
178
179 bool PluginLogic::loadPluginOnDemand(
180     const WrtDB::DbPluginHandle &pluginHandle,
181     JavaScriptObject& parentObject,
182     JSGlobalContextRef context)
183 {
184     return m_impl->loadPluginOnDemand(pluginHandle, parentObject, context);
185 }
186
187 void PluginLogic::loadPluginsIntoIframes(JSGlobalContextRef context)
188 {
189     LogError("This function is Deprecated");
190 }
191
192 void PluginLogic::setCustomProperties(double scaleFactor,
193                                       const char* encodedBundle,
194                                       const char* theme)
195 {
196     LogError("This function is DEPRECATED");
197 }
198
199 void PluginLogic::setCustomProperties(JSGlobalContextRef context,
200                                       double scaleFactor,
201                                       const char* encodedBundle,
202                                       const char* theme)
203 {
204     m_impl->setCustomProperties(context, scaleFactor, encodedBundle, theme);
205 }
206
207 void PluginLogic::dispatchJavaScriptEvent(CustomEventType eventType)
208 {
209     LogError("This function is DEPRECATED");
210 }
211
212 void PluginLogic::dispatchJavaScriptEvent(JSGlobalContextRef context,
213                                           CustomEventType eventType,
214                                           void *data)
215 {
216     m_impl->dispatchJavaScriptEvent(context, eventType, data);
217 }
218
219 void PluginLogic::loadFrame(JSGlobalContextRef context)
220 {
221     m_impl->loadFrame(context);
222 }
223
224 void PluginLogic::unloadFrame(JSGlobalContextRef context)
225 {
226     m_impl->unloadFrame(context);
227 }
228
229 PluginLogic::PluginLogic() : m_impl(new PluginLogic::Impl())
230 {}
231
232 PluginLogic::~PluginLogic()
233 {}
234
235 void PluginLogic::Impl::initSession(int widgetHandle)
236 {
237     LogInfo("init pluginLogic...");
238
239     m_pluginsSupport->Initialize(widgetHandle);
240
241     //add standard objects
242     LogDebug("Preload plugins so file");
243
244     PluginContainerSupport::PluginsList pluginList =
245         m_pluginsSupport->getPluginsList();
246
247     FOREACH(it, pluginList)
248     {
249         PluginModelPtr& pluginModel = *it;
250
251         if (!pluginModel->LibraryDependencies.Get()->empty()) {
252             // Only Root Object
253             continue;
254         }
255
256         PluginPtr pluginLib = pluginModel->LibraryInstance.Get();
257
258         if (!pluginLib) {
259             std::string path = pluginModel->LibraryPath.Get() +
260                 std::string(LIBRARY_PATH_SEPARATOR) +
261                 pluginModel->LibraryName.Get();
262
263             pluginLib = Plugin::LoadFromFile(path);
264
265             if (!pluginLib) {
266                 LogError("Loading library failed");
267             } else {
268                 pluginModel->LibraryInstance.Set(pluginLib);
269
270                 LogDebug(
271                     "pluginModel->LibraryInstance.Set() : " <<
272                     pluginLib->GetFileName());
273             }
274         } else {
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         m_pluginsSupport->Initialize(widgetHandle);
292     }
293     auto sessionIt = m_sessions.find(context);
294
295     // Check if corresponding session if not already created
296     if (sessionIt != m_sessions.end()) {
297         LogWarning("Session already started!");
298         return;
299     }
300
301     auto newSession = JSPageSessionPtr(new JSPageSession(m_pluginsSupport));
302     newSession->startSession(widgetHandle,
303                              context,
304                              scaleFactor,
305                              encodedBundle,
306                              theme);
307
308     m_sessions[context] = newSession;
309 }
310
311 void PluginLogic::Impl::stopSession(JSGlobalContextRef context)
312 {
313     LogInfo("Stopping widget session...");
314
315     auto sessionIt = m_sessions.find(context);
316     if (sessionIt == m_sessions.end()) {
317         LogError("Session not exist!");
318         return;
319     }
320
321     sessionIt->second->stopSession();
322     m_sessions.erase(sessionIt);
323
324     LogInfo("Widget session stopped.");
325 }
326
327 bool PluginLogic::Impl::loadPluginOnDemand(
328     const WrtDB::DbPluginHandle &pluginHandle,
329     JavaScriptObject& parentObject,
330     JSGlobalContextRef context
331     )
332 {
333     LogInfo("Load plugin on demand");
334
335     auto sessionIt = m_sessions.find(context);
336     if (sessionIt == m_sessions.end()) {
337         LogWarning("Session not exist!");
338         return false;
339     }
340
341     return sessionIt->second->loadPluginOnDemand(pluginHandle,
342                                                  parentObject,
343                                                  context);
344 }
345
346 void PluginLogic::Impl::loadFrame(JSGlobalContextRef context)
347 {
348     LogDebug("Load a frame");
349
350     PLUGIN_LOGIC_SANITY_CHECK
351
352     auto sessionIt = m_sessions.find(context);
353     if (sessionIt == m_sessions.end()) {
354         LogWarning("Session not exist!");
355         return;
356     }
357
358     sessionIt->second->loadFrame(context);
359 }
360
361 void PluginLogic::Impl::unloadFrame(JSGlobalContextRef context)
362 {
363     LogDebug("Unload a frame");
364
365     PLUGIN_LOGIC_SANITY_CHECK
366
367     auto sessionIt = m_sessions.find(context);
368     if (sessionIt == m_sessions.end()) {
369         LogWarning("Session not exist!");
370         return;
371     }
372
373     sessionIt->second->unloadFrame(context);
374     m_sessions.erase(sessionIt);
375 }
376
377 void PluginLogic::Impl::setCustomProperties(JSGlobalContextRef context,
378                                             double scaleFactor,
379                                             const char* encodedBundle,
380                                             const char* theme)
381 {
382     LogInfo(
383         "set properties of window object " << scaleFactor << ", "
384                                            << encodedBundle << ", " <<
385         theme);
386
387     PLUGIN_LOGIC_SANITY_CHECK
388
389     auto sessionIt = m_sessions.find(context);
390     if (sessionIt == m_sessions.end()) {
391         LogWarning("Session not exist!");
392         return;
393     }
394
395     sessionIt->second->setCustomProperties(scaleFactor,
396                                            encodedBundle,
397                                            theme);
398 }
399
400 void PluginLogic::Impl::dispatchJavaScriptEvent(JSGlobalContextRef context,
401                                                 CustomEventType eventType,
402                                                 void* data)
403 {
404     LogDebug("Dispatch event");
405
406     PLUGIN_LOGIC_SANITY_CHECK
407
408     auto sessionIt = m_sessions.find(context);
409     if (sessionIt == m_sessions.end()) {
410         LogWarning("Session not exist!");
411         return;
412     }
413
414     sessionIt->second->dispatchJavaScriptEvent(eventType, data);
415 }