2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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)
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
27 #include "plugin_logic.h"
29 #include <dpl/assert.h>
30 #include <dpl/scoped_array.h>
31 #include <dpl/log/secure_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>
38 #include <JavaScriptCore/JavaScript.h>
41 #include <sys/types.h>
52 #include <wrt_plugin_export.h>
53 #include <js_overlay_types.h>
57 #include "plugin_model.h"
58 #include "javascript_interface.h"
59 #include "js_function_manager.h"
60 #include "plugin_container_support.h"
62 #include "js_page_session.h"
65 using namespace WrtDB;
66 using namespace WrtPlugins::W3C;
69 const char *LIBRARY_PATH_SEPARATOR = "/";
72 class JSPageSession::Impl
75 typedef std::set<PluginPtr> LoadedPlugins;
76 typedef std::set<JSGlobalContextRef> LoadedContexts;
79 ///< Widget handle using this session
82 //view for this session
83 JSGlobalContextRef m_context;
85 bool m_sessionStarted;
87 ///< JS object explorer for this session
88 Explorer* m_objectExplorer;
90 PluginContainerSupportPtr m_pluginsSupport;
92 ///< All loaded plugins. Each one must be unloaded. Plugins means
93 //set of features connected with such plugin (library)
94 LoadedPlugins m_loadedPlugins;
96 // Set of currently loaded web pages' contexts. These contexts are
97 // exactly matching with each frames' global context.
98 LoadedContexts m_loadedContexts;
101 PluginPtr loadLibrary(PluginModelPtr& pluginModel);
103 void installStandardFunctions();
104 void installRootPlugins();
105 void installRequestedFeatures();
107 //returns true if success or false if failed
108 bool installPlugin(PluginModelPtr plugin);
109 bool installPluginOnDemand(PluginModelPtr plugin,
110 JavaScriptObject& parentObject,
111 JSGlobalContextRef context);
113 void unloadPluginsFromSession();
116 Impl(const PluginContainerSupportPtr& containerSupport);
120 void startSession(int widgetHandle,
121 JSGlobalContextRef view,
123 const char* encodedBundle,
128 void performLibrariesUnload();
130 bool loadPluginOnDemand(const WrtDB::DbPluginHandle &pluginHandle,
131 JavaScriptObject& parentObject,
132 JSGlobalContextRef context);
134 void loadFrame(JSGlobalContextRef context);
135 void unloadFrame(JSGlobalContextRef context);
137 void setCustomProperties(double scaleFactor,
138 const char* encodedBundle,
141 void dispatchJavaScriptEvent(CustomEventType eventType, void* data);
144 JSPageSession::Impl::Impl(const PluginContainerSupportPtr& support) :
147 m_sessionStarted(false),
148 m_objectExplorer(NULL)
150 _D("Initializing Page Session");
151 m_pluginsSupport = support;
154 JSPageSession::Impl::~Impl()
156 if (m_sessionStarted) {
157 LogError("Must stop widget session before exit!");
161 _D("Deinitializing Page Session");
164 void JSPageSession::Impl::installStandardFunctions()
166 _D("========== install standard Functions START ==========");
168 //add standard functions
169 FOREACH(it, JsFunctionManagerSingleton::Instance().getFunctions()) {
170 m_objectExplorer->registerObject(*it, NULL);
173 _D("========== install standard Functions END ==========");
176 void JSPageSession::Impl::installRootPlugins()
178 _D("========== install root Functions START ==========");
180 PluginContainerSupport::PluginsList rootPlugins =
181 m_pluginsSupport->getRootPlugins();
182 FOREACH(it, rootPlugins)
187 _D("========== install root Functions END ==========");
190 bool JSPageSession::Impl::installPlugin(PluginModelPtr plugin)
192 Assert(plugin && "Plugin Model is NULL");
193 PluginPtr library = loadLibrary(plugin);
196 _E("Loading library failed");
200 _D("Install Plugin : %s", library->GetFileName().c_str());
202 // Register new class
203 FOREACH(it, *(library->GetClassList()))
205 if (!m_objectExplorer->registerObject(*it, NULL)) {
206 _E("Object Registration failed : %s", (*it)->getName().c_str());
212 void JSPageSession::Impl::installRequestedFeatures()
214 _D("========== install requested Features START ==========");
216 std::list<std::string> allowedFeatures =
217 m_pluginsSupport->getAllowedFeatures(m_widgetHandle);
219 PluginContainerSupport::PluginsList allowedPlugins;
221 FOREACH(feature, allowedFeatures)
223 _D("Processing feature: %s", (*feature).c_str());
225 PluginModelPtr plugin = m_pluginsSupport->getPluginForFeature(*feature);
228 _W("It didn't have plugins! : %s", (*feature).c_str());
232 ImplementedObjectsList implObjs =
234 getImplementedObjectsForPluginHandle(plugin->Handle.Get());
236 FOREACH(obj, implObjs)
238 _D("Processing object: %s", (*obj).c_str());
239 /* This can be optimalized, but would need extra data in database.
240 * There should be a list of features that are allowed to be
241 * installed at widget start */
242 if (obj->find(".") == obj->rfind(".")) {
243 allowedPlugins.push_back(plugin);
244 _D("Plugin will be added: %s", plugin->LibraryName.Get().c_str());
250 FOREACH(plugin, allowedPlugins)
252 _D("Installation plugin: %s", (*plugin)->LibraryName.Get().c_str());
253 installPlugin(*plugin);
256 _D("========== install requested Features END ==========");
259 bool JSPageSession::Impl::loadPluginOnDemand(
260 const WrtDB::DbPluginHandle &pluginHandle,
261 JavaScriptObject& parentObject,
262 JSGlobalContextRef context)
264 Assert(parentObject.instance &&
265 !parentObject.name.empty()
266 && "Wrong arguments");
268 if (!m_sessionStarted) {
269 _W("Session not started");
272 // //TODO here may be a bug. if plugin contains feature rejected and
274 // LogDebug("Installing feature : " << widgetFeature.name);
275 // if (widgetFeature.rejected) {
276 // LogWarning("This api-feature was rejected");
280 // auto plugin = m_pluginsSupport->getPluginModelById(pluginHandle);
282 // LogError("Failed to load plugin. plugin handle: " <<
286 m_pluginsSupport->registerPluginModel(pluginHandle);
287 return installPluginOnDemand(
288 m_pluginsSupport->getPluginModelById(pluginHandle),
293 bool JSPageSession::Impl::installPluginOnDemand(PluginModelPtr plugin,
294 JavaScriptObject& parentObject,
295 JSGlobalContextRef context)
297 Assert(plugin && "Plugin Model is NULL");
298 PluginPtr library = loadLibrary(plugin);
301 _E("Loading library failed");
305 _D("Install Plugin %s", library->GetFileName().c_str());
307 if (!(parentObject.instance)) {
308 _E("NULL pointer value");
312 JSObjectPtr parent(new JSObject(parentObject.instance));
314 if (!parent->getObject()) {
315 _E("NULL pointer value");
320 FOREACH(it, *(library->GetClassList()))
322 bool installationStatus =
323 m_objectExplorer->registerObject(*it,
328 if (!installationStatus) {
329 _E("Object Registration failed : %s; Parent object name: %s",
330 (*it)->getName().c_str(),
331 parentObject.name.c_str());
336 _D("Plugin on demand registration completed");
340 void JSPageSession::Impl::setCustomProperties(double scaleFactor,
341 const char* encodedBundle,
344 m_objectExplorer->getWindowPropertySupport()
345 ->setScaleToNavigatorProperty(scaleFactor);
346 m_objectExplorer->getWindowPropertySupport()
347 ->setBundleToWindowProperty(encodedBundle);
348 m_objectExplorer->getWindowPropertySupport()
349 ->setThemeToNavigatorProperty(theme);
352 void JSPageSession::Impl::dispatchJavaScriptEvent(CustomEventType eventType,
355 // Check if session is already started
356 if (!m_sessionStarted) {
357 _W("Session not started!");
360 m_objectExplorer->callEventListeners(eventType, data);
363 void JSPageSession::Impl::startSession(int widgetHandle,
364 JSGlobalContextRef context,
366 const char* encodedBundle,
370 // Check if corresponding session if not already created
371 if (m_sessionStarted) {
372 _W("Session already started!");
376 // Create js object explorer object
377 m_objectExplorer = new Explorer(context);
379 m_sessionStarted = true;
380 m_widgetHandle = widgetHandle;
381 m_loadedPlugins.clear();
384 // Register standard features
385 installStandardFunctions();
387 WidgetDAOReadOnly dao(m_widgetHandle);
388 WidgetType appType = dao.getWidgetType();
389 if (appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
390 installRootPlugins();
392 // Register special features
393 installRequestedFeatures();
395 // set scale, bundle as window's property
396 setCustomProperties(scaleFactor, encodedBundle, theme);
399 void JSPageSession::Impl::stopSession()
401 if (!m_sessionStarted) {
402 _W("Session not started!");
406 unloadPluginsFromSession();
407 m_sessionStarted = false;
410 void JSPageSession::Impl::unloadPluginsFromSession()
412 m_objectExplorer->removePluginsFromIframes();
413 m_objectExplorer->cleanIframesData();
415 // delete js object for overlayed js functions
416 FOREACH(it, JsFunctionManagerSingleton::Instance().getFunctions())
418 m_objectExplorer->deregisterObject(*it);
421 // delete js object for plugins
422 FOREACH(pluginIt, m_loadedPlugins)
424 _D("Unregistering plugin %s", (*pluginIt)->GetFileName().c_str());
425 (*pluginIt)->OnWidgetStop(m_widgetHandle);
427 FOREACH(it, *((*pluginIt)->GetClassList())) {
428 m_objectExplorer->deregisterObject(*it);
432 JavaScriptInterfaceSingleton::Instance().invokeGarbageCollector(m_context);
434 m_loadedPlugins.clear();
436 delete m_objectExplorer;
437 m_objectExplorer = NULL;
440 void JSPageSession::Impl::performLibrariesUnload()
443 LogDebug("Perform library unload");
445 size_t unloadedLibraries = 0;
447 FOREACH(pluginIt, m_loadedPlugins)
449 LogDebug("Preparing library: " << (*pluginIt)->LibraryName.Get());
451 PluginPtr plugin = (*pluginIt)->LibraryInstance.Get();
453 LogWarning("Library not loaded " << (*pluginIt)->LibraryName.Get());
457 (*pluginIt)->LibraryInstance.Set(PluginPtr());
460 LogDebug("unloaded " << unloadedLibraries << " unreferenced libraries!");
464 PluginPtr JSPageSession::Impl::loadLibrary(PluginModelPtr& pluginModel)
466 PluginPtr pluginLib = pluginModel->LibraryInstance.Get();
468 std::string path = pluginModel->LibraryPath.Get() +
469 std::string(LIBRARY_PATH_SEPARATOR) +
470 pluginModel->LibraryName.Get();
472 pluginLib = Plugin::LoadFromFile(path);
475 _E("Loading library failed");
477 pluginModel->LibraryInstance.Set(pluginLib);
479 _D("On widget start");
480 // This is first time for this plugin, start widget Session
481 pluginLib->OnWidgetStart(
483 m_loadedPlugins.insert(pluginLib);
485 FOREACH(context, m_loadedContexts)
487 pluginLib->OnFrameLoad(*context);
491 _D("Get from LibraryInstance");
492 _D("On widget start");
493 // This is first time for this plugin, start widget Session
494 pluginLib->OnWidgetStart(
496 m_loadedPlugins.insert(pluginLib);
498 FOREACH(context, m_loadedContexts)
500 pluginLib->OnFrameLoad(*context);
507 void JSPageSession::Impl::loadFrame(JSGlobalContextRef context)
509 if (!m_sessionStarted) {
510 _W("Session NOT started!");
514 m_loadedContexts.insert(context);
516 FOREACH(pluginIt, m_loadedPlugins)
518 _D("Try to call 'OnFrameLoad' callback : %s",
519 (*pluginIt)->GetFileName().c_str());
520 (*pluginIt)->OnFrameLoad(context);
523 m_objectExplorer->loadFrame(context);
526 void JSPageSession::Impl::unloadFrame(JSGlobalContextRef context)
528 if (!m_sessionStarted) {
529 _W("Session NOT started!");
533 m_loadedContexts.erase(context);
535 FOREACH(pluginIt, m_loadedPlugins)
537 _D("Try to call 'OnFrameUnload' callback : %s",
538 (*pluginIt)->GetFileName().c_str());
539 (*pluginIt)->OnFrameUnload(context);
542 m_objectExplorer->unloadFrame(context);
545 void JSPageSession::startSession(int widgetHandle,
546 JSGlobalContextRef ctx,
548 const char* encodedBundle,
551 m_impl->startSession(widgetHandle, ctx, scaleFactor, encodedBundle, theme);
554 void JSPageSession::stopSession()
556 m_impl->stopSession();
559 void JSPageSession::performLibrariesUnload()
561 m_impl->performLibrariesUnload();
564 bool JSPageSession::loadPluginOnDemand(
565 const WrtDB::DbPluginHandle &pluginHandle,
566 JavaScriptObject& parentObject,
567 JSGlobalContextRef context)
569 return m_impl->loadPluginOnDemand(pluginHandle, parentObject, context);
572 void JSPageSession::setCustomProperties(double scaleFactor,
573 const char* encodedBundle,
576 m_impl->setCustomProperties(scaleFactor, encodedBundle, theme);
579 void JSPageSession::dispatchJavaScriptEvent(CustomEventType eventType,
582 m_impl->dispatchJavaScriptEvent(eventType, data);
585 void JSPageSession::loadFrame(JSGlobalContextRef context)
587 m_impl->loadFrame(context);
590 void JSPageSession::unloadFrame(JSGlobalContextRef context)
592 m_impl->unloadFrame(context);
595 JSPageSession::JSPageSession(const PluginContainerSupportPtr& containerSupport)
597 m_impl(new JSPageSession::Impl(containerSupport))
600 JSPageSession::~JSPageSession()