Initialize Tizen 2.3
[framework/web/wrt-plugins-common.git] / src_wearable / 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
36 // temporary
37 extern "C" JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx);
38
39 #define CATCH_EXCEPTION_NO_MODIFABLE \
40     Catch(Commons::LocalStorageValueNoModifableException) { \
41         _E("The item is read only"); \
42         return JSDOMExceptionFactory:: \
43                    NoModificationAllowedException.make(context, exception); \
44     }
45
46 #define CATCH_EXCEPTION_CONVERSION \
47     Catch(Commons::ConversionException) { \
48         _E("Error on conversion"); \
49         return JSDOMExceptionFactory:: \
50                    UnknownException.make(context, exception); \
51     }
52
53 #define CATCH_EXCEPTION_NULL_PTR \
54     Catch(Commons::NullPointerException) { \
55         _E("Error on pointer, null value"); \
56         return JSDOMExceptionFactory:: \
57                    UnknownException.make(context, exception); \
58     }
59
60 #define CATCH_EXCEPTION_PLATFORM_ERROR \
61     Catch(Commons::PlatformException){ \
62         _E("PlatformException occured"); \
63         return JSDOMExceptionFactory:: \
64                    UnknownException.make(context, exception); \
65     }
66
67 #define CATCH_EXCEPTION_SECURITY \
68     Catch(Commons::SecurityException){ \
69         _E("Security exception occured"); \
70         return JSDOMExceptionFactory:: \
71                    SecurityException.make(context, exception); \
72     }
73
74 #define CATCH_EXCEPTION_OUT_OF_RANGE \
75     Catch(Commons::OutOfRangeException) { \
76         _E("OutOfRangeException"); \
77         return JSDOMExceptionFactory:: \
78                    QuotaExceededException.make(context, exception); \
79     }
80
81 #define CATCH_EXCEPTION_INVALID_ARG \
82     Catch(Commons::InvalidArgumentException) { \
83         _E("Pair for given key doesnt exist"); \
84         return JSValueMakeNull(context); \
85     }
86
87 #define WIDGET_PLUGIN_NAME "Widget"
88
89 #define WRT_WIDGET_PROPERTY_AUTHOR       "author"
90 #define WRT_WIDGET_PROPERTY_AUTHOR_EMAIL "authorEmail"
91 #define WRT_WIDGET_PROPERTY_AUTHOR_HREF  "authorHref"
92 #define WRT_WIDGET_PROPERTY_DESCRIPTION  "description"
93 #define WRT_WIDGET_PROPERTY_ID           "id"
94 #define WRT_WIDGET_PROPERTY_NAME         "name"
95 #define WRT_WIDGET_PROPERTY_SHORT_NAME   "shortName"
96 #define WRT_WIDGET_PROPERTY_VERSION      "version"
97 #define WRT_WIDGET_PROPERTY_HEIGHT       "height"
98 #define WRT_WIDGET_PROPERTY_WIDTH        "width"
99
100 namespace WrtPlugins {
101 namespace W3C {
102 using namespace WrtDeviceApis;
103 using namespace WrtDeviceApis::Commons;
104 using namespace WrtDeviceApis::CommonsJavaScript;
105 using namespace WrtDeviceApis::Widget;
106
107 struct WidgetPrivateObject
108 {
109     Widget::Api::IWidgetPtr iwidget;
110     JSObjectRef preferencesObject;
111     //TEMP
112     //int widgetId      // TODO: check is it necessary (g.rynkowski)
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(int 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                                     int 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     JSValueProtect(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     {
248         context = g_context;
249     }
250
251     JSWidgetPrivateObject* priv =
252         static_cast<JSWidgetPrivateObject*>(JSObjectGetPrivate(object));
253
254     if (!priv) {
255         LogDebug("creation private object");
256
257         Try {
258             using namespace WrtDeviceApis::Commons;
259
260             Widget::Api::IWidgetPtr widget =
261                 Api::WidgetFactory::createWidget();
262             int widgetId = WrtAccessSingleton::Instance().getWidgetId();
263             JSObjectRef preferences =
264                 createPreferencesObject(context,
265                                         object,
266                                         widgetId);
267             if (!preferences) {
268                 LogError("Failed to create preferences object");
269             }
270
271             WidgetPrivateObjectPtr widgetPriv(new WidgetPrivateObject);
272             widgetPriv->iwidget = widget;
273             widgetPriv->preferencesObject = preferences;
274
275             priv = new JSWidgetPrivateObject(context, widgetPriv);
276             JSObjectSetPrivate(object, priv);
277         }
278         Catch(Commons::InvalidArgumentException){
279             LogError("You should register widget id in ON_WIDGET_START");
280             return;
281         }
282         Catch(DPL::Exception) {
283             LogError("Failed to create private object for JSWidget");
284             return;
285         }
286     }
287 }
288
289 void JSWidget::finalize(JSObjectRef object)
290 {
291     LogDebug("entered");
292     LogDebug("Object: " << object);
293     JSWidgetPrivateObject* priv =
294         static_cast<JSWidgetPrivateObject*>(JSObjectGetPrivate(object));
295
296     if (priv) {
297         JSValueUnprotect(priv->getContext(),
298                          priv->getObject()->preferencesObject);
299
300         delete priv;
301         LogDebug("private object is released");
302     } else {
303         LogDebug("private object wasn't created");
304     }
305 }
306
307 JSValueRef JSWidget::getAuthor(JSContextRef context,
308                                JSObjectRef object,
309                                JSStringRef /*propertyName*/,
310                                JSValueRef* exception)
311 {
312     LogDebug("entered");
313
314     Try {
315         Converter converter(context);
316         return converter.toJSValueRef(getIWidget(object)->getAuthor());
317     }
318     CATCH_EXCEPTION_CONVERSION
319     CATCH_EXCEPTION_NULL_PTR
320         CATCH_EXCEPTION_PLATFORM_ERROR
321 }
322
323 JSValueRef JSWidget::getAuthorEmail(JSContextRef context,
324                                     JSObjectRef object,
325                                     JSStringRef /*propertyName*/,
326                                     JSValueRef* exception)
327 {
328     Try {
329         Converter converter(context);
330         return converter.toJSValueRef(getIWidget(object)->getAuthorEmail());
331     }
332     CATCH_EXCEPTION_CONVERSION
333     CATCH_EXCEPTION_NULL_PTR
334         CATCH_EXCEPTION_PLATFORM_ERROR
335 }
336
337 JSValueRef JSWidget::getAuthorHref(JSContextRef context,
338                                    JSObjectRef object,
339                                    JSStringRef /*propertyName*/,
340                                    JSValueRef* exception)
341 {
342     Try {
343         Converter converter(context);
344         return converter.toJSValueRef(getIWidget(object)->getAuthorHref());
345     }
346     CATCH_EXCEPTION_CONVERSION
347     CATCH_EXCEPTION_NULL_PTR
348         CATCH_EXCEPTION_PLATFORM_ERROR
349 }
350
351 JSValueRef JSWidget::getDescription(JSContextRef context,
352                                     JSObjectRef object,
353                                     JSStringRef /*propertyName*/,
354                                     JSValueRef* exception)
355 {
356     Try {
357         Converter converter(context);
358         return converter.toJSValueRef(getIWidget(object)->getDescription());
359     }
360     CATCH_EXCEPTION_CONVERSION
361     CATCH_EXCEPTION_NULL_PTR
362         CATCH_EXCEPTION_PLATFORM_ERROR
363 }
364
365 JSValueRef JSWidget::getId(JSContextRef context,
366                            JSObjectRef object,
367                            JSStringRef /*propertyName*/,
368                            JSValueRef* exception)
369 {
370     Try {
371         Converter converter(context);
372         return converter.toJSValueRef(getIWidget(object)->getId());
373     }
374     CATCH_EXCEPTION_CONVERSION
375     CATCH_EXCEPTION_NULL_PTR
376         CATCH_EXCEPTION_PLATFORM_ERROR
377 }
378
379 JSValueRef JSWidget::getName(JSContextRef context,
380                              JSObjectRef object,
381                              JSStringRef /*propertyName*/,
382                              JSValueRef* exception)
383 {
384     Try {
385         Converter converter(context);
386         return converter.toJSValueRef(getIWidget(object)->getName());
387     }
388     CATCH_EXCEPTION_CONVERSION
389     CATCH_EXCEPTION_NULL_PTR
390         CATCH_EXCEPTION_PLATFORM_ERROR
391 }
392
393 JSValueRef JSWidget::getShortName(JSContextRef context,
394                                   JSObjectRef object,
395                                   JSStringRef /*propertyName*/,
396                                   JSValueRef* exception)
397 {
398     Try {
399         Converter converter(context);
400         return converter.toJSValueRef(getIWidget(object)->getShortName());
401     }
402     CATCH_EXCEPTION_CONVERSION
403     CATCH_EXCEPTION_NULL_PTR
404         CATCH_EXCEPTION_PLATFORM_ERROR
405 }
406
407 JSValueRef JSWidget::getVersion(JSContextRef context,
408                                 JSObjectRef object,
409                                 JSStringRef /*propertyName*/,
410                                 JSValueRef* exception)
411 {
412     Try {
413         Converter converter(context);
414         return converter.toJSValueRef(getIWidget(object)->getVersion());
415     }
416     CATCH_EXCEPTION_CONVERSION
417     CATCH_EXCEPTION_NULL_PTR
418         CATCH_EXCEPTION_PLATFORM_ERROR
419 }
420
421 JSValueRef JSWidget::getHeight(JSContextRef context,
422                                JSObjectRef object,
423                                JSStringRef /*propertyName*/,
424                                JSValueRef* exception)
425 {
426     Try {
427         Converter converter(context);
428         unsigned int height = getIWidget(object)->getHeight();
429         if (0 == height) {
430             height = 1;
431         }
432         return converter.toJSValueRef(height);
433     }
434     CATCH_EXCEPTION_CONVERSION
435     CATCH_EXCEPTION_NULL_PTR
436         CATCH_EXCEPTION_PLATFORM_ERROR
437 }
438
439 JSValueRef JSWidget::getWidth(JSContextRef context,
440                               JSObjectRef object,
441                               JSStringRef /*propertyName*/,
442                               JSValueRef* exception)
443 {
444     Try {
445         Converter converter(context);
446         unsigned int width = getIWidget(object)->getWidth();
447         if (0 == width) {
448             width = 1;
449         }
450         return converter.toJSValueRef(width);
451     }
452     CATCH_EXCEPTION_CONVERSION
453     CATCH_EXCEPTION_NULL_PTR
454         CATCH_EXCEPTION_PLATFORM_ERROR
455 }
456
457 bool JSWidget::hasProperty(JSContextRef context,
458                            JSObjectRef /*object*/,
459                            JSStringRef propertyName)
460 {
461     LogDebug("enter");
462
463     Try {
464         Converter converter(context);
465
466         std::string key = converter.toString(propertyName);
467         if (key == "preferences") {
468             return true;
469         }
470     }
471     Catch(Commons::InvalidArgumentException) {
472         LogDebug("Pair for given key doesnt exist");
473     }
474
475     Catch(Commons::ConversionException) {
476         LogError("Error on conversion");
477     }
478
479     Catch(Commons::NullPointerException) {
480         LogError("Error on pointer, null value");
481     }
482
483     Catch(Commons::PlatformException){
484         LogError("PlatformException occured");
485     }
486     return false;
487 }
488
489 JSValueRef JSWidget::getProperty(JSContextRef context,
490                                  JSObjectRef object,
491                                  JSStringRef propertyName,
492                                  JSValueRef* exception)
493 {
494     LogDebug("Object: " << object);
495
496     Try {
497         Converter converter(context);
498
499         std::string key = converter.toString(propertyName);
500
501         if (key == "preferences") {
502             Converter converter(context);
503             JSObjectRef pref = getPreferences(object);
504             if (!pref) {
505                 LogError("Preferences object is NULL");
506                 return JSValueMakeUndefined(context);
507             }
508             return pref;
509         }
510         LogError("Property NOT supported: " << propertyName);
511         return JSValueMakeUndefined(context);
512     }
513
514     CATCH_EXCEPTION_CONVERSION
515     CATCH_EXCEPTION_NULL_PTR
516         CATCH_EXCEPTION_INVALID_ARG
517 }
518
519 bool JSWidget::setProperty(JSContextRef context,
520                            JSObjectRef /*object*/,
521                            JSStringRef propertyName,
522                            JSValueRef /*jvalue*/,
523                            JSValueRef* exception)
524 {
525     LogDebug("enter");
526
527     Try {
528         Converter converter(context);
529
530         std::string key = converter.toString(propertyName);
531         if (key == "preferences") {
532             LogError("Object is read only");
533             return true;
534         }
535     }
536     CATCH_EXCEPTION_INVALID_ARG
537     CATCH_EXCEPTION_CONVERSION
538         CATCH_EXCEPTION_NULL_PTR
539
540     return false;
541 }
542
543 JSObjectRef JSWidget::callAsConstructor(JSContextRef context,
544                                         JSObjectRef /*constructor*/,
545                                         size_t /*argumentCount*/,
546                                         const JSValueRef /*arguments*/[],
547                                         JSValueRef* /*exception*/)
548 {
549     LogDebug("widget constructor");
550     return JSObjectMake(context, JSWidget::getClassRef(), NULL);
551 }
552
553 #undef CATCH_EXCEPTION_NO_MODIFABLE
554 #undef CATCH_EXCEPTION_CONVERSION
555 #undef CATCH_EXCEPTION_NULL_PTR
556 #undef CATCH_EXCEPTION_PLATFORM_ERROR
557 #undef CATCH_EXCEPTION_SECURITY
558 #undef CATCH_EXCEPTION_OUT_OF_RANGE
559 #undef CATCH_EXCEPTION_INVALID_ARG
560 }
561 }