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