wrt-plugins-tizen_0.4.23
[framework/web/wrt-plugins-tizen.git] / src / Filesystem / JSFilestream.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18  
19 #include "JSFilestream.h"
20
21 #include <dpl/scoped_array.h>
22
23 #include <Commons/Base64.h>
24 #include <CommonsJavaScript/JSUtils.h>
25 #include <JSTizenExceptionFactory.h>
26 #include <JSTizenException.h>
27 #include <SecurityExceptions.h>
28 #include <TimeTracer.h>
29
30 #include "Converter.h"
31 #include "Encodings.h"
32 #include "plugin_config.h"
33 #include "FilesystemUtils.h"
34 #include <Logger.h>
35
36 namespace {
37 const char* PLUGIN_NAME = "FileStream";
38 const char* PROPERTY_EOF = "eof";
39 const char* PROPERTY_POSITION = "position";
40 const char* PROPERTY_BYTES_AVAILABLE = "bytesAvailable";
41 }
42
43 using namespace WrtDeviceApis::Commons;
44 using namespace WrtDeviceApis::CommonsJavaScript;
45 using namespace DeviceAPI::Common;
46
47 namespace DeviceAPI {
48 namespace Filesystem {
49 JSClassRef JSFilestream::m_classRef = 0;
50
51 JSClassDefinition JSFilestream::m_classInfo = {
52         0,
53         kJSClassAttributeNone,
54         PLUGIN_NAME,
55         0,
56         m_properties,
57         m_functions,
58         initialize,
59         finalize,
60         NULL,
61         NULL,
62         NULL,
63         NULL,
64         getPropertyNames,
65         NULL,
66         NULL,
67         hasInstance,
68         NULL
69 };
70
71 JSStaticValue JSFilestream::m_properties[] = {
72         { PROPERTY_EOF, getProperty, NULL, kJSPropertyAttributeReadOnly },
73         { PROPERTY_POSITION, getProperty, setProperty, kJSPropertyAttributeNone },
74         { PROPERTY_BYTES_AVAILABLE, getProperty, NULL, kJSPropertyAttributeReadOnly },
75         { 0, 0, 0, 0 }
76 };
77
78 JSStaticFunction JSFilestream::m_functions[] = {
79         { "close", close, kJSPropertyAttributeNone },
80         { "read", read, kJSPropertyAttributeNone },
81         { "readBytes", readBytes, kJSPropertyAttributeNone },
82         { "readBase64", readBase64, kJSPropertyAttributeNone },
83         { "write", write, kJSPropertyAttributeNone },
84         { "writeBytes", writeBytes, kJSPropertyAttributeNone },
85         { "writeBase64", writeBase64, kJSPropertyAttributeNone },
86         { 0, 0, 0 }
87 };
88
89 void JSFilestream::initialize(JSContextRef context,
90         JSObjectRef object)
91 {
92 }
93
94 void JSFilestream::finalize(JSObjectRef object)
95 {
96         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(object));
97         delete privateObject;
98 }
99
100 const JSClassRef JSFilestream::getClassRef()
101 {
102         if (!m_classRef) {
103                 m_classRef = JSClassCreate(&m_classInfo);
104         }
105         return m_classRef;
106 }
107
108 const JSClassDefinition* JSFilestream::getClassInfo()
109 {
110         return &m_classInfo;
111 }
112
113 JSValueRef JSFilestream::getProperty(JSContextRef context,
114                 JSObjectRef object,
115                 JSStringRef propertyName,
116                 JSValueRef* exception)
117 {
118         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(object));
119         if (!privateObject) {
120                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch error");
121                 
122         }
123
124         PrivateObject::ObjectType stream = privateObject->getObject();
125         Converter converter(context);
126         try {
127                 if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_EOF)) {
128                         return converter.toJSValueRef(stream->isEof());
129                 } else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_POSITION)) {
130                         long pos = stream->getPosition();
131                         if (pos < 0) {
132                                 return JSValueMakeUndefined(context);
133                         }
134                         return converter.toJSValueRef(static_cast<unsigned long>(pos));
135                 } else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_BYTES_AVAILABLE)) {
136                         unsigned long long bytes = stream->getSize() - stream->getPosition();
137                         return converter.toJSValueRef(static_cast<unsigned long long>(bytes));
138                 }
139         } catch (const WrtDeviceApis::Commons::ConversionException& ex) {
140                 LoggerW("trying to get incorrect value");
141         }
142
143         return JSValueMakeUndefined(context);
144 }
145
146 bool JSFilestream::setProperty(JSContextRef context,
147                 JSObjectRef object,
148                 JSStringRef propertyName,
149                 JSValueRef value,
150                 JSValueRef* exception)
151 {
152         PrivateObject* privateObject =  static_cast<PrivateObject*>(JSObjectGetPrivate(object));
153         if (!privateObject) {
154                 return false;
155         }
156
157         Converter converter(context);
158         try {
159                 if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_POSITION)) {
160                         privateObject->getObject()->setPosition(converter.toLong(value));
161                         return true;
162                 }
163         } catch (const WrtDeviceApis::Commons::Exception& ex) {
164                 LoggerW("trying to set incorrect value");
165         }
166
167         return false;
168 }
169
170 void JSFilestream::getPropertyNames(JSContextRef context,
171                 JSObjectRef object,
172                 JSPropertyNameAccumulatorRef propertyNames)
173 {
174 }
175
176 bool JSFilestream::hasInstance(JSContextRef context,
177                 JSObjectRef constructor,
178                 JSValueRef instance,
179                 JSValueRef* exception)
180 {
181     return JSValueIsObjectOfClass(context, instance, JSFilestream::getClassRef());
182 }
183
184 JSValueRef JSFilestream::close(JSContextRef context,
185                 JSObjectRef object,
186                 JSObjectRef thisObject,
187                 size_t argc,
188                 const JSValueRef argv[],
189                 JSValueRef* exception)
190 {
191         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
192         PrivateObject* privateObject =  static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
193         if (!privateObject) {
194                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch error");
195                 
196         }
197         
198         AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_CLOSE);
199         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
200
201
202         Try {
203                 privateObject->getObject()->close();
204         } Catch (WrtDeviceApis::Commons::PlatformException) {
205                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown error");
206         }
207
208         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
209         return JSValueMakeUndefined(context);
210 }
211
212 JSValueRef JSFilestream::read(JSContextRef context,
213                 JSObjectRef object,
214                 JSObjectRef thisObject,
215                 size_t argc,
216                 const JSValueRef argv[],
217                 JSValueRef* exception)
218 {
219         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
220         TIME_TRACER_ITEM_BEGIN("read(UTF8)", 0);
221         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
222         if (!privateObject) {
223                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch error");
224         }
225
226         Converter converter(context);
227         
228         AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_READ);
229         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
230
231         try {
232                 JSValueRef undefinedValue = JSValueMakeUndefined(context);
233                 unsigned long count = 0;
234
235                 if (argc > 0) 
236                         count = converter.toULong(argv[0]);
237                 else 
238                         count = converter.toULong(undefinedValue);
239
240                 if (count <= 0) {
241                         ThrowMsg(InvalidArgumentException, "Invalid argument");
242                 }
243                 std::string outStr = "";
244                 std::string currentCharSet = privateObject->getObject()->getCharSet();
245
246                 DPL::ScopedArray<char> text(privateObject->getObject()->getChars(count));
247
248                 // utf8, iso8859-1, skip
249                 if (!strcmp(currentCharSet.c_str(), Encodings::UTF8) || !strcmp(currentCharSet.c_str(), Encodings::ISO88591))
250                 {
251                         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
252                         return converter.toJSValueRef(std::string(text.Get()));         
253                 }
254                 else 
255                 {
256                         Utils::toUTF8String(currentCharSet, text.Get(), count, outStr);
257                         TIME_TRACER_ITEM_END("read(UTF8)", 0);
258                         return converter.toJSValueRef(outStr);
259                 }
260         } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
261                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, ex.GetMessage());
262         } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
263                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
264         } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
265                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
266         } catch(const WrtDeviceApis::Commons::PlatformException& ex) {
267                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, ex.GetMessage());
268         }
269         
270 }
271
272 JSValueRef JSFilestream::readBytes(JSContextRef context,
273                 JSObjectRef object,
274                 JSObjectRef thisObject,
275                 size_t argc,
276                 const JSValueRef argv[],
277                 JSValueRef* exception)
278 {
279         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
280         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
281         if (!privateObject) {
282                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch error");
283         }
284
285         AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_READ_BYTES);
286         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
287
288
289         Converter converter(context);
290         Try {
291                 JSValueRef undefinedValue = JSValueMakeUndefined(context);
292                 unsigned long count = 0;
293
294                 if (argc > 0) 
295                         count = converter.toULong(argv[0]);
296                 else 
297                         count = converter.toULong(undefinedValue);
298
299                 if (count <= 0) {
300                         ThrowMsg(InvalidArgumentException, "Invalid argument");
301                 }               
302
303                 DPL::ScopedArray<unsigned char> data(privateObject->getObject()->getBytes(count));
304                 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
305                 return converter.toJSValueRef(data.Get(), privateObject->getObject()->getCount());
306         } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
307                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, ex.GetMessage());
308         } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
309                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
310         } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
311                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
312         } catch(const WrtDeviceApis::Commons::PlatformException& ex) {
313                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, ex.GetMessage());
314         }
315
316 }
317
318 JSValueRef JSFilestream::readBase64(JSContextRef context,
319                 JSObjectRef object,
320                 JSObjectRef thisObject,
321                 size_t argc,
322                 const JSValueRef argv[],
323                 JSValueRef* exception)
324 {
325         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
326         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
327         if (!privateObject) {
328                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch error");
329         }
330
331         AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_READ_BASE64);
332         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
333
334         Converter converter(context);
335         try {
336                 JSValueRef undefinedValue = JSValueMakeUndefined(context);
337                 unsigned long count = 0;
338
339                 if (argc > 0) 
340                         count = converter.toULong(argv[0]);
341                 else 
342                         count = converter.toULong(undefinedValue);
343
344                 if (count <= 0) {
345                         ThrowMsg(InvalidArgumentException, "Invalid argument");
346                 }
347
348                 DPL::ScopedArray<unsigned char> data(privateObject->getObject()->getBytes(count));
349                 std::string base64 = WrtDeviceApis::Commons::Base64::encode(data.Get(), privateObject->getObject()->getCount());
350                 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
351                 return converter.toJSValueRef(base64);
352         } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
353                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, ex.GetMessage());
354         } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
355                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
356         } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
357                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
358         } catch(const WrtDeviceApis::Commons::PlatformException& ex) {
359                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, ex.GetMessage());
360         }
361
362 }
363
364 JSValueRef JSFilestream::write(JSContextRef context,
365         JSObjectRef object,
366         JSObjectRef thisObject,
367         size_t argc,
368         const JSValueRef argv[],
369         JSValueRef* exception)
370 {
371         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
372         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
373         if (!privateObject) {
374                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch error");
375         }
376
377         AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_WRITE);
378         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
379
380
381         Converter converter(context);
382         try {
383                 JSValueRef undefinedValue = JSValueMakeUndefined(context);
384
385                 if (argc > 0) 
386                         privateObject->getObject()->write(converter.toString(argv[0]));
387                 else 
388                         privateObject->getObject()->write(converter.toString(undefinedValue));
389
390
391         } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
392                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, ex.GetMessage());
393         } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
394                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
395         } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
396                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
397         } catch(const WrtDeviceApis::Commons::PlatformException& ex) {
398                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, ex.GetMessage());
399         }
400
401         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
402         return JSValueMakeUndefined(context);
403 }
404
405 JSValueRef JSFilestream::writeBytes(JSContextRef context,
406                 JSObjectRef object,
407                 JSObjectRef thisObject,
408                 size_t argc,
409                 const JSValueRef argv[],
410                 JSValueRef* exception)
411 {
412         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
413         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
414         if (!privateObject) {
415                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch error");
416         }
417
418         AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_WRITE_BYTES);
419         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
420
421
422         Converter converter(context);
423         Try {
424                 if (argc < 1 || !JSIsArrayValue(context, argv[0]))
425                         ThrowMsg(ConversionException,  "Type mismatch error");
426
427                 PrivateObject::ObjectType stream = privateObject->getObject();
428                 std::vector<unsigned char> data = converter.toVectorOfUChars(argv[0]);
429                 std::vector<unsigned char>::const_iterator it = data.begin();
430                 for (; it != data.end(); ++it) {
431                         stream->write(*it);
432                 }
433         } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
434                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, ex.GetMessage());
435         } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
436                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
437         } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
438                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
439         } catch(const WrtDeviceApis::Commons::PlatformException& ex) {
440                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, ex.GetMessage());
441         }
442
443         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
444         return JSValueMakeUndefined(context);
445 }
446
447 JSValueRef JSFilestream::writeBase64(JSContextRef context,
448                 JSObjectRef object,
449                 JSObjectRef thisObject,
450                 size_t argc,
451                 const JSValueRef argv[],
452                 JSValueRef* exception)
453 {
454         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
455         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
456         if (!privateObject) {
457                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch error");
458         }
459
460         AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_WRITE_BASE64);
461         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
462
463         Converter converter(context);
464         try {
465                 LoggerD("OK");
466                 
467                 JSValueRef undefinedValue = JSValueMakeUndefined(context);
468                 std::string base64;
469                 if (argc > 0) 
470                         base64 = WrtDeviceApis::Commons::Base64::decode(converter.toString(argv[0]));
471                 else 
472                         base64 = WrtDeviceApis::Commons::Base64::decode(converter.toString(undefinedValue));
473
474                 privateObject->getObject()->write(base64);
475         } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
476                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, ex.GetMessage());
477         } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
478                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
479         } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
480                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
481         } catch(const WrtDeviceApis::Commons::PlatformException& ex) {
482                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, ex.GetMessage());
483         }
484
485         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
486         return JSValueMakeUndefined(context);
487 }
488 } // Tizen1_0
489 } // TizenApis
490