2d868d89d5acf6eb82c954d9624dcc727b166478
[platform/framework/web/wrt-plugins-common.git] / src / modules / tizen / PluginManager / PluginManager.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        PluginManager.cpp
18  * @author      Lukasz Marek (l.marek@samsung.com)
19  * @version     0.1
20  * @brief
21  */
22
23 #include "PluginManager.h"
24 #include <algorithm>
25 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
26 #include <dpl/wrt-dao-ro/plugin_dao_read_only.h>
27 #include <dpl/wrt-dao-ro/WrtDatabase.h>
28 #include <plugin_logic.h>
29 #include <js_types.h>
30 #include <dpl/wrt-dao-ro/common_dao_types.h>
31 #include <Commons/Exception.h>
32 #include <CommonsJavaScript/Converter.h>
33 #include <dpl/exception.h>
34 #include <dpl/log/log.h>
35 #include <dpl/foreach.h>
36
37 using namespace std;
38
39 namespace {
40 const string GLOBAL_OBJECT_NAME = "GLOBAL_OBJECT";
41 const char* SEPARATOR = ".";
42 }
43
44 namespace WrtDeviceApis {
45 namespace PluginManager {
46 PluginManager::PluginManager(int widgetHandle,
47                              const string &objectUri,
48                              JSObjectRef object,
49                              JSContextRef context) :
50     m_widgetHandle(widgetHandle),
51     m_objectInstance(object),
52     m_objectUri(GLOBAL_OBJECT_NAME),
53     m_shortUri(objectUri),
54     m_context(context)
55 {
56     m_objectUri.append(SEPARATOR).append(objectUri);
57     WrtDB::WrtDatabase::attachToThreadRO();
58 }
59
60 PluginManager::~PluginManager()
61 {
62     ObjectList::iterator it = m_objectList.begin();
63     for (; it != m_objectList.end(); ++it) {
64         JSValueUnprotect(m_context, it->second);
65     }
66     WrtDB::WrtDatabase::detachFromThread();
67 }
68
69 bool PluginManager::hasChild(const string &name) const
70 {
71     const PropertyList &prop = getProperties();
72     return prop.end() != find(prop.begin(), prop.end(), name);
73 }
74
75 bool PluginManager::loadChild(const string &name) const
76 {
77     LogInfo("loading " << name);
78     string localUri = m_objectUri;
79     localUri.append(SEPARATOR).append(name);
80
81     WrtDB::DbPluginHandle handle =
82         WrtDB::PluginDAOReadOnly::getPluginHandleForImplementedObject(localUri);
83     if (handle == WrtDB::INVALID_PLUGIN_HANDLE) {
84         LogError("Plugin not found");
85         return false;
86     }
87
88     WrtDB::DbWidgetFeatureSet features;
89     WrtDB::WidgetType widgetType;
90     Try
91     {
92         WrtDB::WidgetDAOReadOnly dao(m_widgetHandle);
93         features = dao.getFeaturesList();
94         widgetType = dao.getWidgetType();
95     }
96     Catch(WrtDB::WidgetDAOReadOnly::Exception::Base)
97     {
98         // Error while reading database - widget handle may
99         // be invalid or some data may be missing in database
100         LogError("Cannot get feature list");
101         return false;
102     }
103
104     if (widgetType == WrtDB::APP_TYPE_TIZENWEBAPP) {
105         JavaScriptObject jsObject = { m_objectInstance,
106                                       m_shortUri };
107         return PluginLogicSingleton::Instance().loadPluginOnDemand(
108                    handle, jsObject, const_cast<JSGlobalContextRef>(m_context));
109     }
110
111     //check does plugin with feature was requested
112     FOREACH(it, features)
113     {
114         if (it->pluginId == handle) {
115             if (it->rejected) {
116                 LogWarning("Feature rejected by ACE");
117                 continue;
118             }
119
120             JavaScriptObject jsObject = { m_objectInstance,
121                                           m_shortUri };
122
123             return PluginLogicSingleton::Instance().loadPluginOnDemand(
124                        handle, jsObject,
125                        const_cast<JSGlobalContextRef>(m_context));
126         }
127     }
128     LogError("Plugin not loaded");
129     return false;
130 }
131
132 JSValueRef PluginManager::getProperty(const string &name) const
133 {
134     LogDebug("getProperty " << name);
135     ObjectList::const_iterator it = m_objectList.find(name);
136     if (it != m_objectList.end()) {
137         //return already set value
138         return it->second;
139     }
140
141     if (!loadChild(name)) {
142         ThrowMsg(Commons::PlatformException, "Cannot load plugin");
143     }
144
145     it = m_objectList.find(name);
146     if (it != m_objectList.end()) {
147         //return set value
148         return it->second;
149     }
150
151     ThrowMsg(Commons::PlatformException, "Cannot obtain property");
152 }
153
154 bool PluginManager::setProperty(const string &name,
155                                 JSValueRef value)
156 {
157     LogDebug("setProperty " << name);
158     if (m_objectList.count(name) > 0) {
159         JSValueUnprotect(m_context, m_objectList[name]);
160     }
161     JSValueProtect(m_context, value);
162     m_objectList[name] = value;
163     return true;
164 }
165
166 bool PluginManager::deleteProperty(const string &name)
167 {
168     if (m_objectList.count(name) > 0) {
169         LogDebug("deleteProperty " << name);
170         JSValueUnprotect(m_context, m_objectList[name]);
171         m_objectList.erase(name);
172         return true;
173     }
174     return false;
175 }
176
177 Api::IPluginManager::PropertyList PluginManager::getProperties() const
178 {
179     if (!m_propertyCache.IsNull()) {
180         return *m_propertyCache;
181     }
182
183     m_propertyCache = PropertyList();
184
185     WrtDB::WidgetDAOReadOnly dao(m_widgetHandle);
186     string localUri = m_objectUri + SEPARATOR;
187
188     if (dao.getWidgetType() == WrtDB::APP_TYPE_TIZENWEBAPP) {
189         WrtDB::PluginHandleList pluginHandleList =
190             WrtDB::PluginDAOReadOnly::getPluginHandleList();
191
192         FOREACH(it_pluginHandle, pluginHandleList)
193         {
194             WrtDB::ImplementedObjectsList implObjectList =
195                 WrtDB::PluginDAOReadOnly::getImplementedObjectsForPluginHandle(
196                     *it_pluginHandle);
197
198             FOREACH(it_implObject, implObjectList)
199             {
200                 //check if implemented object stats with localUri
201                 if (it_implObject->find(localUri) == 0) {
202                     string property = *it_implObject;
203                     //remove local uri that predicts property name.
204                     property.erase(0, localUri.size());
205                     //check if property has its own properties.
206                     size_t pos = property.find(SEPARATOR);
207                     if (pos != string::npos) {
208                         //if so then remove them.
209                         property.erase(pos);
210                     }
211                     m_propertyCache->push_back(property);
212                 }
213             }
214         }
215     } else {
216         WrtDB::DbWidgetFeatureSet features;
217
218         Try
219         {
220             features = dao.getFeaturesList();
221         }
222         Catch(WrtDB::WidgetDAOReadOnly::Exception::Base)
223         {
224             LogError("Cannot get feature list");
225             ReThrow(Commons::PlatformException);
226         }
227
228         WrtDB::DbWidgetFeatureSet::const_iterator feature = features.begin();
229         for (; feature != features.end(); ++feature) {
230             WrtDB::ImplementedObjectsList implObjs =
231                 WrtDB::PluginDAOReadOnly::getImplementedObjectsForPluginHandle(
232                     feature->pluginId);
233             FOREACH(it, implObjs) {
234                 //check if implemented object stats with localUri
235                 if (it->find(localUri) == 0) {
236                     string property = *it;
237                     //remove local uri that predicts property name.
238                     property.erase(0, localUri.size());
239                     //check if property has its own properties.
240                     size_t pos = property.find(SEPARATOR);
241                     if (pos != string::npos) {
242                         //if so then remove them.
243                         property.erase(pos);
244                     }
245                     m_propertyCache->push_back(property);
246                 }
247             }
248         }
249     }
250
251     return *m_propertyCache;
252 }
253
254 void PluginManager::addPropertiesToList(
255     JSPropertyNameAccumulatorRef propertyNames) const
256 {
257     PropertyList properties = getProperties();
258     CommonsJavaScript::Converter converter(m_context);
259     FOREACH(it, properties) {
260         JSStringRef name = converter.toJSStringRef(*it);
261         JSPropertyNameAccumulatorAddName(propertyNames, name);
262         JSStringRelease(name);
263     }
264 }
265 }
266 }