16b92e61dfcb1f788ca660e2112a75911fb8c247
[framework/web/wrt-plugins-common.git] / src / plugin-loading / plugin.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.cpp
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the implementation file of plugin
21  */
22 #include "plugin.h"
23 #include <dpl/log/log.h>
24 #include <dpl/assert.h>
25 #include <dlfcn.h>
26
27 Plugin::Plugin(const std::string &fileName,
28                void *libHandle,
29                on_widget_start_proc *apiOnWidgetStart,
30                on_widget_init_proc *apiOnWidgetInit,
31                on_widget_stop_proc *apiOnWidgetStop,
32                on_frame_load_proc* apiOnFrameLoad,
33                on_frame_unload_proc* apiOnFrameUnload,
34                const ClassPtrList &apiClassList) :
35     m_fileName(fileName),
36     m_libHandle(libHandle),
37     m_apiOnWidgetStart(apiOnWidgetStart),
38     m_apiOnWidgetInit(apiOnWidgetInit),
39     m_apiOnWidgetStop(apiOnWidgetStop),
40     m_apiOnFrameLoad(apiOnFrameLoad),
41     m_apiOnFrameUnload(apiOnFrameUnload),
42     m_apiClassList(apiClassList)
43 {}
44
45 Plugin::~Plugin()
46 {
47     LogInfo("Unloading plugin library: " << m_fileName << "...");
48
49     // Unload library
50     if (dlclose(m_libHandle) != 0) {
51         LogError("Cannot close plugin handle");
52     } else {
53         LogDebug("Library is unloaded");
54     }
55 }
56
57 PluginPtr Plugin::LoadFromFile(const std::string& fileName)
58 {
59     static bool logEnable = (getenv("WRT_LOAD_PLUGINS_LOG_ENABLE") != NULL);
60
61     LogDebug("LoadFromFile" << fileName);
62
63     void *dllHandle;
64     dllHandle = dlopen(fileName.c_str(), RTLD_LAZY);
65
66     LogDebug("dlopen() done!");
67
68     if (dllHandle == NULL) {
69         const char* error = (const char*)dlerror();
70         LogError(
71             "Failed to load plugin: " << fileName <<
72             ". Reason: " << (error != NULL ? error : "unknown"));
73         PluginPtr empty;
74         return empty;
75     }
76
77     // Load new plugin API
78     on_widget_start_proc *onWidgetStartProcPtr = NULL;
79     on_widget_stop_proc *onWidgetStopProcPtr = NULL;
80     on_widget_init_proc *onWidgetInitProcPtr = NULL;
81     on_frame_load_proc *onFrameLoadProcPtr = NULL;
82     on_frame_unload_proc *onFrameUnloadProcPtr = NULL;
83
84     const js_entity_definition_t *rawClassList = NULL;
85     get_widget_entity_map_proc *getWidgetEntityMapProcPtr = NULL;
86
87     onWidgetStartProcPtr =
88         reinterpret_cast<on_widget_start_proc *>(
89             dlsym(dllHandle, PLUGIN_WIDGET_START_PROC_NAME));
90     onWidgetInitProcPtr =
91         reinterpret_cast<on_widget_init_proc *>(
92             dlsym(dllHandle, PLUGIN_WIDGET_INIT_PROC_NAME));
93     onWidgetStopProcPtr =
94         reinterpret_cast<on_widget_stop_proc *>(
95             dlsym(dllHandle, PLUGIN_WIDGET_STOP_PROC_NAME));
96     onFrameLoadProcPtr =
97         reinterpret_cast<on_frame_load_proc *>(
98             dlsym(dllHandle, PLUGIN_FRAME_LOAD_PROC_NAME));
99     onFrameUnloadProcPtr =
100         reinterpret_cast<on_frame_unload_proc *>(
101             dlsym(dllHandle, PLUGIN_FRAME_UNLOAD_PROC_NAME));
102     getWidgetEntityMapProcPtr =
103         reinterpret_cast<get_widget_entity_map_proc *>(
104             dlsym(dllHandle, PLUGIN_GET_CLASS_MAP_PROC_NAME));
105
106     if (getWidgetEntityMapProcPtr) {
107         rawClassList = (*getWidgetEntityMapProcPtr)();
108
109         if (logEnable)
110         {
111             LogDebug(
112             "rawClassList : " << rawClassList <<
113             "by getWidgetClassMapProcPtr()");
114         }
115     } else {
116         rawClassList =
117             static_cast<const js_entity_definition_t *>(dlsym(dllHandle,
118                                                               PLUGIN_CLASS_MAP_NAME));
119         if (logEnable) { LogDebug("rawClassList : " << rawClassList); }
120     }
121
122     if (NULL == onWidgetStartProcPtr || NULL == onWidgetStopProcPtr ||
123         /*NULL == onWidgetInitProcPtr ||*/ NULL == rawClassList)
124     {
125         if (logEnable)
126         {
127             LogWarning("#####");
128             LogWarning(
129                 "##### Warning: The following plugin does not support new plugin API.");
130             LogWarning(
131                 "##### Old plugin API is deprecated. Please update it to new API");
132             LogWarning("#####");
133             LogWarning(
134                 "##### Plugin: " << fileName <<
135                 " has got deprecated or invalid API");
136             LogWarning("#####");
137         }
138
139         // Will not load plugin
140         dlclose(dllHandle);
141
142         PluginPtr empty;
143         return empty;
144     }
145
146     if (logEnable)
147     {
148         LogInfo("#####");
149         LogInfo("##### Plugin: " << fileName << " supports new plugin API");
150         LogInfo("#####");
151         LogInfo("##### $onWidgetStartProc: " << onWidgetStartProcPtr);
152         LogInfo("##### $onWidgetInitProc: " << onWidgetInitProcPtr);
153         LogInfo("##### $onWidgetStopProc " << onWidgetStopProcPtr);
154         LogInfo("##### $onFrameLoadProc " << onFrameLoadProcPtr);
155         LogInfo("##### $onFrameUnloadProc " << onFrameUnloadProcPtr);
156         LogInfo("##### $classMap: " << reinterpret_cast<const void *>(rawClassList));
157         LogInfo("##### ");
158         LogInfo("##### Class map:");
159     }
160
161     const js_entity_definition_t *rawEntityListIterator = rawClassList;
162     ClassPtrList classList(new Plugin::ClassList());
163
164     // Parse all class definitions
165     while (rawEntityListIterator->parent_name != NULL &&
166            rawEntityListIterator->object_name != NULL)
167     {
168         if (logEnable)
169         {
170             // Logging
171             LogInfo("#####");
172             LogInfo("#####     [" << rawEntityListIterator->object_name << "]: ");
173             LogInfo("#####     Interface: " <<
174                     rawEntityListIterator->interface_name);
175             LogInfo("#####     Parent: " << rawEntityListIterator->parent_name);
176         }
177
178         // Register class
179         classList->push_back(ClassPtr(new Class(rawEntityListIterator)));
180
181         // Go to next class
182         ++rawEntityListIterator;
183     }
184
185     // Load export table
186     LogDebug("Plugin successfuly loaded");
187
188     // Insert to loaded modules list
189
190     PluginPtr instance(new Plugin(fileName,
191                                   dllHandle,
192                                   onWidgetStartProcPtr,
193                                   onWidgetInitProcPtr,
194                                   onWidgetStopProcPtr,
195                                   onFrameLoadProcPtr,
196                                   onFrameUnloadProcPtr,
197                                   classList));
198
199     return instance;
200 }
201
202 std::string Plugin::GetFileName() const
203 {
204     return m_fileName;
205 }
206
207 void Plugin::OnWidgetStart(int widgetId)
208 {
209     if (NULL != m_apiOnWidgetStart) {
210         (*m_apiOnWidgetStart)(widgetId);
211     } else {
212         LogWarning("OnWidgetStart not set!");
213     }
214 }
215
216 void Plugin::OnWidgetInit(feature_mapping_interface_t* mapping)
217 {
218     Assert(NULL != mapping && "NULL mapping interface provided");
219     if (NULL != m_apiOnWidgetInit) {
220         (*m_apiOnWidgetInit)(mapping);
221     } else {
222         LogWarning("OnWidgetInit not set!");
223     }
224 }
225
226 void Plugin::OnWidgetStop(int widgetId)
227 {
228     if (NULL != m_apiOnWidgetStop) {
229         (*m_apiOnWidgetStop)(widgetId);
230     } else {
231         LogWarning("OnWidgetStop not set!");
232     }
233 }
234
235 void Plugin::OnFrameLoad(java_script_context_t context)
236 {
237     if (NULL != m_apiOnFrameLoad) {
238         (*m_apiOnFrameLoad)(context);
239     } else {
240         LogWarning("OnFrameLoad not set!");
241     }
242 }
243
244 void Plugin::OnFrameUnload(java_script_context_t context)
245 {
246     if (NULL != m_apiOnFrameUnload) {
247         (*m_apiOnFrameUnload)(context);
248     } else {
249         LogWarning("OnFrameUnload not set!");
250     }
251 }
252
253 const Plugin::ClassPtrList Plugin::GetClassList() const
254 {
255     return m_apiClassList;
256 }