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);
194 AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_GET_STORAGE);
195 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
198 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
201 JSContextRef globalContext = privateObject->getContext();
202 ConverterPtr converter = ConverterFactory::getConverter(globalContext);
203 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
207 JSValueRef onSuccess = getFunction(globalContext, argv[1]);
208 JSValueRef onError = NULL;
211 onError = getFunctionOrNull(globalContext, argv[2]);
214 cbm->setOnSuccess(onSuccess);
215 cbm->setOnError(onError);
217 EventGetStoragePtr event(new EventGetStorage());
218 event->setLabel(converter->toString(argv[0]));
219 event->setForAsynchronousCall(&ResponseDispatcher::getInstance());
220 event->setPrivateData(DPL::StaticPointerCast<WrtDeviceApis::Commons::IEventPrivateData > (cbm));
221 FilesystemAsyncCallbackManagerSingleton::Instance().registerCallbackManager(cbm, globalContext);
223 IManager::getInstance().getStorage(event);
225 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
226 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, ex.GetMessage());
227 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
228 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
229 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
230 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage()));
231 } catch(const WrtDeviceApis::Commons::Exception& ex) {
232 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR, ex.GetMessage()));
235 return JSValueMakeUndefined(context);
238 JSValueRef JSFilesystemManager::getStorageList(JSContextRef context,
240 JSObjectRef thisObject,
242 const JSValueRef argv[],
243 JSValueRef* exception)
245 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
246 if (!privateObject) {
247 return JSValueMakeUndefined(context);
250 AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_LIST_STORAGE);
251 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
255 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
258 JSContextRef globalContext = privateObject->getContext();
259 ConverterPtr converter = ConverterFactory::getConverter(globalContext);
260 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
264 JSValueRef onSuccess = getFunction(globalContext, argv[0]);
265 JSValueRef onError = NULL;
268 onError = getFunctionOrNull(globalContext, argv[1]);
271 cbm->setOnSuccess(onSuccess);
272 cbm->setOnError(onError);
273 cbm->setObject(thisObject);
275 EventListStoragesPtr event(new EventListStorages());
276 event->setForAsynchronousCall(&ResponseDispatcher::getInstance());
277 event->setPrivateData(DPL::StaticPointerCast<WrtDeviceApis::Commons::IEventPrivateData > (cbm));
278 FilesystemAsyncCallbackManagerSingleton::Instance().registerCallbackManager(cbm, globalContext);
281 IManager::getInstance().listStorages(event);
283 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
284 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, ex.GetMessage());
285 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
286 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
287 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
288 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage()));
289 } catch(const WrtDeviceApis::Commons::Exception& ex) {
290 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR, ex.GetMessage()));
293 return JSValueMakeUndefined(context);
296 JSValueRef JSFilesystemManager::addStorageStateListener(JSContextRef context,
298 JSObjectRef thisObject,
300 const JSValueRef argv[],
301 JSValueRef* exception)
303 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
304 if (!privateObject) {
305 return JSValueMakeUndefined(context);
308 AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_ADD_STORAGE_LISTENER);
309 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
312 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "TYPE_MISMATCH_ERROR");
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);
366 AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_REMOVE_STORAGE_LISTENER);
367 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
370 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
375 JSContextRef globalContext = privateObject->getContext();
376 ConverterPtr converter = ConverterFactory::getConverter(globalContext);
379 long id = static_cast<long>(converter->toLong(argv[0]));
380 LogDebug("id:" << id);
384 FilesystemListenerCancellerPtr canceller = FilesystemListenerCancellerPtr(new FilesystemListenerCanceller(globalContext, thisObject, id));
385 IListenerItemPtr listenerItem = DPL::StaticPointerCast<IListenerItem>(canceller);
386 FilesystemListenerManagerSingleton::Instance().unregisterListener(listenerItem);
388 IManager::getInstance().removeStorageStateChangeListener(id);
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::NotFoundException& ex) {
396 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_FOUND_ERROR, ex.GetMessage());
397 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
398 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
399 } catch(const WrtDeviceApis::Commons::Exception& ex) {
400 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, ex.GetMessage());
402 return JSValueMakeUndefined(context);
405 JSValueRef JSFilesystemManager::resolve(JSContextRef context,
407 JSObjectRef thisObject,
409 const JSValueRef argv[],
410 JSValueRef* exception)
415 PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
416 if (!privateObject) {
417 return JSValueMakeUndefined(context);
421 AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(FILESYSTEM_FUNCTION_API_MGR_RESOLVE_ID);
422 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
425 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
428 JSContextRef globalContext = privateObject->getContext();
429 ConverterPtr converter = ConverterFactory::getConverter(globalContext);
432 JSValueRef reserveArguments[4];
433 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
439 for (index = 0; index < 4; index++) {
441 reserveArguments[index] = argv[index];
443 reserveArguments[index] = JSValueMakeUndefined(context);
445 JSValueRef onSuccess = getFunction(globalContext, reserveArguments[1]);
446 JSValueRef onError = NULL;
448 onError = getFunctionOrNull(globalContext, reserveArguments[2]);
450 cbm->setOnSuccess(onSuccess);
451 cbm->setOnError(onError);
452 cbm->setObject(thisObject);
455 std::string virtualPath;
456 path = Utils::fromVirtualPath(globalContext, converter->toString(reserveArguments[0]));
457 virtualPath = converter->toString(reserveArguments[0]);
458 LogDebug("virtualPath:[" << virtualPath << "]");
459 int permissions = PERM_READ | PERM_WRITE;
464 std::string perms = converter->toString(reserveArguments[3]);
465 LogDebug("perms:[" << perms << "]");
466 if (("r" != perms) && ("rw" != perms) && ("w" != perms) && ("a" != perms)) {
467 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Invalid permission");
468 } else if ("r" == perms) {
469 permissions = PERM_READ;
473 if (permissions & PERM_WRITE && virtualPath == "wgt-package") {
474 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::PERMISSION_DENIED_ERROR, "permission denied");
477 PermissionsAccessInfo perms(permissions, virtualPath);
478 AceSecurityStatus status = FILESYSTEM_PERMISSION_CHECK_ACCESS(
479 FILESYSTEM_FUNCTION_API_MGR_RESOLVE_ID,
482 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
484 EventGetNodeDataPtr data(new EventGetNodeData(permissions, cbm));
485 EventResolvePtr event(new EventResolve(path));
486 event->setForAsynchronousCall(&ResponseDispatcher::getInstance());
487 event->setPrivateData(DPL::StaticPointerCast<WrtDeviceApis::Commons::IEventPrivateData > (data));
488 FilesystemAsyncCallbackManagerSingleton::Instance().registerCallbackManager(cbm, globalContext);
490 IManager::getInstance().getNode(event);
492 } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
493 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, ex.GetMessage());
494 } catch(const WrtDeviceApis::Commons::NotFoundException& ex) {
495 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::NOT_FOUND_ERROR, ex.GetMessage()));
496 } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
497 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
498 } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
499 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage()));
500 } catch(const WrtDeviceApis::Commons::Exception& ex) {
501 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR, ex.GetMessage()));
504 return JSValueMakeUndefined(context);