2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "JSFilesystemManager.h"
20 #include <dpl/log/log.h>
22 #include <Commons/Exception.h>
23 #include <API/Filesystem/EventResolve.h>
24 #include <API/Filesystem/IManager.h>
25 #include <API/Filesystem/IPath.h>
26 #include <API/Filesystem/EventGetStorage.h>
27 #include <API/Filesystem/EventListStorages.h>
28 #include <API/Filesystem/EventStorageStateChanged.h>
29 #include <CommonsJavaScript/JSCallbackManager.h>
30 #include <CommonsJavaScript/Utils.h>
31 #include <CommonsJavaScript/JSUtils.h>
32 #include <CommonsJavaScript/Validator.h>
33 #include <Tizen/Common/JSTizenExceptionFactory.h>
34 #include <Tizen/Common/JSTizenException.h>
35 #include <Tizen/Common/SecurityExceptions.h>
38 #include "FilesystemUtils.h"
39 #include "Converter.h"
40 #include "EventGetNodeData.h"
41 #include "plugin_config.h"
42 #include "StorageStaticController.h"
43 #include "ResponseDispatcher.h"
45 using namespace WrtDeviceApis::Commons;
46 using namespace WrtDeviceApis::CommonsJavaScript;
47 using namespace TizenApis::Commons;
51 const char* PLUGIN_NAME = "filesystem";
52 const char* PROPERTY_MAXPATHLENGTH = "maxPathLength";
54 JSValueRef getFunctionOrNull(JSContextRef ctx, JSValueRef arg)
56 if (Validator(ctx).isCallback(arg)) {
58 } else if (!JSValueIsNull(ctx, arg) && !JSValueIsUndefined(ctx, arg)) {
59 ThrowMsg(ConversionException, "Not a function nor JS null.");
65 JSValueRef getFunction(JSContextRef ctx, JSValueRef arg)
67 if (Validator(ctx).isCallback(arg)) {
69 } else if (JSValueIsNull(ctx, arg) || JSValueIsUndefined(ctx, arg)) {
70 ThrowMsg(InvalidArgumentException, "JS null passed as function.");
72 ThrowMsg(ConversionException, "Not a function nor JS null.");
82 JSClassRef JSFilesystemManager::m_classRef = 0;
84 JSClassDefinition JSFilesystemManager::m_classInfo = {
86 kJSClassAttributeNone,
104 JSStaticValue JSFilesystemManager::m_properties[] = {
105 { PROPERTY_MAXPATHLENGTH, getMaxPathLength, NULL, kJSPropertyAttributeReadOnly },
109 JSStaticFunction JSFilesystemManager::m_functions[] = {
110 { "resolve", JSFilesystemManager::resolve, kJSPropertyAttributeNone },
111 { "getStorage", JSFilesystemManager::getStorage, kJSPropertyAttributeNone },
112 { "listStorages", JSFilesystemManager::getStorageList, kJSPropertyAttributeNone },
113 { "addStorageStateChangeListener", JSFilesystemManager::addStorageStateListener, kJSPropertyAttributeNone },
114 { "removeStorageStateChangeListener", JSFilesystemManager::removeStorageStateListener, kJSPropertyAttributeNone },
118 const JSClassRef JSFilesystemManager::getClassRef()
121 m_classRef = JSClassCreate(&m_classInfo);
126 const JSClassDefinition* JSFilesystemManager::getClassInfo()
131 void JSFilesystemManager::initialize(JSContextRef context,
134 PrivateObject* privateObject = new PrivateObject(context);
135 if (!JSObjectSetPrivate(object, privateObject)) {
136 delete privateObject;
140 void JSFilesystemManager::finalize(JSObjectRef object)
142 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(object));
144 JSObjectSetPrivate(object, NULL);
145 delete privateObject;
149 JSValueRef JSFilesystemManager::getMaxPathLength(JSContextRef context,
151 JSStringRef propertyName,
152 JSValueRef* exception)
154 ConverterPtr converter = ConverterFactory::getConverter(context);
156 return converter->toJSValueRef(Api::Filesystem::IManager::getInstance().getMaxPathLength());
157 } catch (const WrtDeviceApis::Commons::ConversionException& ex) {
158 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, "IO error");
160 return JSValueMakeUndefined(context);
163 JSValueRef JSFilesystemManager::getStorage(JSContextRef context,
165 JSObjectRef thisObject,
167 const JSValueRef argv[],
168 JSValueRef* exception)
170 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
171 if (!privateObject) {
172 return JSValueMakeUndefined(context);
176 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
179 JSContextRef globalContext = privateObject->getContext();
180 ConverterPtr converter = ConverterFactory::getConverter(globalContext);
184 JSValueRef onSuccess = getFunction(globalContext, argv[1]);
185 JSValueRef onError = NULL;
186 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
189 onError = getFunctionOrNull(globalContext, argv[2]);
192 cbm->setOnSuccess(onSuccess);
193 cbm->setOnError(onError);
195 if (JSValueIsNull(context, argv[0]) || JSValueIsUndefined(context, argv[0]) || !JSValueIsString(context, argv[0])) {
196 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, "Invalid values error");
199 Api::Filesystem::EventGetStoragePtr event(new Api::Filesystem::EventGetStorage());
200 event->setLabel(converter->toString(argv[0]));
201 event->setForAsynchronousCall(&ResponseDispatcher::getInstance());
202 event->setPrivateData(DPL::StaticPointerCast<WrtDeviceApis::Commons::IEventPrivateData > (cbm));
205 Api::Filesystem::IManager::getInstance().getStorage(event);
207 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
208 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, ex.GetMessage());
209 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
210 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
211 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
212 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
213 } catch(const WrtDeviceApis::Commons::Exception& ex) {
214 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, ex.GetMessage());
217 return JSValueMakeNull(context);
220 JSValueRef JSFilesystemManager::getStorageList(JSContextRef context,
222 JSObjectRef thisObject,
224 const JSValueRef argv[],
225 JSValueRef* exception)
227 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
228 if (!privateObject) {
229 return JSValueMakeUndefined(context);
233 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
237 JSContextRef globalContext = privateObject->getContext();
238 ConverterPtr converter = ConverterFactory::getConverter(globalContext);
242 JSValueRef onSuccess = getFunction(globalContext, argv[0]);
243 JSValueRef onError = NULL;
244 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
247 onError = getFunctionOrNull(globalContext, argv[1]);
250 cbm->setOnSuccess(onSuccess);
251 cbm->setOnError(onError);
254 Api::Filesystem::EventListStoragesPtr event(new Api::Filesystem::EventListStorages());
255 event->setForAsynchronousCall(&ResponseDispatcher::getInstance());
256 event->setPrivateData(DPL::StaticPointerCast<WrtDeviceApis::Commons::IEventPrivateData > (cbm));
257 Api::Filesystem::IManager::getInstance().listStorages(event);
259 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
260 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, ex.GetMessage());
261 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
262 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
263 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
264 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
265 } catch(const WrtDeviceApis::Commons::Exception& ex) {
266 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, ex.GetMessage());
269 return JSValueMakeNull(context);
272 JSValueRef JSFilesystemManager::addStorageStateListener(JSContextRef context,
274 JSObjectRef thisObject,
276 const JSValueRef argv[],
277 JSValueRef* exception)
279 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
280 if (!privateObject) {
281 return JSValueMakeUndefined(context);
285 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
288 JSContextRef globalContext = privateObject->getContext();
289 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
290 ConverterPtr converter = ConverterFactory::getConverter(globalContext);
293 if (JSValueIsNull(context, argv[0]) || JSValueIsUndefined(context, argv[0])) {
294 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::INVALID_VALUES_ERROR, "Invalid values error"));
295 return JSValueMakeNull(context);
296 } else if (!JSObjectIsFunction(context, converter->toJSObjectRef(argv[0]))) {
297 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
299 cbm->setOnSuccess(argv[0]);
301 Api::Filesystem::EventStorageStateChangedEmitterPtr emitter(new Api::Filesystem::EventStorageStateChangedEmitter);
302 emitter->setListener(&StorageStaticController::getInstance());
303 emitter->setEventPrivateData(DPL::StaticPointerCast<Api::Filesystem::EventStorageStateChanged::PrivateDataType>(cbm));
304 long id = Api::Filesystem::IManager::getInstance().addStorageStateChangeListener(emitter);
305 return converter->toJSValueRefLong(id);
306 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
307 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_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::Exception& ex) {
313 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, ex.GetMessage());
316 return JSValueMakeUndefined(context);
319 JSValueRef JSFilesystemManager::removeStorageStateListener(JSContextRef context,
321 JSObjectRef thisObject,
323 const JSValueRef argv[],
324 JSValueRef* exception)
326 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
327 if (!privateObject) {
328 return JSValueMakeUndefined(context);
332 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
335 if (!JSValueIsNumber(context, argv[0])) {
336 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
339 JSContextRef globalContext = privateObject->getContext();
340 ConverterPtr converter = ConverterFactory::getConverter(globalContext);
343 long id = static_cast<long>(converter->toLong(argv[0]));
346 Api::Filesystem::IManager::getInstance().removeStorageStateChangeListener(id);
348 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
349 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, ex.GetMessage());
350 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
351 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
352 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
353 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
354 } catch(const WrtDeviceApis::Commons::Exception& ex) {
355 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, ex.GetMessage());
358 return JSValueMakeUndefined(context);
361 JSValueRef JSFilesystemManager::resolve(JSContextRef context,
363 JSObjectRef thisObject,
365 const JSValueRef argv[],
366 JSValueRef* exception)
368 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
369 if (!privateObject) {
370 return JSValueMakeUndefined(context);
374 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
377 JSContextRef globalContext = privateObject->getContext();
378 ConverterPtr converter = ConverterFactory::getConverter(globalContext);
382 JSValueRef onSuccess = getFunction(globalContext, argv[1]);
383 JSValueRef onError = NULL;
384 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
387 onError = getFunctionOrNull(globalContext, argv[2]);
390 cbm->setOnSuccess(onSuccess);
391 cbm->setOnError(onError);
393 Api::Filesystem::IPathPtr path = Utils::fromVirtualPath(globalContext, converter->toString(argv[0]));
394 std::string virtualPath = converter->toString(argv[0]);
396 int permissions = Api::Filesystem::PERM_READ | Api::Filesystem::PERM_WRITE;
399 if (!JSValueIsNull(context, argv[3]) && !JSValueIsUndefined(context, argv[3])) {
400 std::string perms = converter->toString(argv[3]);
401 if (("r" != perms) && ("rw" != perms) && ("w" != perms) && ("a" != perms)) {
402 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, "Invalid values error");
403 } else if ("r" == perms) {
404 permissions = Api::Filesystem::PERM_READ;
409 PermissionsAccessInfo perms(permissions, virtualPath);
410 AceSecurityStatus status = FILESYSTEM_PERMISSION_CHECK_ACCESS(
411 privateObject->getContext(),
412 FILESYSTEM_FUNCTION_API_MGR_RESOLVE_ID,
415 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
417 EventGetNodeDataPtr data(new EventGetNodeData(permissions, cbm));
418 Api::Filesystem::EventResolvePtr event(new Api::Filesystem::EventResolve(path));
419 event->setForAsynchronousCall(&ResponseDispatcher::getInstance());
420 event->setPrivateData(DPL::StaticPointerCast<WrtDeviceApis::Commons::IEventPrivateData > (data));
421 Api::Filesystem::IManager::getInstance().getNode(event);
423 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
424 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, ex.GetMessage());
425 } catch(const WrtDeviceApis::Commons::NotFoundException& ex) {
426 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_FOUND_ERROR, ex.GetMessage());
427 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
428 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
429 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
430 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
431 } catch(const WrtDeviceApis::Commons::Exception& ex) {
432 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, ex.GetMessage());
435 return JSValueMakeNull(context);