2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "JSFilestream.h"
21 #include <dpl/scoped_array.h>
23 #include <Commons/Base64.h>
24 #include <CommonsJavaScript/JSUtils.h>
25 #include <JSWebAPIErrorFactory.h>
26 #include <SecurityExceptions.h>
27 #include <TimeTracer.h>
30 #include "Converter.h"
31 #include "Encodings.h"
32 #include "plugin_config.h"
33 #include "FilesystemUtils.h"
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";
43 using namespace WrtDeviceApis::Commons;
44 using namespace WrtDeviceApis::CommonsJavaScript;
45 using namespace DeviceAPI::Common;
48 namespace Filesystem {
49 JSClassRef JSFilestream::m_classRef = 0;
51 JSClassDefinition JSFilestream::m_classInfo = {
53 kJSClassAttributeNone,
71 JSStaticValue JSFilestream::m_properties[] = {
72 { PROPERTY_EOF, getProperty, NULL, kJSPropertyAttributeReadOnly },
73 { PROPERTY_POSITION, getProperty, setProperty, kJSPropertyAttributeNone },
74 { PROPERTY_BYTES_AVAILABLE, getProperty, NULL, kJSPropertyAttributeReadOnly },
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 },
89 void JSFilestream::initialize(JSContextRef context,
94 void JSFilestream::finalize(JSObjectRef object)
96 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(object));
100 const JSClassRef DLL_EXPORT JSFilestream::getClassRef()
103 m_classRef = JSClassCreate(&m_classInfo);
108 const JSClassDefinition* JSFilestream::getClassInfo()
113 JSValueRef JSFilestream::getProperty(JSContextRef context,
115 JSStringRef propertyName,
116 JSValueRef* exception)
118 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(object));
119 if (!privateObject) {
120 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
124 PrivateObject::ObjectType stream = privateObject->getObject();
125 Converter converter(context);
127 if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_EOF)) {
128 return converter.toJSValueRef(stream->isEof());
129 } else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_POSITION)) {
130 long pos = stream->getPosition();
132 return JSValueMakeUndefined(context);
134 return converter.toJSValueRef(static_cast<unsigned long>(pos));
135 } else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_BYTES_AVAILABLE)) {
136 long position = stream->getPosition();
137 long bytes = stream->getSize() - position;
139 return converter.toJSValueRefLong(static_cast<long>(bytes));
141 } catch (const WrtDeviceApis::Commons::ConversionException& ex) {
142 LoggerW("trying to get incorrect value");
145 return JSValueMakeUndefined(context);
148 bool JSFilestream::setProperty(JSContextRef context,
150 JSStringRef propertyName,
152 JSValueRef* exception)
154 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(object));
155 if (!privateObject) {
159 Converter converter(context);
161 if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_POSITION)) {
162 privateObject->getObject()->setPosition(converter.toLong(value));
165 } catch (const WrtDeviceApis::Commons::Exception& ex) {
166 LoggerW("trying to set incorrect value");
172 void JSFilestream::getPropertyNames(JSContextRef context,
174 JSPropertyNameAccumulatorRef propertyNames)
178 bool JSFilestream::hasInstance(JSContextRef context,
179 JSObjectRef constructor,
181 JSValueRef* exception)
183 return JSValueIsObjectOfClass(context, instance, JSFilestream::getClassRef());
186 JSValueRef JSFilestream::close(JSContextRef context,
188 JSObjectRef thisObject,
190 const JSValueRef argv[],
191 JSValueRef* exception)
193 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
194 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
195 if (!privateObject) {
196 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
200 TIZEN_CHECK_ACCESS(context, exception, privateObject, FILESYSTEM_FUNCTION_API_CLOSE);
203 privateObject->getObject()->close();
204 } Catch (WrtDeviceApis::Commons::PlatformException) {
205 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
208 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
209 return JSValueMakeUndefined(context);
212 JSValueRef JSFilestream::read(JSContextRef context,
214 JSObjectRef thisObject,
216 const JSValueRef argv[],
217 JSValueRef* exception)
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 JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
226 Converter converter(context);
229 TIZEN_CHECK_ACCESS(context, exception, privateObject, FILESYSTEM_FUNCTION_API_READ);
232 JSValueRef undefinedValue = JSValueMakeUndefined(context);
233 unsigned long count = 0;
236 count = converter.toULong(argv[0]);
238 count = converter.toULong(undefinedValue);
241 ThrowMsg(InvalidArgumentException, "Invalid argument");
243 std::string outStr = "";
244 std::string currentCharSet = privateObject->getObject()->getCharSet();
246 DPL::ScopedArray<char> text(privateObject->getObject()->getChars(count));
248 // utf8, iso8859-1, skip
249 if (!strcmp(currentCharSet.c_str(), Encodings::UTF8) || !strcmp(currentCharSet.c_str(), Encodings::ISO88591))
251 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
252 return converter.toJSValueRef(std::string(text.Get()));
256 Utils::toUTF8String(currentCharSet, text.Get(), count, outStr);
257 TIME_TRACER_ITEM_END("read(UTF8)", 0);
258 return converter.toJSValueRef(outStr);
260 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
261 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, ex.GetMessage());
262 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
263 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, ex.GetMessage());
264 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
265 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, ex.GetMessage());
266 } catch(const WrtDeviceApis::Commons::PlatformException& ex) {
267 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::IO_ERROR, ex.GetMessage());
272 JSValueRef JSFilestream::readBytes(JSContextRef context,
274 JSObjectRef thisObject,
276 const JSValueRef argv[],
277 JSValueRef* exception)
279 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
280 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
281 if (!privateObject) {
282 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
285 TIZEN_CHECK_ACCESS(context, exception, privateObject, FILESYSTEM_FUNCTION_API_READ_BYTES);
287 Converter converter(context);
289 JSValueRef undefinedValue = JSValueMakeUndefined(context);
290 unsigned long count = 0;
293 count = converter.toULong(argv[0]);
295 count = converter.toULong(undefinedValue);
298 ThrowMsg(InvalidArgumentException, "Invalid argument");
301 DPL::ScopedArray<unsigned char> data(privateObject->getObject()->getBytes(count));
302 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
303 return converter.toJSValueRef(data.Get(), privateObject->getObject()->getCount());
304 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
305 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, ex.GetMessage());
306 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
307 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, ex.GetMessage());
308 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
309 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, ex.GetMessage());
310 } catch(const WrtDeviceApis::Commons::PlatformException& ex) {
311 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::IO_ERROR, ex.GetMessage());
316 JSValueRef JSFilestream::readBase64(JSContextRef context,
318 JSObjectRef thisObject,
320 const JSValueRef argv[],
321 JSValueRef* exception)
323 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
324 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
325 if (!privateObject) {
326 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
329 TIZEN_CHECK_ACCESS(context, exception, privateObject, FILESYSTEM_FUNCTION_API_READ_BASE64);
331 Converter converter(context);
333 JSValueRef undefinedValue = JSValueMakeUndefined(context);
334 unsigned long count = 0;
337 count = converter.toULong(argv[0]);
339 count = converter.toULong(undefinedValue);
342 ThrowMsg(InvalidArgumentException, "Invalid argument");
345 DPL::ScopedArray<unsigned char> data(privateObject->getObject()->getBytes(count));
346 std::string base64 = WrtDeviceApis::Commons::Base64::encode(data.Get(), privateObject->getObject()->getCount());
347 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
348 return converter.toJSValueRef(base64);
349 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
350 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, ex.GetMessage());
351 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
352 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, ex.GetMessage());
353 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
354 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, ex.GetMessage());
355 } catch(const WrtDeviceApis::Commons::PlatformException& ex) {
356 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::IO_ERROR, ex.GetMessage());
361 JSValueRef JSFilestream::write(JSContextRef context,
363 JSObjectRef thisObject,
365 const JSValueRef argv[],
366 JSValueRef* exception)
368 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
369 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
370 if (!privateObject) {
371 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
374 TIZEN_CHECK_ACCESS(context, exception, privateObject, FILESYSTEM_FUNCTION_API_WRITE);
376 Converter converter(context);
378 JSValueRef undefinedValue = JSValueMakeUndefined(context);
381 privateObject->getObject()->write(converter.toString(argv[0]));
383 privateObject->getObject()->write(converter.toString(undefinedValue));
386 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
387 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, ex.GetMessage());
388 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
389 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, ex.GetMessage());
390 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
391 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, ex.GetMessage());
392 } catch(const WrtDeviceApis::Commons::PlatformException& ex) {
393 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::IO_ERROR, ex.GetMessage());
396 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
397 return JSValueMakeUndefined(context);
400 JSValueRef JSFilestream::writeBytes(JSContextRef context,
402 JSObjectRef thisObject,
404 const JSValueRef argv[],
405 JSValueRef* exception)
407 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
408 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
409 if (!privateObject) {
410 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
413 TIZEN_CHECK_ACCESS(context, exception, privateObject, FILESYSTEM_FUNCTION_API_WRITE_BYTES);
415 Converter converter(context);
417 if (argc < 1 || !JSIsArrayValue(context, argv[0]))
418 ThrowMsg(ConversionException, "Type mismatch error");
420 PrivateObject::ObjectType stream = privateObject->getObject();
421 std::vector<unsigned char> data = converter.toVectorOfUChars(argv[0]);
422 std::vector<unsigned char>::const_iterator it = data.begin();
423 for (; it != data.end(); ++it) {
426 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
427 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, ex.GetMessage());
428 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
429 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, ex.GetMessage());
430 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
431 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, ex.GetMessage());
432 } catch(const WrtDeviceApis::Commons::PlatformException& ex) {
433 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::IO_ERROR, ex.GetMessage());
436 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
437 return JSValueMakeUndefined(context);
440 JSValueRef JSFilestream::writeBase64(JSContextRef context,
442 JSObjectRef thisObject,
444 const JSValueRef argv[],
445 JSValueRef* exception)
447 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
448 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
449 if (!privateObject) {
450 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
453 TIZEN_CHECK_ACCESS(context, exception, privateObject, FILESYSTEM_FUNCTION_API_WRITE_BASE64);
455 Converter converter(context);
459 JSValueRef undefinedValue = JSValueMakeUndefined(context);
462 base64 = WrtDeviceApis::Commons::Base64::decode(converter.toString(argv[0]));
464 base64 = WrtDeviceApis::Commons::Base64::decode(converter.toString(undefinedValue));
466 privateObject->getObject()->write(base64);
467 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
468 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, ex.GetMessage());
469 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
470 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, ex.GetMessage());
471 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
472 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, ex.GetMessage());
473 } catch(const WrtDeviceApis::Commons::PlatformException& ex) {
474 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::IO_ERROR, ex.GetMessage());
477 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
478 return JSValueMakeUndefined(context);