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 "JSFilesystemManager.h"
21 #include <dpl/log/log.h>
23 #include <Commons/Exception.h>
24 #include "EventResolve.h"
27 #include "EventGetStorage.h"
28 #include "EventListStorages.h"
29 #include "EventStorageStateChanged.h"
30 #include <CommonsJavaScript/JSCallbackManager.h>
31 #include <CommonsJavaScript/Utils.h>
32 #include <CommonsJavaScript/JSUtils.h>
33 #include <CommonsJavaScript/Validator.h>
34 #include <JSTizenExceptionFactory.h>
35 #include <JSTizenException.h>
36 #include <SecurityExceptions.h>
37 #include <Commons/WrtAccess/WrtAccess.h>
38 #include <WidgetDB/WidgetDBMgr.h>
39 #include <WidgetDB/IWidgetDB.h>
42 #include "FilesystemUtils.h"
43 #include "Converter.h"
44 #include "EventGetNodeData.h"
45 #include "plugin_config.h"
46 #include "StorageStaticController.h"
47 #include "ResponseDispatcher.h"
48 #include "FilesystemAsyncCallbackManager.h"
49 #include "FilesystemListenerManager.h"
51 using namespace WrtDeviceApis::Commons;
52 using namespace WrtDeviceApis::CommonsJavaScript;
53 using namespace DeviceAPI::Common;
54 using namespace WrtDeviceApis;
58 const char* PLUGIN_NAME = "filesystem";
59 const char* PROPERTY_MAXPATHLENGTH = "maxPathLength";
61 JSValueRef getFunctionOrNull(JSContextRef ctx, JSValueRef arg)
63 if (Validator(ctx).isCallback(arg)) {
65 } else if (!JSValueIsNull(ctx, arg) && !JSValueIsUndefined(ctx, arg)) {
66 ThrowMsg(ConversionException, "Not a function nor JS null.");
72 JSValueRef getFunction(JSContextRef ctx, JSValueRef arg)
74 if (Validator(ctx).isCallback(arg)) {
77 ThrowMsg(ConversionException, "JS null passed as function.");
86 namespace Filesystem {
88 JSClassRef JSFilesystemManager::m_classRef = 0;
90 JSClassDefinition JSFilesystemManager::m_classInfo = {
92 kJSClassAttributeNone,
110 JSStaticValue JSFilesystemManager::m_properties[] = {
111 { PROPERTY_MAXPATHLENGTH, getMaxPathLength, NULL, kJSPropertyAttributeReadOnly },
115 JSStaticFunction JSFilesystemManager::m_functions[] = {
116 { "resolve", JSFilesystemManager::resolve, kJSPropertyAttributeNone },
117 { "getStorage", JSFilesystemManager::getStorage, kJSPropertyAttributeNone },
118 { "listStorages", JSFilesystemManager::getStorageList, kJSPropertyAttributeNone },
119 { "addStorageStateChangeListener", JSFilesystemManager::addStorageStateListener, kJSPropertyAttributeNone },
120 { "removeStorageStateChangeListener", JSFilesystemManager::removeStorageStateListener, kJSPropertyAttributeNone },
124 const JSClassRef JSFilesystemManager::getClassRef()
127 m_classRef = JSClassCreate(&m_classInfo);
132 const JSClassDefinition* JSFilesystemManager::getClassInfo()
137 void JSFilesystemManager::initialize(JSContextRef context,
140 PrivateObject* privateObject = new PrivateObject(context);
141 if (!JSObjectSetPrivate(object, privateObject)) {
142 delete privateObject;
145 int widgetId = WrtAccessSingleton::Instance().getWidgetId();
146 WidgetDB::Api::IWidgetDBPtr widgetDB = WidgetDB::Api::getWidgetDB(widgetId);
148 LogDebug(widgetDB->getWidgetInstallationPath());
149 std::string wgtpackage = "wgt-package";
150 std::string wgtprivate = "wgt-private";
151 std::string wgtprivatetemp = "wgt-private-tmp";
153 IManager::getInstance().addWidgetStorage(wgtpackage, widgetDB->getWidgetInstallationPath());
154 IManager::getInstance().addWidgetStorage(wgtprivate, widgetDB->getWidgetPersistentStoragePath());
155 IManager::getInstance().addWidgetStorage(wgtprivatetemp, widgetDB->getWidgetTemporaryStoragePath());
160 void JSFilesystemManager::finalize(JSObjectRef object)
162 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(object));
164 JSObjectSetPrivate(object, NULL);
165 delete privateObject;
169 JSValueRef JSFilesystemManager::getMaxPathLength(JSContextRef context,
171 JSStringRef propertyName,
172 JSValueRef* exception)
174 ConverterPtr converter = ConverterFactory::getConverter(context);
176 return converter->toJSValueRef(IManager::getInstance().getMaxPathLength());
177 } catch (const WrtDeviceApis::Commons::ConversionException& ex) {
178 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, "IO error");
182 JSValueRef JSFilesystemManager::getStorage(JSContextRef context,
184 JSObjectRef thisObject,
186 const JSValueRef argv[],
187 JSValueRef* exception)
189 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
190 if (!privateObject) {
191 return JSValueMakeUndefined(context);
195 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
198 AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_GET_STORAGE);
199 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
202 JSContextRef globalContext = privateObject->getContext();
203 ConverterPtr converter = ConverterFactory::getConverter(globalContext);
204 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
208 JSValueRef onSuccess = getFunction(globalContext, argv[1]);
209 JSValueRef onError = NULL;
212 onError = getFunctionOrNull(globalContext, argv[2]);
215 cbm->setOnSuccess(onSuccess);
216 cbm->setOnError(onError);
218 EventGetStoragePtr event(new EventGetStorage());
219 event->setLabel(converter->toString(argv[0]));
220 event->setForAsynchronousCall(&ResponseDispatcher::getInstance());
221 event->setPrivateData(DPL::StaticPointerCast<WrtDeviceApis::Commons::IEventPrivateData > (cbm));
222 FilesystemAsyncCallbackManagerSingleton::Instance().registerCallbackManager(cbm, globalContext);
224 IManager::getInstance().getStorage(event);
226 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
227 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, ex.GetMessage());
228 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
229 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
230 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
231 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage()));
232 } catch(const WrtDeviceApis::Commons::Exception& ex) {
233 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR, ex.GetMessage()));
236 return JSValueMakeUndefined(context);
239 JSValueRef JSFilesystemManager::getStorageList(JSContextRef context,
241 JSObjectRef thisObject,
243 const JSValueRef argv[],
244 JSValueRef* exception)
246 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
247 if (!privateObject) {
248 return JSValueMakeUndefined(context);
252 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
256 AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_LIST_STORAGE);
257 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
260 JSContextRef globalContext = privateObject->getContext();
261 ConverterPtr converter = ConverterFactory::getConverter(globalContext);
262 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
266 JSValueRef onSuccess = getFunction(globalContext, argv[0]);
267 JSValueRef onError = NULL;
270 onError = getFunctionOrNull(globalContext, argv[1]);
273 cbm->setOnSuccess(onSuccess);
274 cbm->setOnError(onError);
275 cbm->setObject(thisObject);
277 EventListStoragesPtr event(new EventListStorages());
278 event->setForAsynchronousCall(&ResponseDispatcher::getInstance());
279 event->setPrivateData(DPL::StaticPointerCast<WrtDeviceApis::Commons::IEventPrivateData > (cbm));
280 FilesystemAsyncCallbackManagerSingleton::Instance().registerCallbackManager(cbm, globalContext);
283 IManager::getInstance().listStorages(event);
285 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
286 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, ex.GetMessage());
287 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
288 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
289 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
290 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage()));
291 } catch(const WrtDeviceApis::Commons::Exception& ex) {
292 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR, ex.GetMessage()));
295 return JSValueMakeUndefined(context);
298 JSValueRef JSFilesystemManager::addStorageStateListener(JSContextRef context,
300 JSObjectRef thisObject,
302 const JSValueRef argv[],
303 JSValueRef* exception)
305 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
306 if (!privateObject) {
307 return JSValueMakeUndefined(context);
311 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "TYPE_MISMATCH_ERROR");
314 AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_ADD_STORAGE_LISTENER);
315 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
317 JSContextRef globalContext = privateObject->getContext();
318 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
319 ConverterPtr converter = ConverterFactory::getConverter(globalContext);
322 JSValueRef onSuccess = getFunction(globalContext, argv[0]);
323 JSValueRef onError = NULL;
325 onError = getFunctionOrNull(globalContext, argv[1]);
328 cbm->setOnSuccess(onSuccess);
329 cbm->setOnError(onError);
331 EventStorageStateChangedEmitterPtr emitter(new EventStorageStateChangedEmitter);
332 emitter->setListener(&StorageStaticController::getInstance());
333 emitter->setEventPrivateData(DPL::StaticPointerCast<EventStorageStateChanged::PrivateDataType>(cbm));
334 long id = IManager::getInstance().addStorageStateChangeListener(emitter);
336 FilesystemListenerCancellerPtr canceller = FilesystemListenerCancellerPtr(new FilesystemListenerCanceller(globalContext, thisObject, id));
337 IListenerItemPtr listenerItem = DPL::StaticPointerCast<IListenerItem>(canceller);
338 FilesystemListenerManagerSingleton::Instance().registerListener(listenerItem, globalContext);
340 return converter->toJSValueRefLong(id);
341 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
342 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, ex.GetMessage());
343 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
344 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
345 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
346 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage()));
347 } catch(const WrtDeviceApis::Commons::Exception& ex) {
348 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR, ex.GetMessage()));
351 return JSValueMakeUndefined(context);
354 JSValueRef JSFilesystemManager::removeStorageStateListener(JSContextRef context,
356 JSObjectRef thisObject,
358 const JSValueRef argv[],
359 JSValueRef* exception)
361 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
362 if (!privateObject) {
363 return JSValueMakeUndefined(context);
367 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
370 AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_REMOVE_STORAGE_LISTENER);
371 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
373 JSContextRef globalContext = privateObject->getContext();
374 ConverterPtr converter = ConverterFactory::getConverter(globalContext);
377 long id = static_cast<long>(converter->toLong(argv[0]));
378 LogDebug("id:" << id);
382 FilesystemListenerCancellerPtr canceller = FilesystemListenerCancellerPtr(new FilesystemListenerCanceller(globalContext, thisObject, id));
383 IListenerItemPtr listenerItem = DPL::StaticPointerCast<IListenerItem>(canceller);
384 FilesystemListenerManagerSingleton::Instance().unregisterListener(listenerItem);
386 IManager::getInstance().removeStorageStateChangeListener(id);
389 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
390 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, ex.GetMessage());
391 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
392 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
393 } catch (const WrtDeviceApis::Commons::NotFoundException& ex) {
394 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_FOUND_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::Exception& ex) {
398 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, ex.GetMessage());
400 return JSValueMakeUndefined(context);
403 JSValueRef JSFilesystemManager::resolve(JSContextRef context,
405 JSObjectRef thisObject,
407 const JSValueRef argv[],
408 JSValueRef* exception)
413 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
414 if (!privateObject) {
415 return JSValueMakeUndefined(context);
419 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
422 JSContextRef globalContext = privateObject->getContext();
423 ConverterPtr converter = ConverterFactory::getConverter(globalContext);
426 JSValueRef reserveArguments[4];
427 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
431 for (index = 0; index < 4; index++) {
433 reserveArguments[index] = argv[index];
435 reserveArguments[index] = JSValueMakeUndefined(context);
437 JSValueRef onSuccess = getFunction(globalContext, reserveArguments[1]);
438 JSValueRef onError = NULL;
440 onError = getFunctionOrNull(globalContext, reserveArguments[2]);
442 cbm->setOnSuccess(onSuccess);
443 cbm->setOnError(onError);
444 cbm->setObject(thisObject);
447 std::string virtualPath;
448 path = Utils::fromVirtualPath(globalContext, converter->toString(reserveArguments[0]));
449 virtualPath = converter->toString(reserveArguments[0]);
450 LogDebug("virtualPath:[" << virtualPath << "]");
451 int permissions = PERM_READ | PERM_WRITE;
456 std::string perms = converter->toString(reserveArguments[3]);
457 LogDebug("perms:[" << perms << "]");
458 if (("r" != perms) && ("rw" != perms) && ("w" != perms) && ("a" != perms)) {
459 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Invalid permission");
460 } else if ("r" == perms) {
461 permissions = PERM_READ;
465 if (permissions & PERM_WRITE && virtualPath == "wgt-package") {
466 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::PERMISSION_DENIED_ERROR, "permission denied");
469 PermissionsAccessInfo perms(permissions, virtualPath);
470 AceSecurityStatus status = FILESYSTEM_PERMISSION_CHECK_ACCESS(
471 FILESYSTEM_FUNCTION_API_MGR_RESOLVE_ID,
474 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
476 EventGetNodeDataPtr data(new EventGetNodeData(permissions, cbm));
477 EventResolvePtr event(new EventResolve(path));
478 event->setForAsynchronousCall(&ResponseDispatcher::getInstance());
479 event->setPrivateData(DPL::StaticPointerCast<WrtDeviceApis::Commons::IEventPrivateData > (data));
480 FilesystemAsyncCallbackManagerSingleton::Instance().registerCallbackManager(cbm, globalContext);
482 IManager::getInstance().getNode(event);
484 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
485 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, ex.GetMessage());
486 } catch(const WrtDeviceApis::Commons::NotFoundException& ex) {
487 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::NOT_FOUND_ERROR, ex.GetMessage()));
488 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
489 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
490 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
491 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage()));
492 } catch(const WrtDeviceApis::Commons::Exception& ex) {
493 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR, ex.GetMessage()));
496 return JSValueMakeUndefined(context);