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