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