upload tizen1.0 source
[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 "IFrameSupport.h"
34 #include "AddEventListenerSupport.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");
234
235     if( !AddEventListenerSupport::isInitialized())
236     {
237         AddEventListenerSupport::initializeContext(context);
238     }
239
240     LocalStoragePrivateData* priv =
241       static_cast<LocalStoragePrivateData*>(JSObjectGetPrivate(object));
242
243     Assert(priv && "private object of preferences is NULL");
244 }
245
246 void JSPreferences::finalize(JSObjectRef object)
247 {
248     LogDebug("entered");
249     LocalStoragePrivateData* priv =
250       static_cast<LocalStoragePrivateData*>(JSObjectGetPrivate(object));
251
252     delete priv;
253     LogDebug("private object is realised");
254 }
255
256 JSValueRef JSPreferences::removeItem(JSContextRef context,
257                                      JSObjectRef object,
258                                      JSObjectRef thisObject,
259                                      size_t argumentCount,
260                                      const JSValueRef arguments[],
261                                      JSValueRef* exception)
262 {
263     LogDebug("entered");
264
265     Try {
266         Converter converter(context);
267
268         std::string key = converter.toString(arguments[0]);
269
270         auto event = modifyItemAndCreateEvent(ModificationType::RemoveItem,
271                                               thisObject,
272                                               key);
273
274         auto iframe = IFrameSupport::
275             getIFrameObjectForWidget(getWidgetObject(thisObject));
276
277         Assert(iframe && "Iframe is NULL");
278
279         AddEventListenerSupport::
280             CallListenersFromDifferentIFrames(iframe, event);
281
282         LogDebug("end");
283         return JSValueMakeNull(context);
284     }
285     CATCH_EXCEPTION_NO_MODIFABLE
286     CATCH_EXCEPTION_CONVERSION
287     CATCH_EXCEPTION_NULL_PTR
288     CATCH_EXCEPTION_PLATFORM_ERROR
289     CATCH_EXCEPTION_SECURITY
290 }
291
292 JSValueRef JSPreferences::setItem(JSContextRef context,
293                                   JSObjectRef object,
294                                   JSObjectRef thisObject,
295                                   size_t argumentCount,
296                                   const JSValueRef arguments[],
297                                   JSValueRef* exception)
298 {
299     LogDebug("entered");
300     LogDebug("This: " << thisObject);
301     LogDebug("Object: " << object);
302
303     Try {
304         Converter converter(context);
305
306         std::string key = converter.toString(arguments[0]);
307         std::string value = converter.tryString(arguments[1]);
308
309         auto event = modifyItemAndCreateEvent(ModificationType::SetItem,
310                                               thisObject,
311                                               key,
312                                               value);
313
314         auto iframe = IFrameSupport::
315             getIFrameObjectForWidget(getWidgetObject(thisObject));
316         Assert(iframe && "Iframe is NULL");
317
318         AddEventListenerSupport::
319             CallListenersFromDifferentIFrames(iframe, event);
320
321         LogDebug("end");
322
323         return JSValueMakeUndefined(context);
324     }
325     CATCH_EXCEPTION_NO_MODIFABLE
326     CATCH_EXCEPTION_CONVERSION
327     CATCH_EXCEPTION_NULL_PTR
328     CATCH_EXCEPTION_PLATFORM_ERROR
329     CATCH_EXCEPTION_SECURITY
330     CATCH_EXCEPTION_OUT_OF_RANGE
331 }
332
333
334 JSValueRef JSPreferences::clear(JSContextRef context,
335                                 JSObjectRef object,
336                                 JSObjectRef thisObject,
337                                 size_t argumentCount,
338                                 const JSValueRef arguments[],
339                                 JSValueRef* exception)
340 {
341     LogDebug("entered");
342
343     Try {
344         getIStorage(thisObject)->clear(false);
345
346
347         auto iframe = IFrameSupport::
348             getIFrameObjectForWidget(getWidgetObject(thisObject));
349
350         Assert(iframe && "Iframe is NULL");
351
352         //create event object
353         IStorageEventPtr storageEvent = getStorageEvent();
354
355         AddEventListenerSupport::
356             CallListenersFromDifferentIFrames(iframe, storageEvent);
357
358         LogDebug("end");
359
360         return JSValueMakeNull(context);
361     }
362     CATCH_EXCEPTION_NULL_PTR
363     CATCH_EXCEPTION_PLATFORM_ERROR
364     CATCH_EXCEPTION_SECURITY
365 }
366
367 JSValueRef JSPreferences::getItem(JSContextRef context,
368                                   JSObjectRef object,
369                                   JSObjectRef thisObject,
370                                   size_t argumentCount,
371                                   const JSValueRef arguments[],
372                                   JSValueRef* exception)
373 {
374     LogDebug("entered");
375
376     Try {
377         Converter converter(context);
378
379         std::string key = converter.tryString(arguments[0]);
380
381         LogDebug("Getting item for key " << key);
382
383         DPL::Optional<std::string> value =
384             getIStorage(thisObject)->getValue(key);
385
386         if (!value)
387             return JSValueMakeNull(context);
388         else
389             return converter.toJSValueRef(*value);
390     }
391     CATCH_EXCEPTION_INVALID_ARG
392     CATCH_EXCEPTION_CONVERSION
393     CATCH_EXCEPTION_NULL_PTR
394     CATCH_EXCEPTION_PLATFORM_ERROR
395     CATCH_EXCEPTION_SECURITY
396 }
397
398 JSValueRef JSPreferences::key(JSContextRef context,
399                               JSObjectRef object,
400                               JSObjectRef thisObject,
401                               size_t argumentCount,
402                               const JSValueRef arguments[],
403                               JSValueRef* exception)
404 {
405     LogDebug("entered");
406
407     Try{
408         if (argumentCount<1) {
409             LogError("No argument found");
410             Throw(Commons::InvalidArgumentException);
411         }
412
413         Converter converter(context);
414
415         size_t n = converter.toSizeT(arguments[0]);
416
417         std::string value = getIStorage(thisObject)->getValueByIndex(n);
418
419         LogDebug("end");
420
421         return converter.toJSValueRef(value);
422     }
423     CATCH_EXCEPTION_CONVERSION
424     CATCH_EXCEPTION_NULL_PTR
425     CATCH_EXCEPTION_PLATFORM_ERROR
426     CATCH_EXCEPTION_SECURITY
427     CATCH_EXCEPTION_INVALID_ARG
428 }
429
430 JSValueRef JSPreferences::getLength(JSContextRef context,
431                                     JSObjectRef object,
432                                     JSStringRef propertyName,
433                                     JSValueRef* exception)
434 {
435     LogDebug("enter");
436
437     Try
438     {
439         Converter converter(context);
440
441         size_t value = getIStorage(object)->getStorageSize();
442         return converter.toJSValueRef(value);
443     }
444     CATCH_EXCEPTION_CONVERSION
445     CATCH_EXCEPTION_NULL_PTR
446     CATCH_EXCEPTION_PLATFORM_ERROR
447     CATCH_EXCEPTION_SECURITY
448     CATCH_EXCEPTION_INVALID_ARG
449 }
450
451 bool JSPreferences::hasProperty(JSContextRef context,
452                            JSObjectRef object,
453                            JSStringRef propertyName)
454 {
455     LogDebug("enter");
456
457     Try{
458         Converter converter(context);
459
460         std::string key = converter.toString(propertyName);
461
462         if(!getIStorage(object)->getValue(key)) {
463             return false;
464         } else {
465             return true;
466         }
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 JSPreferences::getProperty(JSContextRef context,
488                                       JSObjectRef object,
489                                       JSStringRef propertyName,
490                                       JSValueRef* exception)
491 {
492     LogDebug("enter");
493
494     Try{
495         Converter converter(context);
496
497         std::string key = converter.toString(propertyName);
498
499         DPL::Optional<std::string> value =
500             getIStorage(object)->getValue(key);
501
502         LogDebug("end");
503
504         if (!value)
505             return JSValueMakeNull(context);
506         else
507             return converter.toJSValueRef(*value);
508     }
509
510     CATCH_EXCEPTION_CONVERSION
511     CATCH_EXCEPTION_NULL_PTR
512     CATCH_EXCEPTION_PLATFORM_ERROR
513     CATCH_EXCEPTION_INVALID_ARG
514 }
515
516 bool JSPreferences::setProperty(JSContextRef context,
517                                 JSObjectRef object,
518                                 JSStringRef propertyName,
519                                 JSValueRef jvalue,
520                                 JSValueRef* exception)
521 {
522     LogDebug("enter");
523
524     Try{
525         Converter converter(context);
526
527         std::string key = converter.toString(propertyName);
528         std::string value = converter.toString(jvalue);
529
530         auto event = modifyItemAndCreateEvent(ModificationType::SetItem,
531                                               object,
532                                               key,
533                                               value);
534
535         auto iframe = IFrameSupport::
536             getIFrameObjectForWidget(getWidgetObject(object));
537         Assert(iframe && "Iframe is NULL");
538
539         AddEventListenerSupport::
540             CallListenersFromDifferentIFrames(iframe, event);
541
542         LogDebug("end");
543
544         return true;
545     }
546     CATCH_EXCEPTION_NO_MODIFABLE
547     CATCH_EXCEPTION_OUT_OF_RANGE
548     CATCH_EXCEPTION_INVALID_ARG
549     CATCH_EXCEPTION_CONVERSION
550     CATCH_EXCEPTION_NULL_PTR
551     CATCH_EXCEPTION_PLATFORM_ERROR
552     CATCH_EXCEPTION_SECURITY
553
554     return false;
555 }
556
557 #undef CATCH_EXCEPTION_NO_MODIFABLE
558 #undef CATCH_EXCEPTION_CONVERSION
559 #undef CATCH_EXCEPTION_NULL_PTR
560 #undef CATCH_EXCEPTION_PLATFORM_ERROR
561 #undef CATCH_EXCEPTION_SECURITY
562 #undef CATCH_EXCEPTION_OUT_OF_RANGE
563 #undef CATCH_EXCEPTION_INVALID_ARG
564
565 }
566 }