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.
28 #include <Commons/FunctionDeclaration.h>
29 #include <Commons/Exception.h>
30 #include <Commons/WrtAccess/WrtAccess.h>
31 #include <CommonsJavaScript/JSCallbackManager.h>
32 #include <CommonsJavaScript/Validator.h>
33 #include <CommonsJavaScript/JSUtils.h>
34 #include <JSWebAPIErrorFactory.h>
35 #include <SecurityExceptions.h>
36 #include <ArgumentValidator.h>
37 #include <GlobalContextManager.h>
40 #include <TimeTracer.h>
44 #include "EventCopy.h"
45 #include "EventMove.h"
46 #include "EventListNodes.h"
47 #include "EventOpen.h"
48 #include "EventReadText.h"
49 #include "Converter.h"
50 #include "plugin_config.h"
51 #include "Encodings.h"
52 #include "JSFilestream.h"
54 #include "FilesystemUtils.h"
55 #include "FilesystemPathUtils.h"
56 #include <SecurityAccessor.h>
58 using namespace WrtDeviceApis::Commons;
59 using namespace WrtDeviceApis::CommonsJavaScript;
62 #define PLUGIN_NAME "File"
63 #define PROPERTY_PARENT "parent"
64 #define PROPERTY_READ_ONLY "readOnly"
65 #define PROPERTY_IS_FILE "isFile"
66 #define PROPERTY_IS_DIRECTORY "isDirectory"
67 #define PROPERTY_CREATED "created"
68 #define PROPERTY_MODIFIED "modified"
69 #define PROPERTY_PATH "path"
70 #define PROPERTY_NAME "name"
71 #define PROPERTY_FULL_PATH "fullPath"
72 #define PROPERTY_FILE_SIZE "fileSize"
73 #define PROPERTY_LENGTH "length"
75 const std::string TIME_TRACER_FILE_RESOLVE = "JSFile::resolve";
78 JSValueRef getFunctionOrNull(JSContextRef ctx, JSValueRef arg)
80 if (Validator(ctx).isCallback(arg)) {
82 } else if (!JSValueIsNull(ctx, arg) && !JSValueIsUndefined(ctx, arg)) {
83 LOGW("throw DeviceAPI::Common::TypeMismatchException");
84 throw DeviceAPI::Common::TypeMismatchException(
85 "Not a function nor JS null.");
90 JSValueRef getFunction(JSContextRef ctx, JSValueRef arg)
92 if (Validator(ctx).isCallback(arg)) {
95 LOGW("throw DeviceAPI::Common::TypeMismatchException");
96 throw DeviceAPI::Common::TypeMismatchException(
97 "Not a function nor JS null.");
101 namespace DeviceAPI {
102 namespace Filesystem {
104 using namespace DeviceAPI::Common;
107 template <class EventPtr>
108 bool verifyPath(EventPtr callback,
110 JSContextRef localContext,
114 EventResolvePtr eventResolve(new EventResolve(localContext));
115 eventResolve->setPath(aPath);
116 eventResolve->setForSynchronousCall();
118 Manager::getInstance().getNode(eventResolve);
119 if (!eventResolve->getResult() || !eventResolve->getExceptionName().empty())
121 LOGW("Exception name %s", eventResolve->getExceptionName().c_str());
122 if ("NotFoundError" == eventResolve->getExceptionName())
124 LOGW("throw NotFoundException");
125 throw DeviceAPI::Common::NotFoundException(
128 LOGD("POST IO ERROR");
129 Utils::MainLoop<EventPtr>::passErrorLater(
130 JSWebAPIErrorFactory::IO_ERROR,
132 JSValueMakeUndefined(localContext),
136 if (eventResolve->getResult()->getType() != aType) {
137 LOGW("throw InvalidValuesException");
138 throw DeviceAPI::Common::InvalidValuesException(
139 "Invalid directory");
143 } //Anonymous namespace
145 JSClassRef JSFile::m_classRef = 0;
147 JSClassDefinition JSFile::m_classInfo = {
149 kJSClassAttributeNone,
167 JSStaticValue JSFile::m_properties[] = {
168 { PROPERTY_PARENT, getProperty, NULL, kJSPropertyAttributeReadOnly },
169 { PROPERTY_READ_ONLY, getProperty, NULL, kJSPropertyAttributeReadOnly },
170 { PROPERTY_IS_FILE, getProperty, NULL, kJSPropertyAttributeReadOnly },
171 { PROPERTY_IS_DIRECTORY, getProperty, NULL, kJSPropertyAttributeReadOnly },
172 { PROPERTY_CREATED, getProperty, NULL, kJSPropertyAttributeReadOnly },
173 { PROPERTY_MODIFIED, getProperty, NULL, kJSPropertyAttributeReadOnly },
174 { PROPERTY_PATH, getProperty, NULL, kJSPropertyAttributeReadOnly },
175 { PROPERTY_NAME, getProperty, NULL, kJSPropertyAttributeReadOnly },
176 { PROPERTY_FULL_PATH, getProperty, NULL, kJSPropertyAttributeReadOnly },
177 { PROPERTY_FILE_SIZE, getProperty, NULL, kJSPropertyAttributeReadOnly },
178 { PROPERTY_LENGTH, getProperty, NULL, kJSPropertyAttributeReadOnly },
182 JSStaticFunction JSFile::m_functions[] = {
183 { "toURI", toUri, kJSPropertyAttributeNone },
184 { "listFiles", listFiles, kJSPropertyAttributeNone },
185 { "openStream", openStream, kJSPropertyAttributeNone },
186 { "readAsText", readAsText, kJSPropertyAttributeNone },
187 { "copyTo", copyTo, kJSPropertyAttributeNone },
188 { "moveTo", moveTo, kJSPropertyAttributeNone },
189 { "createDirectory", createDirectory, kJSPropertyAttributeNone },
190 { "createFile", createFile, kJSPropertyAttributeNone },
191 { "resolve", resolve, kJSPropertyAttributeNone },
192 { "deleteDirectory", deleteDirectory, kJSPropertyAttributeNone },
193 { "deleteFile", deleteFile, kJSPropertyAttributeNone },
197 void JSFile::initialize(JSContextRef context,
202 void JSFile::finalize(JSObjectRef object)
204 FileHolder* priv = static_cast<FileHolder*>(JSObjectGetPrivate(object));
206 JSObjectSetPrivate(object, NULL);
211 const JSClassRef DLL_EXPORT JSFile::getClassRef()
214 m_classRef = JSClassCreate(&m_classInfo);
219 const JSClassDefinition* JSFile::getClassInfo()
224 FilePtr DLL_EXPORT JSFile::getPrivateObject(JSContextRef context,
227 if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
228 LOGE("Object type do not match");
229 throw TypeMismatchException("Object type is not JSFile");
232 JSObjectRef object = JSUtil::JSValueToObject(context, value);
233 FileHolder* priv = static_cast<FileHolder*>(JSObjectGetPrivate(object));
235 LOGE("NULL private data");
236 throw UnknownException("Private data holder is null");
239 LOGE("NULL shared pointer in private data");
240 throw UnknownException("Private data is null");
246 void JSFile::setPrivateObject(JSObjectRef object, FilePtr data)
249 LOGE("NULL shared pointer given to set as private data");
250 throw UnknownException("NULL private data given");
253 FileHolder* priv = static_cast<FileHolder*>(JSObjectGetPrivate(object));
258 priv = new FileHolder();
261 if(!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
264 LOGE("Failed to set JSFile private datae");
265 throw UnknownException("Failed to set JSFile private data");
270 JSObjectRef DLL_EXPORT JSFile::makeJSObject(JSContextRef context, FilePtr ptr,
271 Common::SecurityAccessor* srcSecurityAccessor)
274 LOGE("NULL pointer to File given");
275 throw UnknownException("NULL pointer to File given");
278 FileHolder* priv = new FileHolder();
281 JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
282 if(!JSObjectSetPrivate(obj, static_cast<void*>(priv))) {
284 LOGE("Failed to set private in JSFile");
285 throw UnknownException("Private data not set");
288 ptr->setContext(context);
290 if(srcSecurityAccessor) {
291 ptr->copyAceCheckAccessFunction(srcSecurityAccessor);
294 LOGW("Source SecurityAccessor is not available!");
300 JSValueRef JSFile::getProperty(JSContextRef context,
302 JSStringRef propertyName,
303 JSValueRef* exception)
308 FilePtr priv = JSFile::getPrivateObject(context, object);
310 LOGE("Private object is not set.");
311 return JSValueMakeUndefined(context);
314 JSContextRef globalContext = priv->getContext();
315 Converter converter(globalContext);
317 auto node = priv->getNode();
318 if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_PARENT))
320 NodePtr parent(node->getParent());
321 File::PermissionList perms = priv->getParentPermissions();
322 if (parent && !perms.empty())
324 parent->setPermissions(perms.back());
327 FilePtr parentPriv = FilePtr(new File(parent, perms));
328 return JSFile::makeJSObject(priv->getContext(),parentPriv, priv.get());
330 return JSValueMakeNull(context);
332 else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_READ_ONLY))
334 bool readOnly = ((node->getMode() & PM_USER_WRITE) == 0);
335 return converter.toJSValueRef(readOnly);
337 else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_IS_FILE))
339 bool isFile = (node->getType() == NT_FILE);
340 return converter.toJSValueRef(isFile);
342 else if (JSStringIsEqualToUTF8CString(propertyName,
343 PROPERTY_IS_DIRECTORY))
345 bool isDirectory = (node->getType() == NT_DIRECTORY);
346 return converter.toJSValueRef(isDirectory);
348 else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_CREATED))
350 std::time_t created = node->getCreated();
351 return converter.toJSValueRef(created);
353 else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_MODIFIED))
355 std::time_t modified = node->getModified();
356 return converter.toJSValueRef(modified);
358 else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_PATH))
360 std::string fpath = node->getPath()->getFullPath();
361 std::string vpath = Utils::toVirtualPath(globalContext, fpath);
362 std::string::size_type pos = vpath.rfind(Path::getSeparator());
364 if (std::string::npos != pos)
366 path = vpath.substr(0, pos + 1);
372 return converter.toJSValueRef(path);
374 else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_NAME))
376 std::string fpath = node->getPath()->getFullPath();
377 std::string vpath = Utils::toVirtualPath(globalContext, fpath);
379 std::string::size_type pos = vpath.rfind(Path::getSeparator());
381 if (std::string::npos != pos) {
382 name = vpath.substr(pos + 1);
384 return converter.toJSValueRef(name);
386 else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_FULL_PATH))
388 std::string path = priv->getOriginalFullPath();
389 LOGD("path = originalFullPath: %s", path.c_str());
392 path = node->getPath()->getFullPath();
393 LOGD("path = %s (originalFullPath is not set)", path.c_str());
396 return converter.toJSValueRef(Utils::toVirtualPath(globalContext,
399 else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_FILE_SIZE))
401 if (node->getType() == NT_DIRECTORY)
403 return JSValueMakeUndefined(context);
405 return converter.toJSValueRef(node->getSize());
407 else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_LENGTH))
409 if (node->getType() == NT_FILE) {
410 return JSValueMakeUndefined(context);
412 // TODO: think about more efficent solution!
413 NodeList children = node->getChildNodes();
414 return converter.toJSValueRef(children.size());
416 } catch (const WrtDeviceApis::Commons::Exception& ex) {
417 LOGW("Exception caught: %s", ex.GetMessage().c_str());
418 } catch (const DeviceAPI::Common::BasePlatformException& ex) {
419 LOGW("Exception caught: %s", ex.getMessage().c_str());
421 LOGW("Unknown exception cought");
424 return JSValueMakeUndefined(context);
427 void JSFile::getPropertyNames(JSContextRef context,
429 JSPropertyNameAccumulatorRef propertyNames)
433 bool JSFile::hasInstance(JSContextRef context,
434 JSObjectRef constructor,
435 JSValueRef possibleInstance,
436 JSValueRef* exception)
438 return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
441 JSValueRef JSFile::toUri(JSContextRef context,
443 JSObjectRef thisObject,
445 const JSValueRef argv[],
446 JSValueRef* exception)
448 SET_TIME_TRACER_ITEM(0);
452 FilePtr priv = JSFile::getPrivateObject(context, thisObject);
454 Converter converter(context);
455 TIZEN_CHECK_ACCESS(context, exception, priv.get(), FILESYSTEM_FUNCTION_API_TO_URI);
457 std::string uri = priv->getOriginalURI();
458 LOGD("uri = originalURI: %s", uri.c_str());
461 int widgetId = WrtAccessSingleton::Instance().getWidgetId();
462 uri = priv->getNode()->toUri(widgetId);
463 LOGD("uri = %s(originalURI is not set)", uri.c_str());
466 return converter.toJSValueRef(uri);
467 } catch(const DeviceAPI::Common::BasePlatformException& err) {
468 LOGW("WrtDeviceAPI::Common::BasePlatformException exception caught");
469 return JSWebAPIErrorFactory::postException(context, exception, err);
471 LOGW("Unexpected exception caught");
472 DeviceAPI::Common::UnknownException err(
474 return JSWebAPIErrorFactory::postException(context, exception, err);
478 JSValueRef JSFile::listFiles(JSContextRef context,
480 JSObjectRef thisObject,
482 const JSValueRef argv[],
483 JSValueRef* exception)
485 SET_TIME_TRACER_ITEM(0);
488 EventListNodesPtr callback;
491 FilePtr priv = JSFile::getPrivateObject(context, thisObject);
493 TIZEN_CHECK_ACCESS(context, exception, priv.get(),
494 FILESYSTEM_FUNCTION_API_LIST_FILES);
496 ArgumentValidator validator(context, argc, argv);
497 validator.toFunction(0, false);
498 validator.toFunction(1, true);
499 validator.toObject(2, true);
501 JSContextRef globalContext = priv->getContext();
503 JSValueRef reserveArguments[3];
504 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
506 auto globalContextManager = GlobalContextManager::getInstance();
507 auto listContext = globalContextManager->getGlobalContext(context);
508 callback = EventListNodesPtr(new EventListNodes(listContext));
510 for (index = 0; index < 3; index++)
513 reserveArguments[index] = argv[index];
515 reserveArguments[index] = JSValueMakeUndefined(context);
519 JSValueRef onSuccess = getFunction(globalContext, reserveArguments[0]);
520 JSValueRef onError = NULL;
524 onError = getFunctionOrNull(globalContext, reserveArguments[1]);
527 callback->setSuccessCallback(onSuccess);
528 callback->setErrorCallback(onError);
530 Converter converter(globalContext);
533 if (JSValueIsNull(context, reserveArguments[2]) == false &&
534 JSValueIsUndefined(context, reserveArguments[2]) == false) {
535 callback->setFilter(converter.toNodeFilter(reserveArguments[2]));
538 auto myNode = priv->getNode();
539 File::PermissionList perms = priv->getParentPermissions();
540 perms.push_back(myNode->getPermissions());
542 callback->setParentPermissions(perms);
543 callback->setNode(myNode);
545 Node::getChildNodes(callback);
547 } catch(const DeviceAPI::Common::BasePlatformException& err) {
548 LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
549 if (!checkReportAsyncAPI(err.getName(),
553 LOGD("Synchronous error report for [%s]", err.getName().c_str());
554 return JSWebAPIErrorFactory::postException(context,
558 } catch(const WrtDeviceApis::Commons::Exception& err) {
559 LOGD("WrtDeviceApis::Commons::Exception Exception caught");
560 if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
564 return JSWebAPIErrorFactory::postException(
567 translateApi2APIErrors(std::string(err.GetClassName())),
568 std::string(err.GetMessage()));
571 LOGD("Unexpected exception caught");
572 DeviceAPI::Common::UnknownException err(
574 return JSWebAPIErrorFactory::postException(context, exception, err);
576 return JSValueMakeUndefined(context);
579 JSValueRef JSFile::openStream(JSContextRef context,
581 JSObjectRef thisObject,
582 size_t argumentCount,
583 const JSValueRef arguments[],
584 JSValueRef* exception)
586 SET_TIME_TRACER_ITEM(0);
589 EventOpenPtr callback;
591 FilePtr priv = JSFile::getPrivateObject(context, thisObject);
592 TIZEN_CHECK_ACCESS(context, exception, priv.get(),
593 FILESYSTEM_FUNCTION_API_OPEN_STREAM);
595 auto globalCtx = GlobalContextManager::getInstance()->getGlobalContext(context);
596 callback = EventOpenPtr(new EventOpen(globalCtx));
597 ArgumentValidator validator(context, argumentCount, arguments);
599 Converter(globalCtx).toAccessMode(validator.toJSValueRef(0, false));
600 callback->setSuccessCallback(validator.toFunction(1 ,false));
601 callback->setErrorCallback(validator.toFunction(2 ,true));
602 std::string encoding = validator.toString(3, true, Encodings::UTF8);
604 auto node = priv->getNode();
605 if ((AM_READ != mode) && (PERM_READ == node->getPermissions())) {
606 LOGE("Permission denied");
607 return Utils::MainLoop<EventOpenPtr>::passErrorLater(
608 JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
609 "permission denied error",
610 JSValueMakeUndefined(context),
614 if (!(encoding == Encodings::UTF8 || encoding == Encodings::ISO88591
615 || encoding == Encodings::SJIS)) {
616 LOGE("Type mismath");
617 throw DeviceAPI::Common::TypeMismatchException("Type mismatch");
619 callback->setCharSet(encoding);
620 callback->setNode(priv->getNode());
621 callback->setMode(mode);
622 Node::open(callback);
624 } catch(const DeviceAPI::Common::BasePlatformException& err) {
625 LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
626 if (!checkReportAsyncAPI(err.getName(),
630 LOGD("Synchronous error report for [%s]", err.getName().c_str());
631 return JSWebAPIErrorFactory::postException(context,
635 } catch(const WrtDeviceApis::Commons::Exception& err) {
636 LOGD("WrtDeviceApis::Commons::Exception Exception caught");
637 if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
641 return JSWebAPIErrorFactory::postException(
644 translateApi2APIErrors(std::string(err.GetClassName())),
645 std::string(err.GetMessage()));
648 LOGD("Unexpected exception caught");
649 DeviceAPI::Common::UnknownException err(
651 return JSWebAPIErrorFactory::postException(context, exception, err);
654 return JSValueMakeUndefined(context);
657 JSValueRef JSFile::readAsText(
658 JSContextRef localContext,
660 JSObjectRef thisObject,
662 const JSValueRef argv[],
663 JSValueRef* exception)
665 SET_TIME_TRACER_ITEM(0);
668 EventReadTextPtr callback;
671 FilePtr priv = JSFile::getPrivateObject(localContext, thisObject);
672 TIZEN_CHECK_ACCESS(localContext, exception, priv.get(),
673 FILESYSTEM_FUNCTION_API_READ_AS_TEXT);
675 callback = EventReadTextPtr(new EventReadText(
676 GlobalContextManager::getInstance()->getGlobalContext(localContext)));
678 ArgumentValidator validator(localContext, argc, argv);
679 callback->setSuccessCallback(validator.toFunction(0,false));
680 callback->setErrorCallback(validator.toFunction(1,true));
682 std::string encoding = validator.toString(2,true,Encodings::UTF8);
684 if (!(encoding == Encodings::UTF8 || encoding == Encodings::ISO88591
685 || encoding == Encodings::SJIS)) {
686 LOGE("Type mismath");
687 throw DeviceAPI::Common::TypeMismatchException("Type mismatch");
690 if (NT_FILE != priv->getNode()->getType()) {
691 LOGE("JSFile is not file.");
692 return Utils::MainLoop<EventReadTextPtr>::passErrorLater(
693 JSWebAPIErrorFactory::IO_ERROR,
695 JSValueMakeUndefined(localContext),
699 callback->setCharSet(encoding);
700 callback->setNode(priv->getNode());
702 Node::readAsText(callback);
704 } catch(const DeviceAPI::Common::BasePlatformException& err) {
705 LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
706 if (!checkReportAsyncAPI(err.getName(),
710 LOGD("Synchronous error report for [%s]", err.getName().c_str());
711 return JSWebAPIErrorFactory::postException(localContext,
715 } catch(const WrtDeviceApis::Commons::Exception& err) {
716 LOGD("WrtDeviceApis::Commons::Exception Exception caught");
717 if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
721 return JSWebAPIErrorFactory::postException(
724 translateApi2APIErrors(std::string(err.GetClassName())),
725 std::string(err.GetMessage()));
728 LOGD("Unexpected exception caught");
729 DeviceAPI::Common::UnknownException err(
731 return JSWebAPIErrorFactory::postException(localContext, exception, err);
734 return JSValueMakeUndefined(localContext);
737 JSValueRef JSFile::copyTo(JSContextRef localContext,
738 JSObjectRef /*object*/,
739 JSObjectRef thisObject,
741 const JSValueRef argv[],
742 JSValueRef* exception)
744 SET_TIME_TRACER_ITEM(0);
747 JSContextRef globalContext = NULL;
748 EventCopyPtr callback;
751 FilePtr priv = JSFile::getPrivateObject(localContext, thisObject);
753 TIZEN_CHECK_ACCESS(localContext, exception, priv.get(),
754 FILESYSTEM_FUNCTION_API_COPY_TO);
756 JSContextRef privateContext = priv->getContext();
758 JSValueRef reserveArguments[5];
759 auto globalContextManager = GlobalContextManager::getInstance();
760 globalContext = globalContextManager->getGlobalContext(localContext);
761 callback = EventCopyPtr(new EventCopy(globalContext));
763 ArgumentValidator validator(localContext, argc, argv);
764 validator.toFunction(3, true);
765 validator.toFunction(4, true);
767 for (index = 0; index < 5; index++)
770 reserveArguments[index] = argv[index];
772 reserveArguments[index] = JSValueMakeUndefined(localContext);
776 Converter converter(privateContext);
777 JSValueRef onSuccess = NULL;
778 JSValueRef onError = NULL;
780 onSuccess = getFunctionOrNull(privateContext, reserveArguments[3]);
781 onError = getFunctionOrNull(privateContext, reserveArguments[4]);
783 callback->setSuccessCallback(onSuccess);
784 callback->setErrorCallback(onError);
786 //TODO add check validation for src, dest string.
787 PathPtr src = Utils::fromVirtualPath(
789 converter.toString(reserveArguments[0]));
790 PathPtr dest = Utils::fromVirtualPath(
792 converter.toString(reserveArguments[1]));
793 bool overwrite = converter.toBool(reserveArguments[2]);;
795 auto dirNode = priv->getNode();
796 LOGD("copyTo executed from dir:[%s] src path:[%s] dest path:[%s]",
797 dirNode->getPath()->getFullPath().c_str(),
798 src->getFullPath().c_str(),
799 dest->getFullPath().c_str());
800 if (NT_DIRECTORY != dirNode->getType()) {
801 LOGW("This node is not directory");
802 return Utils::MainLoop<EventCopyPtr>::passErrorLater(
803 JSWebAPIErrorFactory::IO_ERROR,
805 JSValueMakeUndefined(localContext),
810 // The file or directory to be copied MUST be under the Directory
811 // from which the method is invoked, otherwise the operation
812 // MUST NOT be performed.
814 // ringtones: the location for ringtones (read-only location)
815 // wgt-package: the widget package location (read-only location)
818 const bool isSubPath = dirNode->isSubPath(src);
819 const bool destIsAllowed = isDestinationAllowed(dest);
820 if (!isSubPath || !destIsAllowed)
822 LOGE("isSubPath:%d destIsAllowed:%d", isSubPath, destIsAllowed);
823 return Utils::MainLoop<EventCopyPtr>::passErrorLater(
824 JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
826 JSValueMakeUndefined(localContext),
830 callback->setSource(src);
831 callback->setDestination(dest);
834 callback->setOptions(OPT_OVERWRITE);
837 Manager::getInstance().copy(callback);
838 } catch(const DeviceAPI::Common::BasePlatformException& err) {
839 LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
840 if (!checkReportAsyncAPI(err.getName(),
845 LOGD("Synchronous error report for [%s]", err.getName().c_str());
846 return JSWebAPIErrorFactory::postException(localContext,
850 } catch(const WrtDeviceApis::Commons::Exception& err) {
851 LOGD("WrtDeviceApis::Commons::Exception Exception caught");
852 if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
857 return JSWebAPIErrorFactory::postException(
860 translateApi2APIErrors(std::string(err.GetClassName())),
861 std::string(err.GetMessage()));
864 LOGD("Unexpected exception caught");
865 DeviceAPI::Common::UnknownException err("Unknown Error");
866 return JSWebAPIErrorFactory::postException(localContext, exception, err);
869 return JSValueMakeUndefined(localContext);
872 bool JSFile::isDestinationAllowed(PathPtr aDestination)
874 static auto ringtones =
875 Utils::fromVirtualPath(NULL, "ringtones")->getFullPath();
876 static auto wgtPackage =
877 Utils::fromVirtualPath(NULL, "wgt-package")->getFullPath();
878 LOGD("Check allowed destinations ringtones [%s] wgt-package [%s] "
882 aDestination->getFullPath().c_str());
883 return !Node::isSubPath(ringtones, aDestination) &&
884 !Node::isSubPath(wgtPackage, aDestination);
888 JSValueRef JSFile::moveTo(JSContextRef localContext,
890 JSObjectRef thisObject,
892 const JSValueRef argv[],
893 JSValueRef* exception)
895 SET_TIME_TRACER_ITEM(0);
898 EventMovePtr callback;
901 FilePtr priv = JSFile::getPrivateObject(localContext, thisObject);
903 TIZEN_CHECK_ACCESS(localContext, exception, priv.get(),
904 FILESYSTEM_FUNCTION_API_MOVE_TO);
906 ArgumentValidator validator(localContext, argc, argv);
907 auto globalManager = GlobalContextManager::getInstance();
908 JSContextRef globalContext = globalManager->getGlobalContext(localContext);
909 callback = EventMovePtr(new EventMove(globalContext));
911 std::string srcPath = validator.toString(0);
912 std::string destPath = validator.toString(1);
913 bool overwrite = validator.toBool(2);
915 JSValueRef onSuccess = validator.toFunction(3, true);
916 JSValueRef onError = validator.toFunction(4, true);
918 callback->setSuccessCallback(onSuccess);
919 callback->setErrorCallback(onError);
920 auto node = priv->getNode();
922 if (NT_DIRECTORY != node->getType()) {
923 return Utils::MainLoop<EventMovePtr>::passErrorLater(
924 JSWebAPIErrorFactory::IO_ERROR,
926 JSValueMakeUndefined(localContext),
929 auto dirNode = priv->getNode();
931 PathPtr src = Utils::fromVirtualPath(
934 PathPtr dest = Utils::fromVirtualPath(
939 // The file or directory to be moved MUST be under the Directory
940 // from which the method is invoked, otherwise the operation
941 // MUST NOT be performed.
943 // ringtones: the location for ringtones (read-only location)
944 // wgt-package: the widget package location (read-only location)
946 if (!dirNode->isSubPath(src) || !isDestinationAllowed(dest))
948 return Utils::MainLoop<EventMovePtr>::passErrorLater(
949 JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
951 JSValueMakeUndefined(localContext),
954 if ((node->getPermissions() & PERM_WRITE) == 0)
956 return Utils::MainLoop<EventMovePtr>::passErrorLater(
957 JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
958 "permission denied error",
959 JSValueMakeUndefined(localContext),
963 callback->setSource(src);
964 callback->setDestination(dest);
968 callback->setOptions(OPT_OVERWRITE);
971 Manager::getInstance().move(callback);
973 } catch(const DeviceAPI::Common::BasePlatformException& err) {
974 LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
975 if (!checkReportAsyncAPI(err.getName(),
980 LOGD("Synchronous error report for [%s]", err.getName().c_str());
981 return JSWebAPIErrorFactory::postException(localContext,
985 } catch(const WrtDeviceApis::Commons::Exception& err) {
986 LOGD("WrtDeviceApis::Commons::Exception Exception caught");
987 if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
992 return JSWebAPIErrorFactory::postException(
995 translateApi2APIErrors(std::string(err.GetClassName())),
996 std::string(err.GetMessage()));
999 LOGD("Unexpected exception caught");
1000 DeviceAPI::Common::UnknownException err(
1002 return JSWebAPIErrorFactory::postException(localContext, exception, err);
1005 return JSValueMakeUndefined(localContext);
1008 JSValueRef JSFile::createDirectory(JSContextRef context,
1010 JSObjectRef thisObject,
1012 const JSValueRef argv[],
1013 JSValueRef* exception)
1015 SET_TIME_TRACER_ITEM(0);
1019 FilePtr priv = JSFile::getPrivateObject(context, thisObject);
1021 TIZEN_CHECK_ACCESS(context, exception, priv.get(),
1022 FILESYSTEM_FUNCTION_API_CREATE_DIR);
1024 Converter converter(context);
1027 LOGW("throw InvalidValuesException");
1028 throw DeviceAPI::Common::InvalidValuesException(
1029 "Invalid path name");
1031 auto dirNode = priv->getNode();
1032 if ((dirNode->getPermissions() & PERM_WRITE) == 0)
1034 LOGW("throw SecurityException");
1035 throw DeviceAPI::Common::InvalidValuesException(
1036 "Permission denied error");
1039 PathPtr path = converter.toPath(argv[0]);
1040 NodePtr node(dirNode->createChild(path, NT_DIRECTORY, OPT_RECURSIVE));
1041 node->setPermissions(dirNode->getPermissions());
1043 FilePtr newDirPriv = FilePtr(new File(node, priv->getParentPermissions()));
1044 newDirPriv->pushParentPermissions(dirNode->getPermissions());
1045 return JSFile::makeJSObject(priv->getContext(), newDirPriv, priv.get());
1046 } catch(const DeviceAPI::Common::BasePlatformException& err) {
1047 LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
1048 return JSWebAPIErrorFactory::postException(context, exception, err);
1050 LOGD("Unexpected exception caught");
1051 DeviceAPI::Common::UnknownException err(
1053 return JSWebAPIErrorFactory::postException(context, exception, err);
1057 JSValueRef JSFile::createFile(JSContextRef context,
1059 JSObjectRef thisObject,
1061 const JSValueRef argv[],
1062 JSValueRef* exception)
1064 SET_TIME_TRACER_ITEM(0);
1068 FilePtr priv = JSFile::getPrivateObject(context, thisObject);
1070 TIZEN_CHECK_ACCESS(context, exception, priv.get(),
1071 FILESYSTEM_FUNCTION_API_CREATE_FILE);
1073 Converter converter(context);
1076 LOGW("throw InvalidValuesException");
1077 throw DeviceAPI::Common::InvalidValuesException(
1078 "Invalid path name");
1080 auto dirNode = priv->getNode();
1081 if ((dirNode->getPermissions() & PERM_WRITE) == 0)
1083 LOGW("throw SecurityException");
1084 throw DeviceAPI::Common::InvalidValuesException("Permission denied error");
1087 PathPtr path = converter.toPath(argv[0]);
1088 NodePtr node = dirNode->createChild(path, NT_FILE);
1090 FilePtr newFilePriv = FilePtr(new File(node, priv->getParentPermissions()));
1091 newFilePriv->pushParentPermissions(dirNode->getPermissions());
1092 return JSFile::makeJSObject(priv->getContext(), newFilePriv, priv.get());
1093 } catch(const DeviceAPI::Common::BasePlatformException& err) {
1094 LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught - %s: %s",
1095 err.getName().c_str(), err.getMessage().c_str());
1096 return JSWebAPIErrorFactory::postException(context, exception, err);
1098 LOGD("Unexpected exception caught");
1099 DeviceAPI::Common::UnknownException err(
1101 return JSWebAPIErrorFactory::postException(context, exception, err);
1105 JSValueRef JSFile::resolve(JSContextRef context,
1107 JSObjectRef thisObject,
1109 const JSValueRef argv[],
1110 JSValueRef* exception)
1112 SET_TIME_TRACER_ITEM(0);
1116 FilePtr priv = JSFile::getPrivateObject(context, thisObject);
1118 TIZEN_CHECK_ACCESS(context, exception, priv.get(),
1119 FILESYSTEM_FUNCTION_API_RESOLVE);
1121 if (priv->getNode()->getType() != NT_DIRECTORY) {
1122 LOGE("JSFile object is not directory.");
1123 return JSWebAPIErrorFactory::postException(
1126 JSWebAPIErrorFactory::IO_ERROR,
1130 Converter converter(context);
1133 LOGW("throw InvalidValuesException");
1134 throw DeviceAPI::Common::InvalidValuesException(
1135 "Invalid path name");
1137 auto dirNode = priv->getNode();
1138 PathPtr path = converter.toPath(argv[0]);
1139 NodePtr node = dirNode->getChild(path);
1140 node->setPermissions(dirNode->getPermissions());
1142 FilePtr resolvedPriv = FilePtr(new File(node, priv->getParentPermissions()));
1143 resolvedPriv->pushParentPermissions(dirNode->getPermissions());
1144 return JSFile::makeJSObject(priv->getContext(), resolvedPriv, priv.get());
1145 } catch(const DeviceAPI::Common::BasePlatformException& err) {
1146 LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
1147 return JSWebAPIErrorFactory::postException(context, exception, err);
1149 LOGD("Unexpected exception caught");
1150 DeviceAPI::Common::UnknownException err(
1152 return JSWebAPIErrorFactory::postException(context, exception, err);
1156 JSValueRef JSFile::deleteDirectory(JSContextRef localContext,
1158 JSObjectRef thisObject,
1160 const JSValueRef argv[],
1161 JSValueRef* exception)
1163 SET_TIME_TRACER_ITEM(0);
1166 EventRemovePtr callback;
1169 FilePtr priv = JSFile::getPrivateObject(localContext, thisObject);
1171 TIZEN_CHECK_ACCESS(localContext, exception, priv.get(),
1172 FILESYSTEM_FUNCTION_API_DELETE_DIR);
1174 auto fileNode = priv->getNode();
1177 return JSWebAPIErrorFactory::postException(
1180 JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR,
1181 "Type missmatch error");
1184 ArgumentValidator validator(localContext, argc, argv);
1185 validator.toFunction(2, true);
1188 JSValueRef reserveArguments[4];
1190 auto global = GlobalContextManager::getInstance();
1191 JSContextRef globalContext = global->getGlobalContext(localContext);
1192 callback = EventRemovePtr(new EventRemove(globalContext));
1194 for (index = 0; index < 4; index++) {
1196 reserveArguments[index] = argv[index];
1198 reserveArguments[index] = JSValueMakeUndefined(localContext);
1202 JSValueRef onSuccess = NULL;
1203 JSValueRef onError = NULL;
1205 onSuccess = getFunctionOrNull(globalContext, reserveArguments[2]);
1206 onError = getFunctionOrNull(globalContext, reserveArguments[3]);
1208 callback->setSuccessCallback(onSuccess);
1209 callback->setErrorCallback(onError);
1212 if ((fileNode->getPermissions() & PERM_WRITE) == 0)
1214 return Utils::MainLoop<EventRemovePtr>::passErrorLater(
1215 JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
1216 "permission denied error",
1217 JSValueMakeUndefined(localContext),
1221 if (fileNode->getType() != NT_DIRECTORY) {
1222 return Utils::MainLoop<EventRemovePtr>::passErrorLater(
1223 JSWebAPIErrorFactory::IO_ERROR,
1225 JSValueMakeUndefined(localContext),
1229 Converter converter(localContext);
1230 PathPtr path = Utils::fromVirtualPath(
1232 converter.toString(reserveArguments[0]));
1233 bool recursive = converter.toBool(reserveArguments[1]);
1235 if (fileNode->getPath()->getFullPath() != path->getPath()) {
1236 return Utils::MainLoop<EventRemovePtr>::passErrorLater(
1237 JSWebAPIErrorFactory::NOT_FOUND_ERROR,
1238 "not found error in current directory",
1239 JSValueMakeUndefined(localContext),
1243 if (verifyPath(callback, path, localContext, NT_DIRECTORY))
1245 return JSValueMakeUndefined(localContext);
1248 callback->setOptions(OPT_RECURSIVE);
1251 callback->setPath(path);
1253 Manager::getInstance().remove(callback);
1254 } catch(const DeviceAPI::Common::BasePlatformException& err) {
1255 LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
1256 if (!checkReportAsyncAPI(err.getName(),
1260 LOGD("Synchronous error report for [%s]", err.getName().c_str());
1261 return JSWebAPIErrorFactory::postException(localContext,
1265 } catch(const WrtDeviceApis::Commons::Exception& err) {
1266 LOGD("WrtDeviceApis::Commons::Exception Exception caught");
1267 if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
1271 return JSWebAPIErrorFactory::postException(
1274 translateApi2APIErrors(std::string(err.GetClassName())),
1275 std::string(err.GetMessage()));
1278 LOGD("Unexpected exception caught");
1279 DeviceAPI::Common::UnknownException err(
1281 return JSWebAPIErrorFactory::postException(localContext, exception, err);
1284 return JSValueMakeUndefined(localContext);
1287 JSValueRef JSFile::deleteFile(JSContextRef context,
1289 JSObjectRef thisObject,
1291 const JSValueRef argv[],
1292 JSValueRef* exception)
1294 SET_TIME_TRACER_ITEM(0);
1297 EventRemovePtr callback;
1300 FilePtr priv = JSFile::getPrivateObject(context, thisObject);
1302 TIZEN_CHECK_ACCESS(context, exception, priv.get(),
1303 FILESYSTEM_FUNCTION_API_DELETE_FILE);
1305 ArgumentValidator validator(context, argc, argv);
1306 validator.toFunction(1, true);
1307 validator.toFunction(2, true);
1310 JSValueRef reserveArguments[3];
1311 auto contextManager = GlobalContextManager::getInstance();
1312 JSContextRef globalContext = contextManager->getGlobalContext(context);
1313 callback = EventRemovePtr(new EventRemove(globalContext));
1315 for (index = 0; index < 3; index++) {
1317 reserveArguments[index] = argv[index];
1319 reserveArguments[index] = JSValueMakeUndefined(context);
1323 JSValueRef onSuccess = NULL;
1324 JSValueRef onError = NULL;
1326 onSuccess = getFunctionOrNull(globalContext, reserveArguments[1]);
1327 onError = getFunctionOrNull(globalContext, reserveArguments[2]);
1329 callback->setSuccessCallback(onSuccess);
1330 callback->setErrorCallback(onError);
1332 auto node = priv->getNode();
1333 if ((node->getPermissions() & PERM_WRITE) == 0)
1335 return Utils::MainLoop<EventRemovePtr>::passErrorLater(
1336 JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
1337 "permission denied error",
1338 JSValueMakeUndefined(context),
1342 if (node->getType() != NT_DIRECTORY) {
1343 return Utils::MainLoop<EventRemovePtr>::passErrorLater(
1344 JSWebAPIErrorFactory::IO_ERROR,
1346 JSValueMakeUndefined(context),
1351 Converter converter(context);
1352 PathPtr path = Utils::fromVirtualPath(
1354 converter.toString(reserveArguments[0]));
1356 if (*node->getPath() != path->getPath()) {
1357 return Utils::MainLoop<EventRemovePtr>::passErrorLater(
1358 JSWebAPIErrorFactory::NOT_FOUND_ERROR,
1359 "not found error in current directory",
1360 JSValueMakeUndefined(context),
1363 if (verifyPath(callback, path, context, NT_FILE))
1365 return JSValueMakeUndefined(context);
1368 LOGD("try to call async event");
1369 callback->setPath(path);
1370 Manager::getInstance().remove(callback);
1371 } catch(const DeviceAPI::Common::BasePlatformException& err) {
1372 LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
1373 if (!checkReportAsyncAPI(err.getName(),
1377 LOGD("Synchronous error report for [%s]", err.getName().c_str());
1378 return JSWebAPIErrorFactory::postException(context,
1382 } catch(const WrtDeviceApis::Commons::Exception& err) {
1383 LOGD("WrtDeviceApis::Commons::Exception Exception caught");
1384 if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
1388 return JSWebAPIErrorFactory::postException(
1391 translateApi2APIErrors(std::string(err.GetClassName())),
1392 std::string(err.GetMessage()));
1395 LOGD("Unexpected exception caught");
1396 DeviceAPI::Common::UnknownException err(
1398 return JSWebAPIErrorFactory::postException(context, exception, err);
1401 return JSValueMakeUndefined(context);
1404 } //namespace DeviceAPI
1405 } //namespace Filesystem