[Release] wrt-plugins-common_0.3.104
[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/secure_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         _E("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         _E("Error on conversion"); \
58         return JSDOMExceptionFactory:: \
59                    UnknownException.make(context, exception); \
60     }
61
62 #define CATCH_EXCEPTION_NULL_PTR \
63     Catch(Commons::NullPointerException) { \
64         _E("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         _E("PlatformException occured"); \
72         return JSDOMExceptionFactory:: \
73                    UnknownException.make(context, exception); \
74     }
75
76 #define CATCH_EXCEPTION_SECURITY \
77     Catch(Commons::SecurityException){ \
78         _E("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         _E("OutOfRangeException"); \
86         return JSDOMExceptionFactory:: \
87                    QuotaExceededException.make(context, exception); \
88     }
89
90 #define CATCH_EXCEPTION_INVALID_ARG \
91     Catch(Commons::InvalidArgumentException) { \
92         _E("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     _D("get localstorage object");
101     LocalStoragePrivateData* priv =
102         static_cast<LocalStoragePrivateData*>(JSObjectGetPrivate(arg));
103
104     if (!priv) {
105         _E("Private object not initialized");
106         ThrowMsg(Commons::NullPointerException,
107                  "Private object not initialized");
108     }
109
110     return priv->istorage;
111 }
112
113 JSObjectRef getWidgetObject(JSObjectRef arg)
114 {
115     _D("get widget object");
116     LocalStoragePrivateData* priv =
117         static_cast<LocalStoragePrivateData*>(JSObjectGetPrivate(arg));
118
119     if (!priv) {
120         _E("Private object not initialized");
121         ThrowMsg(Commons::NullPointerException,
122                  "Private object not initialized");
123     }
124
125     return priv->widgetObject;
126 }
127
128 enum class ModificationType
129 {
130     RemoveItem,
131     SetItem
132 };
133
134 //this function may throw exceptions
135 IStorageEventPtr modifyItemAndCreateEvent(ModificationType type,
136                                           JSObjectRef thisObject,
137                                           const string& key,
138                                           const string& value = std::string())
139 {
140     DPL::Optional<std::string> oldValue =
141         getIStorage(thisObject)->getValue(key);
142
143     if (ModificationType::SetItem == type) {
144         getIStorage(thisObject)->setItem(key, value, false);
145     } else if (ModificationType::RemoveItem == type) {
146         getIStorage(thisObject)->removeItem(key);
147     } else {
148         Assert(0 && "Wrong Modification type");
149     }
150
151     DPL::Optional<std::string> newValue =
152         getIStorage(thisObject)->getValue(key);
153
154     //create event object
155     IStorageEventPtr storageEvent = getStorageEvent();
156
157     //key
158     storageEvent->setKey(key);
159     //oldvalue
160     if (!!oldValue) {
161         storageEvent->setOldValue(*oldValue);
162     }
163     //newValue
164     if (!!newValue) {
165         storageEvent->setNewValue(*newValue);
166     }
167
168     return storageEvent;
169 }
170
171 JSClassDefinition JSPreferences::m_classInfo = {
172     0,
173     kJSClassAttributeNone,
174     PREFERENCES_PLUGIN_NAME,
175     0,
176     m_property,
177     m_function,
178     initialize,
179     finalize,
180     hasProperty,
181     getProperty,
182     setProperty,
183     NULL, //DeleteProperty,
184     NULL, //GetPropertyNames,
185     NULL, //CallAsFunction,
186     NULL, //CallAsConstructor,
187     NULL, //HasInstance,
188     NULL, //ConvertToType,
189 };
190
191 JSStaticFunction JSPreferences::m_function[] = {
192     { "setItem", JSPreferences::setItem, kJSPropertyAttributeNone },
193     { "removeItem", JSPreferences::removeItem, kJSPropertyAttributeNone },
194     { "getItem", JSPreferences::getItem, kJSPropertyAttributeNone },
195     { "clear", JSPreferences::clear, kJSPropertyAttributeNone },
196     { "key", JSPreferences::key, kJSPropertyAttributeNone },
197     { 0, 0, 0 }
198 };
199
200 JSStaticValue JSPreferences::m_property[] = {
201     { LOCAL_STORAGE_PROPERTY_LENGTH,
202       JSPreferences::getLength,
203       NULL,
204       kJSPropertyAttributeReadOnly },
205     { 0, 0, 0, 0 }
206 };
207
208 JSClassRef JSPreferences::getClassRef()
209 {
210     if (!m_jsClassRef) {
211         m_jsClassRef = JSClassCreate(&m_classInfo);
212     }
213     return m_jsClassRef;
214 }
215
216 const JSClassDefinition* JSPreferences::getClassInfo()
217 {
218     return &m_classInfo;
219 }
220
221 JSClassRef JSPreferences::m_jsClassRef =
222     JSClassCreate(JSPreferences::getClassInfo());
223
224 void JSPreferences::initialize(JSContextRef context,
225                                JSObjectRef object)
226 {
227     _D("entered. Context: %p", context);
228
229     LocalStoragePrivateData* priv =
230         static_cast<LocalStoragePrivateData*>(JSObjectGetPrivate(object));
231
232     Assert(priv && "private object of preferences is NULL");
233 }
234
235 void JSPreferences::finalize(JSObjectRef object)
236 {
237     _D("entered");
238     LocalStoragePrivateData* priv =
239         static_cast<LocalStoragePrivateData*>(JSObjectGetPrivate(object));
240
241     delete priv;
242 }
243
244 JSValueRef JSPreferences::removeItem(JSContextRef context,
245                                      JSObjectRef /*object*/,
246                                      JSObjectRef thisObject,
247                                      size_t /*argumentCount*/,
248                                      const JSValueRef arguments[],
249                                      JSValueRef* exception)
250 {
251     _D("entered");
252
253     Try {
254         Converter converter(context);
255
256         std::string key = converter.toString(arguments[0]);
257
258         DPL::Optional<std::string> oldValue = getIStorage(thisObject)->getValue(key);
259         getIStorage(thisObject)->removeItem(key);
260         DPL::Optional<std::string> newValue = getIStorage(thisObject)->getValue(key);
261
262         JSContextRef g_context  = JSContextGetGlobalContext(context);
263
264         DispatchEventSupport::dispatchStorageEvent(g_context, key, oldValue, newValue, "");
265
266         return JSValueMakeNull(context);
267     }
268     CATCH_EXCEPTION_NO_MODIFABLE
269     CATCH_EXCEPTION_CONVERSION
270     CATCH_EXCEPTION_NULL_PTR
271     CATCH_EXCEPTION_PLATFORM_ERROR
272         CATCH_EXCEPTION_SECURITY
273 }
274
275 JSValueRef JSPreferences::setItem(JSContextRef context,
276                                   JSObjectRef /*object*/,
277                                   JSObjectRef thisObject,
278                                   size_t /*argumentCount*/,
279                                   const JSValueRef arguments[],
280                                   JSValueRef* exception)
281 {
282     _D("entered");
283
284     Try {
285         Converter converter(context);
286
287         std::string key = converter.toString(arguments[0]);
288         std::string value = converter.tryString(arguments[1]);
289
290         DPL::Optional<std::string> oldValue = getIStorage(thisObject)->getValue(key);
291         getIStorage(thisObject)->setItem(key, value, false);
292         DPL::Optional<std::string> newValue = getIStorage(thisObject)->getValue(key);
293
294         JSContextRef g_context  = JSContextGetGlobalContext(context);
295
296         DispatchEventSupport::dispatchStorageEvent(g_context, key, oldValue, newValue, "");
297
298         return JSValueMakeUndefined(context);
299     }
300     CATCH_EXCEPTION_NO_MODIFABLE
301     CATCH_EXCEPTION_CONVERSION
302     CATCH_EXCEPTION_NULL_PTR
303     CATCH_EXCEPTION_PLATFORM_ERROR
304     CATCH_EXCEPTION_SECURITY
305         CATCH_EXCEPTION_OUT_OF_RANGE
306 }
307
308 JSValueRef JSPreferences::clear(JSContextRef context,
309                                 JSObjectRef /*object*/,
310                                 JSObjectRef thisObject,
311                                 size_t /*argumentCount*/,
312                                 const JSValueRef /*arguments*/[],
313                                 JSValueRef* exception)
314 {
315     _D("entered");
316
317     Try {
318         getIStorage(thisObject)->clear(false);
319
320         JSContextRef g_context  = JSContextGetGlobalContext(context);
321
322         const auto& null = DPL::Optional<std::string>::Null;
323
324         DispatchEventSupport::dispatchStorageEvent(g_context, null, null, null, "");
325
326         return JSValueMakeNull(context);
327     }
328     CATCH_EXCEPTION_NULL_PTR
329     CATCH_EXCEPTION_PLATFORM_ERROR
330         CATCH_EXCEPTION_SECURITY
331 }
332
333 JSValueRef JSPreferences::getItem(JSContextRef context,
334                                   JSObjectRef /*object*/,
335                                   JSObjectRef thisObject,
336                                   size_t /*argumentCount*/,
337                                   const JSValueRef arguments[],
338                                   JSValueRef* exception)
339 {
340     _D("entered");
341
342     Try {
343         Converter converter(context);
344
345         std::string key = converter.tryString(arguments[0]);
346
347         _D("Getting item for key %s", key.c_str());
348
349         DPL::Optional<std::string> value =
350             getIStorage(thisObject)->getValue(key);
351
352         if (!value) {
353             return JSValueMakeNull(context);
354         } else {
355             return converter.toJSValueRef(*value);
356         }
357     }
358     CATCH_EXCEPTION_INVALID_ARG
359     CATCH_EXCEPTION_CONVERSION
360     CATCH_EXCEPTION_NULL_PTR
361     CATCH_EXCEPTION_PLATFORM_ERROR
362         CATCH_EXCEPTION_SECURITY
363 }
364
365 JSValueRef JSPreferences::key(JSContextRef context,
366                               JSObjectRef /*object*/,
367                               JSObjectRef thisObject,
368                               size_t argumentCount,
369                               const JSValueRef arguments[],
370                               JSValueRef* exception)
371 {
372     _D("entered");
373
374     Try {
375         if (argumentCount < 1) {
376             _E("No argument found");
377             Throw(Commons::InvalidArgumentException);
378         }
379
380         Converter converter(context);
381
382         size_t n = converter.toSizeT(arguments[0]);
383
384         std::string value = getIStorage(thisObject)->getKeyByIndex(n);
385
386         return converter.toJSValueRef(value);
387     }
388     CATCH_EXCEPTION_CONVERSION
389     CATCH_EXCEPTION_NULL_PTR
390     CATCH_EXCEPTION_PLATFORM_ERROR
391     CATCH_EXCEPTION_SECURITY
392         CATCH_EXCEPTION_INVALID_ARG
393 }
394
395 JSValueRef JSPreferences::getLength(JSContextRef context,
396                                     JSObjectRef object,
397                                     JSStringRef /*propertyName*/,
398                                     JSValueRef* exception)
399 {
400     _D("enter");
401
402     Try
403     {
404         Converter converter(context);
405
406         size_t value = getIStorage(object)->getStorageSize();
407         return converter.toJSValueRef(value);
408     }
409     CATCH_EXCEPTION_CONVERSION
410     CATCH_EXCEPTION_NULL_PTR
411     CATCH_EXCEPTION_PLATFORM_ERROR
412     CATCH_EXCEPTION_SECURITY
413         CATCH_EXCEPTION_INVALID_ARG
414 }
415
416 bool JSPreferences::hasProperty(JSContextRef context,
417                                 JSObjectRef object,
418                                 JSStringRef propertyName)
419 {
420     _D("enter");
421
422     Try {
423         Converter converter(context);
424
425         std::string key = converter.toString(propertyName);
426
427         if (!getIStorage(object)->getValue(key)) {
428             return false;
429         } else {
430             return true;
431         }
432     }
433
434     Catch(Commons::InvalidArgumentException) {
435         _E("Pair for given key doesnt exist");
436     }
437
438     Catch(Commons::ConversionException) {
439         _E("Error on conversion");
440     }
441
442     Catch(Commons::NullPointerException) {
443         _E("Error on pointer, null value");
444     }
445
446     Catch(Commons::PlatformException){
447         _E("PlatformException occured");
448     }
449     return false;
450 }
451
452 JSValueRef JSPreferences::getProperty(JSContextRef context,
453                                       JSObjectRef object,
454                                       JSStringRef propertyName,
455                                       JSValueRef* exception)
456 {
457     _D("enter");
458
459     Try {
460         Converter converter(context);
461
462         std::string key = converter.toString(propertyName);
463
464         DPL::Optional<std::string> value =
465             getIStorage(object)->getValue(key);
466
467         if (!value) {
468             return JSValueMakeNull(context);
469         } else {
470             return converter.toJSValueRef(*value);
471         }
472     }
473
474     CATCH_EXCEPTION_CONVERSION
475     CATCH_EXCEPTION_NULL_PTR
476     CATCH_EXCEPTION_PLATFORM_ERROR
477         CATCH_EXCEPTION_INVALID_ARG
478 }
479
480 bool JSPreferences::setProperty(JSContextRef context,
481                                 JSObjectRef object,
482                                 JSStringRef propertyName,
483                                 JSValueRef jvalue,
484                                 JSValueRef* exception)
485 {
486     _D("enter");
487
488     Try {
489         Converter converter(context);
490
491         std::string key = converter.toString(propertyName);
492         std::string value = converter.toString(jvalue);
493
494         DPL::Optional<std::string> oldValue = getIStorage(object)->getValue(key);
495         getIStorage(object)->setItem(key, value, false);
496         DPL::Optional<std::string> newValue = getIStorage(object)->getValue(key);
497
498         JSContextRef g_context  = JSContextGetGlobalContext(context);
499         std::string oldValueStr = "";
500         std::string newValueStr = "";
501
502         if (!!oldValue) { oldValueStr = *oldValue; }
503         if (!!newValue) { newValueStr = *newValue; }
504
505         DispatchEventSupport::dispatchStorageEvent(g_context, key, oldValueStr, newValueStr, "");
506
507         return true;
508     }
509     CATCH_EXCEPTION_NO_MODIFABLE
510     CATCH_EXCEPTION_OUT_OF_RANGE
511     CATCH_EXCEPTION_INVALID_ARG
512     CATCH_EXCEPTION_CONVERSION
513     CATCH_EXCEPTION_NULL_PTR
514     CATCH_EXCEPTION_PLATFORM_ERROR
515         CATCH_EXCEPTION_SECURITY
516
517     return false;
518 }
519
520 #undef CATCH_EXCEPTION_NO_MODIFABLE
521 #undef CATCH_EXCEPTION_CONVERSION
522 #undef CATCH_EXCEPTION_NULL_PTR
523 #undef CATCH_EXCEPTION_PLATFORM_ERROR
524 #undef CATCH_EXCEPTION_SECURITY
525 #undef CATCH_EXCEPTION_OUT_OF_RANGE
526 #undef CATCH_EXCEPTION_INVALID_ARG
527 }
528 }