Update wrt-plugins-common_0.3.53
[framework/web/wrt-plugins-common.git] / src / standards / W3C / Widget / JSPreferences.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        JSPreferences.cpp
19  * @author      Grzegorz Krawczyk (g.krawczyk@samsung.com)
20  * @version     0.1
21  */
22
23 #include "JSPreferences.h"
24
25 #include <string>
26 #include <dpl/assert.h>
27 #include <dpl/log/log.h>
28 #include <dpl/optional.h>
29 #include <CommonsJavaScript/Converter.h>
30 #include <CommonsJavaScript/JSDOMExceptionFactory.h>
31 #include <StorageEvent/StorageEventMgr.h>
32 #include <StorageEvent/IStorageEvent.h>
33 #include <js-overlay/js_iframe_support.h>
34 #include <js-overlay/js_overlay_addEventListener.h>
35
36 using namespace std;
37 using namespace WrtDeviceApis;
38 using namespace WrtDeviceApis::Commons;
39 using namespace WrtDeviceApis::CommonsJavaScript;
40 using namespace WrtDeviceApis::LocalStorage::Api;
41 using namespace WrtDeviceApis::StorageEvent::Api;
42
43 #define PREFERENCES_PLUGIN_NAME       "preferences"
44 #define LOCAL_STORAGE_PROPERTY_LENGTH "length"
45
46 #define CATCH_EXCEPTION_NO_MODIFABLE \
47     Catch(Commons::LocalStorageValueNoModifableException) {\
48         LogError("The item is read only");\
49         return JSDOMExceptionFactory::\
50             NoModificationAllowedException.make(context, exception);\
51     }
52
53 #define CATCH_EXCEPTION_CONVERSION \
54     Catch(Commons::ConversionException) {\
55         LogError("Error on conversion");\
56         return JSDOMExceptionFactory::\
57             UnknownException.make(context, exception);\
58     }
59
60 #define CATCH_EXCEPTION_NULL_PTR \
61     Catch(Commons::NullPointerException) {\
62         LogError("Error on pointer, null value");\
63         return JSDOMExceptionFactory::\
64             UnknownException.make(context, exception);\
65     }
66
67 #define CATCH_EXCEPTION_PLATFORM_ERROR \
68     Catch(Commons::PlatformException){\
69         LogError("PlatformException occured");\
70         return JSDOMExceptionFactory::\
71             UnknownException.make(context, exception);\
72     }
73
74 #define CATCH_EXCEPTION_SECURITY \
75     Catch(Commons::SecurityException){\
76         LogError("Security exception occured");\
77         return JSDOMExceptionFactory::\
78             SecurityException.make(context, exception);\
79     }
80
81 #define CATCH_EXCEPTION_OUT_OF_RANGE \
82     Catch(Commons::OutOfRangeException) {\
83         LogError("OutOfRangeException");\
84         return JSDOMExceptionFactory::\
85             QuotaExceededException.make(context, exception);\
86     }
87
88 #define CATCH_EXCEPTION_INVALID_ARG \
89     Catch(Commons::InvalidArgumentException) {\
90         LogError("Pair for given key doesnt exist");\
91         return JSValueMakeNull(context);\
92     }
93
94 namespace WrtPlugins {
95 namespace W3C {
96
97
98 ILocalStoragePtr getIStorage(JSObjectRef arg)
99 {
100     LogWarning("get localstorage object");
101
102     LocalStoragePrivateData* priv =
103         static_cast<LocalStoragePrivateData*>(JSObjectGetPrivate(arg));
104
105     if (!priv) {
106         LogError("Private object not initialized");
107         ThrowMsg(Commons::NullPointerException,
108                  "Private object not initialized");
109     }
110
111     return priv->istorage;
112 }
113
114 JSObjectRef getWidgetObject(JSObjectRef arg)
115 {
116     LogWarning("get widget object");
117
118     LocalStoragePrivateData* priv =
119         static_cast<LocalStoragePrivateData*>(JSObjectGetPrivate(arg));
120
121     if (!priv) {
122         LogError("Private object not initialized");
123         ThrowMsg(Commons::NullPointerException,
124                  "Private object not initialized");
125     }
126
127     return priv->widgetObject;
128
129 }
130
131 enum class ModificationType{
132     RemoveItem,
133     SetItem
134 };
135
136 //this function may throw exceptions
137 IStorageEventPtr modifyItemAndCreateEvent(ModificationType type,
138                                           JSObjectRef thisObject,
139                                           const string& key,
140                                           const string& value = std::string())
141 {
142     DPL::Optional<std::string> oldValue =
143         getIStorage(thisObject)->getValue(key);
144
145     if (ModificationType::SetItem == type)
146     {
147         getIStorage(thisObject)->setItem(key, value, false);
148     }
149     else if (ModificationType::RemoveItem == type)
150     {
151         getIStorage(thisObject)->removeItem(key);
152     }
153     else
154     {
155         Assert(0 && "Wrong Modification type");
156     }
157
158     DPL::Optional<std::string> newValue =
159         getIStorage(thisObject)->getValue(key);
160
161     //create event object
162     IStorageEventPtr storageEvent = getStorageEvent();
163
164     //key
165     storageEvent->setKey(key);
166     //oldvalue
167     if (!!oldValue) { storageEvent->setOldValue(*oldValue); }
168     //newValue
169     if(!!newValue){ storageEvent->setNewValue(*newValue); }
170
171     return storageEvent;
172 }
173
174
175 JSClassDefinition JSPreferences::m_classInfo =
176 {
177     0,
178     kJSClassAttributeNone,
179     PREFERENCES_PLUGIN_NAME,
180     0,
181     m_property,
182     m_function,
183     initialize,
184     finalize,
185     hasProperty,
186     getProperty,
187     setProperty,
188     NULL,//DeleteProperty,
189     NULL,//GetPropertyNames,
190     NULL,//CallAsFunction,
191     NULL,//CallAsConstructor,
192     NULL,//HasInstance,
193     NULL,//ConvertToType,
194 };
195
196 JSStaticFunction JSPreferences::m_function[] = {
197     { "setItem", JSPreferences::setItem, kJSPropertyAttributeNone },
198     { "removeItem", JSPreferences::removeItem, kJSPropertyAttributeNone },
199     { "getItem", JSPreferences::getItem, kJSPropertyAttributeNone },
200     { "clear", JSPreferences::clear, kJSPropertyAttributeNone },
201     { "key", JSPreferences::key, kJSPropertyAttributeNone },
202     { 0, 0, 0 }
203 };
204
205 JSStaticValue JSPreferences::m_property[] =
206 {
207     {LOCAL_STORAGE_PROPERTY_LENGTH,
208         JSPreferences::getLength,
209         NULL,
210         kJSPropertyAttributeReadOnly},
211     { 0, 0, 0, 0 }
212 };
213
214 const JSClassRef JSPreferences::getClassRef()
215 {
216     if (!m_jsClassRef) {
217         m_jsClassRef = JSClassCreate(&m_classInfo);
218     }
219     return m_jsClassRef;
220 }
221
222 const JSClassDefinition* JSPreferences::getClassInfo()
223 {
224     return &m_classInfo;
225 }
226
227 JSClassRef JSPreferences::m_jsClassRef =
228     JSClassCreate(JSPreferences::getClassInfo());
229
230 void JSPreferences::initialize(JSContextRef context,
231         JSObjectRef object)
232 {
233     LogDebug("entered. Context: " << context);
234
235     LocalStoragePrivateData* priv =
236       static_cast<LocalStoragePrivateData*>(JSObjectGetPrivate(object));
237
238     Assert(priv && "private object of preferences is NULL");
239 }
240
241 void JSPreferences::finalize(JSObjectRef object)
242 {
243     LogDebug("entered");
244     LocalStoragePrivateData* priv =
245       static_cast<LocalStoragePrivateData*>(JSObjectGetPrivate(object));
246
247     delete priv;
248     LogDebug("private object is realised");
249 }
250
251 JSValueRef JSPreferences::removeItem(JSContextRef context,
252                                      JSObjectRef object,
253                                      JSObjectRef thisObject,
254                                      size_t argumentCount,
255                                      const JSValueRef arguments[],
256                                      JSValueRef* exception)
257 {
258     LogDebug("entered");
259
260     Try {
261         Converter converter(context);
262
263         std::string key = converter.toString(arguments[0]);
264
265         auto event = modifyItemAndCreateEvent(ModificationType::RemoveItem,
266                                               thisObject,
267                                               key);
268
269         auto iframe = IFrameSupport::
270             getIFrameObjectForWidget(getWidgetObject(thisObject));
271
272         Assert(iframe && "Iframe is NULL");
273
274         AddEventListenerSupport::
275             CallStorageListenersFromDifferentIFrames(iframe, event);
276
277         LogDebug("end");
278         return JSValueMakeNull(context);
279     }
280     CATCH_EXCEPTION_NO_MODIFABLE
281     CATCH_EXCEPTION_CONVERSION
282     CATCH_EXCEPTION_NULL_PTR
283     CATCH_EXCEPTION_PLATFORM_ERROR
284     CATCH_EXCEPTION_SECURITY
285 }
286
287 JSValueRef JSPreferences::setItem(JSContextRef context,
288                                   JSObjectRef object,
289                                   JSObjectRef thisObject,
290                                   size_t argumentCount,
291                                   const JSValueRef arguments[],
292                                   JSValueRef* exception)
293 {
294     LogDebug("entered");
295     LogDebug("This: " << thisObject);
296     LogDebug("Object: " << object);
297
298     Try {
299         Converter converter(context);
300
301         std::string key = converter.toString(arguments[0]);
302         std::string value = converter.tryString(arguments[1]);
303
304         auto event = modifyItemAndCreateEvent(ModificationType::SetItem,
305                                               thisObject,
306                                               key,
307                                               value);
308
309         auto iframe = IFrameSupport::
310             getIFrameObjectForWidget(getWidgetObject(thisObject));
311         Assert(iframe && "Iframe is NULL");
312
313         AddEventListenerSupport::
314             CallStorageListenersFromDifferentIFrames(iframe, event);
315
316         LogDebug("end");
317
318         return JSValueMakeUndefined(context);
319     }
320     CATCH_EXCEPTION_NO_MODIFABLE
321     CATCH_EXCEPTION_CONVERSION
322     CATCH_EXCEPTION_NULL_PTR
323     CATCH_EXCEPTION_PLATFORM_ERROR
324     CATCH_EXCEPTION_SECURITY
325     CATCH_EXCEPTION_OUT_OF_RANGE
326 }
327
328
329 JSValueRef JSPreferences::clear(JSContextRef context,
330                                 JSObjectRef object,
331                                 JSObjectRef thisObject,
332                                 size_t argumentCount,
333                                 const JSValueRef arguments[],
334                                 JSValueRef* exception)
335 {
336     LogDebug("entered");
337
338     Try {
339         getIStorage(thisObject)->clear(false);
340
341
342         auto iframe = IFrameSupport::
343             getIFrameObjectForWidget(getWidgetObject(thisObject));
344
345         Assert(iframe && "Iframe is NULL");
346
347         //create event object
348         IStorageEventPtr storageEvent = getStorageEvent();
349
350         AddEventListenerSupport::
351             CallStorageListenersFromDifferentIFrames(iframe, storageEvent);
352
353         LogDebug("end");
354
355         return JSValueMakeNull(context);
356     }
357     CATCH_EXCEPTION_NULL_PTR
358     CATCH_EXCEPTION_PLATFORM_ERROR
359     CATCH_EXCEPTION_SECURITY
360 }
361
362 JSValueRef JSPreferences::getItem(JSContextRef context,
363                                   JSObjectRef object,
364                                   JSObjectRef thisObject,
365                                   size_t argumentCount,
366                                   const JSValueRef arguments[],
367                                   JSValueRef* exception)
368 {
369     LogDebug("entered");
370
371     Try {
372         Converter converter(context);
373
374         std::string key = converter.tryString(arguments[0]);
375
376         LogDebug("Getting item for key " << key);
377
378         DPL::Optional<std::string> value =
379             getIStorage(thisObject)->getValue(key);
380
381         if (!value)
382             return JSValueMakeNull(context);
383         else
384             return converter.toJSValueRef(*value);
385     }
386     CATCH_EXCEPTION_INVALID_ARG
387     CATCH_EXCEPTION_CONVERSION
388     CATCH_EXCEPTION_NULL_PTR
389     CATCH_EXCEPTION_PLATFORM_ERROR
390     CATCH_EXCEPTION_SECURITY
391 }
392
393 JSValueRef JSPreferences::key(JSContextRef context,
394                               JSObjectRef object,
395                               JSObjectRef thisObject,
396                               size_t argumentCount,
397                               const JSValueRef arguments[],
398                               JSValueRef* exception)
399 {
400     LogDebug("entered");
401
402     Try{
403         if (argumentCount<1) {
404             LogError("No argument found");
405             Throw(Commons::InvalidArgumentException);
406         }
407
408         Converter converter(context);
409
410         size_t n = converter.toSizeT(arguments[0]);
411
412         std::string value = getIStorage(thisObject)->getKeyByIndex(n);
413
414         LogDebug("end");
415
416         return converter.toJSValueRef(value);
417     }
418     CATCH_EXCEPTION_CONVERSION
419     CATCH_EXCEPTION_NULL_PTR
420     CATCH_EXCEPTION_PLATFORM_ERROR
421     CATCH_EXCEPTION_SECURITY
422     CATCH_EXCEPTION_INVALID_ARG
423 }
424
425 JSValueRef JSPreferences::getLength(JSContextRef context,
426                                     JSObjectRef object,
427                                     JSStringRef propertyName,
428                                     JSValueRef* exception)
429 {
430     LogDebug("enter");
431
432     Try
433     {
434         Converter converter(context);
435
436         size_t value = getIStorage(object)->getStorageSize();
437         return converter.toJSValueRef(value);
438     }
439     CATCH_EXCEPTION_CONVERSION
440     CATCH_EXCEPTION_NULL_PTR
441     CATCH_EXCEPTION_PLATFORM_ERROR
442     CATCH_EXCEPTION_SECURITY
443     CATCH_EXCEPTION_INVALID_ARG
444 }
445
446 bool JSPreferences::hasProperty(JSContextRef context,
447                            JSObjectRef object,
448                            JSStringRef propertyName)
449 {
450     LogDebug("enter");
451
452     Try{
453         Converter converter(context);
454
455         std::string key = converter.toString(propertyName);
456
457         if(!getIStorage(object)->getValue(key)) {
458             return false;
459         } else {
460             return true;
461         }
462     }
463
464     Catch(Commons::InvalidArgumentException) {
465         LogDebug("Pair for given key doesnt exist");
466     }
467
468     Catch(Commons::ConversionException) {
469         LogError("Error on conversion");
470     }
471
472     Catch(Commons::NullPointerException) {
473         LogError("Error on pointer, null value");
474     }
475
476     Catch(Commons::PlatformException){
477         LogError("PlatformException occured");
478     }
479     return false;
480 }
481
482 JSValueRef JSPreferences::getProperty(JSContextRef context,
483                                       JSObjectRef object,
484                                       JSStringRef propertyName,
485                                       JSValueRef* exception)
486 {
487     LogDebug("enter");
488
489     Try{
490         Converter converter(context);
491
492         std::string key = converter.toString(propertyName);
493
494         DPL::Optional<std::string> value =
495             getIStorage(object)->getValue(key);
496
497         LogDebug("end");
498
499         if (!value)
500             return JSValueMakeNull(context);
501         else
502             return converter.toJSValueRef(*value);
503     }
504
505     CATCH_EXCEPTION_CONVERSION
506     CATCH_EXCEPTION_NULL_PTR
507     CATCH_EXCEPTION_PLATFORM_ERROR
508     CATCH_EXCEPTION_INVALID_ARG
509 }
510
511 bool JSPreferences::setProperty(JSContextRef context,
512                                 JSObjectRef object,
513                                 JSStringRef propertyName,
514                                 JSValueRef jvalue,
515                                 JSValueRef* exception)
516 {
517     LogDebug("enter");
518
519     Try{
520         Converter converter(context);
521
522         std::string key = converter.toString(propertyName);
523         std::string value = converter.toString(jvalue);
524
525         auto event = modifyItemAndCreateEvent(ModificationType::SetItem,
526                                               object,
527                                               key,
528                                               value);
529
530         auto iframe = IFrameSupport::
531             getIFrameObjectForWidget(getWidgetObject(object));
532         Assert(iframe && "Iframe is NULL");
533
534         AddEventListenerSupport::
535             CallStorageListenersFromDifferentIFrames(iframe, event);
536
537         LogDebug("end");
538
539         return true;
540     }
541     CATCH_EXCEPTION_NO_MODIFABLE
542     CATCH_EXCEPTION_OUT_OF_RANGE
543     CATCH_EXCEPTION_INVALID_ARG
544     CATCH_EXCEPTION_CONVERSION
545     CATCH_EXCEPTION_NULL_PTR
546     CATCH_EXCEPTION_PLATFORM_ERROR
547     CATCH_EXCEPTION_SECURITY
548
549     return false;
550 }
551
552 #undef CATCH_EXCEPTION_NO_MODIFABLE
553 #undef CATCH_EXCEPTION_CONVERSION
554 #undef CATCH_EXCEPTION_NULL_PTR
555 #undef CATCH_EXCEPTION_PLATFORM_ERROR
556 #undef CATCH_EXCEPTION_SECURITY
557 #undef CATCH_EXCEPTION_OUT_OF_RANGE
558 #undef CATCH_EXCEPTION_INVALID_ARG
559
560 }
561 }