3f3f8c3613e57c6a889ab9fbd1e3e9269d9233e2
[platform/framework/web/wrt-plugins-common.git] / src / standards / W3C / Widget / JSWidget.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  *
18  * @file        JSWidget.cpp
19  * @author      Grzegorz Krawczyk (g.krawczyk@samsung.com)
20  * @version     0.1
21  */
22
23 #include "JSWidget.h"
24 #include <memory>
25 #include <CommonsJavaScript/Converter.h>
26 #include <dpl/log/log.h>
27 #include <dpl/assert.h>
28 #include <Widget/WidgetFactory.h>
29 #include <CommonsJavaScript/JSDOMExceptionFactory.h>
30 #include "JSPreferences.h"
31 #include <Widget/IWidget.h>
32 #include <LocalStorage/LocalStorageMgr.h>
33 #include <Commons/WrtAccess/WrtAccess.h>
34 #include <js-overlay/js_iframe_support.h>
35
36
37 #define CATCH_EXCEPTION_NO_MODIFABLE \
38     Catch(Commons::LocalStorageValueNoModifableException) {\
39         LogError("The item is read only");\
40         return JSDOMExceptionFactory::\
41             NoModificationAllowedException.make(context, exception);\
42     }
43
44 #define CATCH_EXCEPTION_CONVERSION \
45     Catch(Commons::ConversionException) {\
46         LogError("Error on conversion");\
47         return JSDOMExceptionFactory::\
48             UnknownException.make(context, exception);\
49     }
50
51 #define CATCH_EXCEPTION_NULL_PTR \
52     Catch(Commons::NullPointerException) {\
53         LogError("Error on pointer, null value");\
54         return JSDOMExceptionFactory::\
55             UnknownException.make(context, exception);\
56     }
57
58 #define CATCH_EXCEPTION_PLATFORM_ERROR \
59     Catch(Commons::PlatformException){\
60         LogError("PlatformException occured");\
61         return JSDOMExceptionFactory::\
62             UnknownException.make(context, exception);\
63     }
64
65 #define CATCH_EXCEPTION_SECURITY \
66     Catch(Commons::SecurityException){\
67         LogError("Security exception occured");\
68         return JSDOMExceptionFactory::\
69             SecurityException.make(context, exception);\
70     }
71
72 #define CATCH_EXCEPTION_OUT_OF_RANGE \
73     Catch(Commons::OutOfRangeException) {\
74         LogError("OutOfRangeException");\
75         return JSDOMExceptionFactory::\
76             QuotaExceededException.make(context, exception);\
77     }
78
79 #define CATCH_EXCEPTION_INVALID_ARG \
80     Catch(Commons::InvalidArgumentException) {\
81         LogError("Pair for given key doesnt exist");\
82         return JSValueMakeNull(context);\
83     }
84
85 #define WIDGET_PLUGIN_NAME "Widget"
86
87 #define WRT_WIDGET_PROPERTY_AUTHOR       "author"
88 #define WRT_WIDGET_PROPERTY_AUTHOR_EMAIL "authorEmail"
89 #define WRT_WIDGET_PROPERTY_AUTHOR_HREF  "authorHref"
90 #define WRT_WIDGET_PROPERTY_DESCRIPTION  "description"
91 #define WRT_WIDGET_PROPERTY_ID           "id"
92 #define WRT_WIDGET_PROPERTY_NAME         "name"
93 #define WRT_WIDGET_PROPERTY_SHORT_NAME   "shortName"
94 #define WRT_WIDGET_PROPERTY_VERSION      "version"
95 #define WRT_WIDGET_PROPERTY_HEIGHT       "height"
96 #define WRT_WIDGET_PROPERTY_WIDTH        "width"
97
98 namespace WrtPlugins {
99 namespace W3C {
100
101 using namespace WrtDeviceApis;
102 using namespace WrtDeviceApis::Commons;
103 using namespace WrtDeviceApis::CommonsJavaScript;
104 using namespace WrtDeviceApis::Widget;
105
106
107 struct WidgetPrivateObject
108 {
109     Widget::Api::IWidgetPtr iwidget;
110     JSObjectRef preferencesObject;
111     //TEMP
112     int widgetId;
113     JSObjectRef widgetObject;
114 };
115 typedef std::shared_ptr<WidgetPrivateObject> WidgetPrivateObjectPtr;
116
117 typedef WrtDeviceApis::CommonsJavaScript::PrivateObjectT
118     <WidgetPrivateObjectPtr>::Type JSWidgetPrivateObject;
119
120 WrtDeviceApis::Widget::Api::IWidgetPtr getIWidget(JSObjectRef arg)
121 {
122     JSWidgetPrivateObject* priv =
123         static_cast<JSWidgetPrivateObject*>(JSObjectGetPrivate(arg));
124
125     if (!priv) {
126         LogError("Private object not initialized");
127         ThrowMsg(Commons::NullPointerException,
128                  "Private object not initialized");
129     }
130
131     return priv->getObject()->iwidget;
132 }
133
134
135 LocalStorage::Api::ILocalStoragePtr getLocalStorage(int widgetId)
136 {
137     static int id = widgetId;
138     Assert(id == widgetId && "SPA is not longer supported");
139
140     static LocalStorage::Api::ILocalStoragePtr storage(
141         LocalStorage::Api::getLocalStorage(widgetId));
142
143     return storage;
144 }
145
146 JSObjectRef getPreferences(JSObjectRef arg)
147 {
148     JSWidgetPrivateObject* priv =
149         static_cast<JSWidgetPrivateObject*>(JSObjectGetPrivate(arg));
150
151     if (!priv) {
152         LogError("Private object not initialized");
153         return NULL;
154     }
155
156     return priv->getObject()->preferencesObject;
157 }
158
159 JSObjectRef createPreferencesObject(JSContextRef context,
160                                     JSObjectRef widgetObject,
161                                     int widgetId)
162 {
163     Assert(widgetObject && "Widget Object can'n be null");
164     //delete is invoked in JSPreferences::finalize
165     LocalStoragePrivateData* priv = new LocalStoragePrivateData;
166     Assert(priv && "Private data is null");
167     priv->istorage = getLocalStorage(widgetId);
168     priv->widgetObject = widgetObject;
169
170     JSObjectRef preferences = JSObjectMake(context,
171                                            JSPreferences::getClassRef(),
172                                            priv);
173
174     if(!preferences){
175         LogError("Preferences object is null");
176         delete priv;
177     }
178     //Unprotect is called in JSWidget::finalize
179     JSValueProtect(context, preferences);
180
181     return preferences;
182 };
183
184
185 JSClassDefinition JSWidget::m_classInfo = {
186     0,
187     kJSClassAttributeNone,
188     WIDGET_PLUGIN_NAME,
189     0,
190     m_property,
191     NULL,
192     initialize,
193     finalize,
194     hasProperty,
195     getProperty,
196     setProperty,
197     NULL, //DeleteProperty,
198     NULL, //GetPropertyNames,
199     NULL, //CallAsFunction,
200     callAsConstructor,
201     NULL, //HasInstance,
202     NULL, //ConvertToType,
203 };
204
205 JSStaticValue JSWidget::m_property[] = {
206     { WRT_WIDGET_PROPERTY_AUTHOR, JSWidget::getAuthor,
207       0, kJSPropertyAttributeReadOnly },
208     { WRT_WIDGET_PROPERTY_AUTHOR_EMAIL, JSWidget::getAuthorEmail,
209       0, kJSPropertyAttributeReadOnly },
210     { WRT_WIDGET_PROPERTY_AUTHOR_HREF, JSWidget::getAuthorHref,
211       0, kJSPropertyAttributeReadOnly },
212     { WRT_WIDGET_PROPERTY_DESCRIPTION, JSWidget::getDescription,
213       0, kJSPropertyAttributeReadOnly },
214     { WRT_WIDGET_PROPERTY_ID, JSWidget::getId,
215       0, kJSPropertyAttributeReadOnly },
216     { WRT_WIDGET_PROPERTY_NAME, JSWidget::getName,
217       0, kJSPropertyAttributeReadOnly },
218     { WRT_WIDGET_PROPERTY_SHORT_NAME, JSWidget::getShortName,
219       0, kJSPropertyAttributeReadOnly },
220     { WRT_WIDGET_PROPERTY_VERSION, JSWidget::getVersion,
221       0, kJSPropertyAttributeReadOnly },
222     { WRT_WIDGET_PROPERTY_HEIGHT, JSWidget::getHeight,
223       0, kJSPropertyAttributeReadOnly },
224     { WRT_WIDGET_PROPERTY_WIDTH, JSWidget::getWidth,
225       0, kJSPropertyAttributeReadOnly },
226     { 0, 0, 0, 0 }
227 };
228
229 const JSClassRef JSWidget::getClassRef()
230 {
231     if (!m_jsClassRef) {
232         m_jsClassRef = JSClassCreate(&m_classInfo);
233     }
234     return m_jsClassRef;
235 }
236
237 const JSClassDefinition* JSWidget::getClassInfo()
238 {
239     return &m_classInfo;
240 }
241
242 JSClassRef JSWidget::m_jsClassRef = JSClassCreate(JSWidget::getClassInfo());
243
244 JSContextRef JSWidget::m_globalContext = NULL;
245
246 void JSWidget::initialize(JSContextRef context,
247         JSObjectRef object)
248 {
249     LogDebug("entered. Context : " << context);
250     LogDebug("Object: " << object);
251
252     JSWidgetPrivateObject* priv =
253         static_cast<JSWidgetPrivateObject*>(JSObjectGetPrivate(object));
254
255     if (!priv) {
256         LogDebug("creation private object");
257
258         Try {
259             using namespace WrtDeviceApis::Commons;
260
261             Widget::Api::IWidgetPtr widget =
262                 Api::WidgetFactory::createWidget();
263             int widgetId = WrtAccessSingleton::Instance().getWidgetId();
264             JSObjectRef preferences =
265                 createPreferencesObject(context,
266                                         object,
267                                         widgetId);
268             if(!preferences){
269                 LogError("Failed to create preferences object");
270             }
271
272             WidgetPrivateObjectPtr widgetPriv(new WidgetPrivateObject);
273             widgetPriv->iwidget = widget;
274             widgetPriv->preferencesObject = preferences;
275
276             priv = new JSWidgetPrivateObject(context, widgetPriv);
277             JSObjectSetPrivate(object, priv);
278             LogDebug("private object created");
279
280         }
281         Catch(Commons::InvalidArgumentException){
282             LogError("You should register widget id in ON_WIDGET_START");
283             return;
284         }
285
286     }
287 }
288
289 void JSWidget::finalize(JSObjectRef object)
290 {
291     LogDebug("entered");
292     JSWidgetPrivateObject* priv =
293         static_cast<JSWidgetPrivateObject*>(JSObjectGetPrivate(object));
294
295     JSValueUnprotect(priv->getContext(),
296                      priv->getObject()->preferencesObject);
297
298     delete priv;
299     LogDebug("private object is released");
300 }
301
302 void JSWidget::acquireGlobalContext(java_script_context_t global_context,
303         js_object_instance_t iframe,
304         js_object_instance_t object)
305 {
306     IFrameSupport::RegisterWidget(global_context, iframe, object);
307     if (!m_globalContext) {
308         m_globalContext = static_cast<JSContextRef>(global_context);
309         LogInfo("Global context acquired.");
310     } else {
311         LogInfo("Global context already set.");
312     }
313 }
314
315 JSValueRef JSWidget::getAuthor(JSContextRef context,
316         JSObjectRef object,
317         JSStringRef propertyName,
318         JSValueRef* exception)
319 {
320     LogDebug("entered");
321
322     Try {
323         Converter converter(context);
324         return converter.toJSValueRef(getIWidget(object)->getAuthor());
325     }
326     CATCH_EXCEPTION_CONVERSION
327     CATCH_EXCEPTION_NULL_PTR
328     CATCH_EXCEPTION_PLATFORM_ERROR
329 }
330
331 JSValueRef JSWidget::getAuthorEmail(JSContextRef context,
332         JSObjectRef object,
333         JSStringRef propertyName,
334         JSValueRef* exception)
335 {
336     Try {
337         Converter converter(context);
338         return converter.toJSValueRef(getIWidget(object)->getAuthorEmail());
339     }
340     CATCH_EXCEPTION_CONVERSION
341     CATCH_EXCEPTION_NULL_PTR
342     CATCH_EXCEPTION_PLATFORM_ERROR
343 }
344
345 JSValueRef JSWidget::getAuthorHref(JSContextRef context,
346         JSObjectRef object,
347         JSStringRef propertyName,
348         JSValueRef* exception)
349 {
350     Try {
351         Converter converter(context);
352         return converter.toJSValueRef(getIWidget(object)->getAuthorHref());
353     }
354     CATCH_EXCEPTION_CONVERSION
355     CATCH_EXCEPTION_NULL_PTR
356     CATCH_EXCEPTION_PLATFORM_ERROR
357 }
358
359 JSValueRef JSWidget::getDescription(JSContextRef context,
360         JSObjectRef object,
361         JSStringRef propertyName,
362         JSValueRef* exception)
363 {
364     Try {
365         Converter converter(context);
366         return converter.toJSValueRef(getIWidget(object)->getDescription());
367     }
368     CATCH_EXCEPTION_CONVERSION
369     CATCH_EXCEPTION_NULL_PTR
370     CATCH_EXCEPTION_PLATFORM_ERROR
371 }
372
373 JSValueRef JSWidget::getId(JSContextRef context,
374         JSObjectRef object,
375         JSStringRef propertyName,
376         JSValueRef* exception)
377 {
378     Try {
379         Converter converter(context);
380         return converter.toJSValueRef(getIWidget(object)->getId());
381     }
382     CATCH_EXCEPTION_CONVERSION
383     CATCH_EXCEPTION_NULL_PTR
384     CATCH_EXCEPTION_PLATFORM_ERROR
385 }
386
387 JSValueRef JSWidget::getName(JSContextRef context,
388         JSObjectRef object,
389         JSStringRef propertyName,
390         JSValueRef* exception)
391 {
392     Try {
393         Converter converter(context);
394         return converter.toJSValueRef(getIWidget(object)->getName());
395     }
396     CATCH_EXCEPTION_CONVERSION
397     CATCH_EXCEPTION_NULL_PTR
398     CATCH_EXCEPTION_PLATFORM_ERROR
399 }
400
401 JSValueRef JSWidget::getShortName(JSContextRef context,
402         JSObjectRef object,
403         JSStringRef propertyName,
404         JSValueRef* exception)
405 {
406     Try {
407         Converter converter(context);
408         return converter.toJSValueRef(getIWidget(object)->getShortName());
409     }
410     CATCH_EXCEPTION_CONVERSION
411     CATCH_EXCEPTION_NULL_PTR
412     CATCH_EXCEPTION_PLATFORM_ERROR
413 }
414
415 JSValueRef JSWidget::getVersion(JSContextRef context,
416         JSObjectRef object,
417         JSStringRef propertyName,
418         JSValueRef* exception)
419 {
420     Try {
421         Converter converter(context);
422         return converter.toJSValueRef(getIWidget(object)->getVersion());
423     }
424     CATCH_EXCEPTION_CONVERSION
425     CATCH_EXCEPTION_NULL_PTR
426     CATCH_EXCEPTION_PLATFORM_ERROR
427 }
428
429 JSValueRef JSWidget::getHeight(JSContextRef context,
430         JSObjectRef object,
431         JSStringRef propertyName,
432         JSValueRef* exception)
433 {
434     Try {
435         Converter converter(context);
436         unsigned int height = getIWidget(object)->getHeight();
437         if (0 == height) {
438             height = 1;
439         }
440         return converter.toJSValueRef(height);
441     }
442     CATCH_EXCEPTION_CONVERSION
443     CATCH_EXCEPTION_NULL_PTR
444     CATCH_EXCEPTION_PLATFORM_ERROR
445 }
446
447 JSValueRef JSWidget::getWidth(JSContextRef context,
448         JSObjectRef object,
449         JSStringRef propertyName,
450         JSValueRef* exception)
451 {
452     Try {
453         Converter converter(context);
454         unsigned int width = getIWidget(object)->getWidth();
455         if (0 == width) {
456             width = 1;
457         }
458         return converter.toJSValueRef(width);
459     }
460     CATCH_EXCEPTION_CONVERSION
461     CATCH_EXCEPTION_NULL_PTR
462     CATCH_EXCEPTION_PLATFORM_ERROR
463 }
464
465 bool JSWidget::hasProperty(JSContextRef context,
466                            JSObjectRef object,
467                            JSStringRef propertyName)
468 {
469     LogDebug("enter");
470
471     Try{
472         Converter converter(context);
473
474         std::string key = converter.toString(propertyName);
475         if (key == "preferences") {
476             return true;
477         }
478     }
479     Catch(Commons::InvalidArgumentException) {
480         LogDebug("Pair for given key doesnt exist");
481     }
482
483     Catch(Commons::ConversionException) {
484         LogError("Error on conversion");
485     }
486
487     Catch(Commons::NullPointerException) {
488         LogError("Error on pointer, null value");
489     }
490
491     Catch(Commons::PlatformException){
492         LogError("PlatformException occured");
493     }
494     return false;
495 }
496
497 JSValueRef JSWidget::getProperty(JSContextRef context,
498                                  JSObjectRef object,
499                                  JSStringRef propertyName,
500                                  JSValueRef* exception)
501 {
502     LogDebug("Object: " << object);
503
504     Try {
505         Converter converter(context);
506
507         std::string key = converter.toString(propertyName);
508
509         if (key=="preferences") {
510             Converter converter(context);
511             JSObjectRef pref = getPreferences(object);
512             if (!pref)
513             {
514                 LogError("Preferences object is NULL");
515                 return JSValueMakeUndefined(context);
516             }
517             return pref;
518         }
519         LogError("Property NOT supported: " << propertyName);
520         return JSValueMakeUndefined(context);
521     }
522
523     CATCH_EXCEPTION_CONVERSION
524     CATCH_EXCEPTION_NULL_PTR
525     CATCH_EXCEPTION_INVALID_ARG
526 }
527
528 bool JSWidget::setProperty(JSContextRef context,
529                            JSObjectRef object,
530                            JSStringRef propertyName,
531                            JSValueRef jvalue,
532                            JSValueRef* exception)
533 {
534     LogDebug("enter");
535
536     Try{
537         Converter converter(context);
538
539         std::string key = converter.toString(propertyName);
540         if (key == "preferences"){
541             LogError("Object is read only");
542             return true;
543         }
544     }
545     CATCH_EXCEPTION_INVALID_ARG
546     CATCH_EXCEPTION_CONVERSION
547     CATCH_EXCEPTION_NULL_PTR
548
549     return false;
550 }
551
552 JSObjectRef JSWidget::callAsConstructor(JSContextRef context,
553                                         JSObjectRef constructor,
554                                         size_t argumentCount,
555                                         const JSValueRef arguments[],
556                                         JSValueRef* exception)
557 {
558     LogDebug("widget constructor");
559     if (!m_globalContext) {
560         LogError("Global context not set. Creating 'widget' object with "
561                 "local context!");
562         return JSObjectMake(context, JSWidget::getClassRef(), NULL);
563     }
564     return JSObjectMake(m_globalContext, JSWidget::getClassRef(), NULL);
565 }
566
567 #undef CATCH_EXCEPTION_NO_MODIFABLE
568 #undef CATCH_EXCEPTION_CONVERSION
569 #undef CATCH_EXCEPTION_NULL_PTR
570 #undef CATCH_EXCEPTION_PLATFORM_ERROR
571 #undef CATCH_EXCEPTION_SECURITY
572 #undef CATCH_EXCEPTION_OUT_OF_RANGE
573 #undef CATCH_EXCEPTION_INVALID_ARG
574
575 }
576 }