merge wrt-plugins-tizen_0.2.0-2
[profile/ivi/wrt-plugins-tizen.git] / src / standards / Tizen / Filesystem / JSFilesystemManager.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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. 
15  */
16
17  
18 #include "JSFilesystemManager.h"
19
20 #include <dpl/log/log.h>
21
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>
36 #include <Commons/WrtWrapper/WrtWrappersMgr.h>
37 #include <WidgetDB/WidgetDBMgr.h>
38 #include <WidgetDB/IWidgetDB.h>
39
40 #include "JSFile.h"
41 #include "FilesystemUtils.h"
42 #include "Converter.h"
43 #include "EventGetNodeData.h"
44 #include "plugin_config.h"
45 #include "StorageStaticController.h"
46 #include "ResponseDispatcher.h"
47
48 using namespace WrtDeviceApis::Commons;
49 using namespace WrtDeviceApis::CommonsJavaScript;
50 using namespace TizenApis::Commons;
51 using namespace WrtDeviceApis;
52 using namespace TizenApis::Api::Filesystem;
53
54
55 namespace {
56 const char* PLUGIN_NAME = "filesystem";
57 const char* PROPERTY_MAXPATHLENGTH = "maxPathLength";
58
59 JSValueRef getFunctionOrNull(JSContextRef ctx, JSValueRef arg)
60 {
61         if (Validator(ctx).isCallback(arg)) {
62                 return arg;
63         } else if (!JSValueIsNull(ctx, arg) && !JSValueIsUndefined(ctx, arg)) {
64                 ThrowMsg(ConversionException, "Not a function nor JS null.");
65         }
66         return NULL;
67 }
68
69
70 JSValueRef getFunction(JSContextRef ctx, JSValueRef arg)
71 {
72         if (Validator(ctx).isCallback(arg)) {
73                 return arg;
74         } else if (JSValueIsNull(ctx, arg) || JSValueIsUndefined(ctx, arg)) {
75                 ThrowMsg(InvalidArgumentException, "JS null passed as function.");
76         }
77         ThrowMsg(ConversionException, "Not a function nor JS null.");
78 }
79
80 }
81
82
83
84 namespace TizenApis {
85 namespace Tizen1_0 {
86
87 JSClassRef JSFilesystemManager::m_classRef = 0;
88
89 JSClassDefinition JSFilesystemManager::m_classInfo = {
90         0,
91         kJSClassAttributeNone,
92         PLUGIN_NAME,
93         0,
94         m_properties,
95         m_functions,
96         initialize,
97         finalize,
98         NULL,
99         NULL,
100         NULL,
101         NULL,
102         NULL,
103         NULL,
104         NULL,
105         NULL,
106         NULL
107 };
108
109 JSStaticValue JSFilesystemManager::m_properties[] = {
110         { PROPERTY_MAXPATHLENGTH, getMaxPathLength, NULL, kJSPropertyAttributeReadOnly },
111         { 0, 0, 0, 0 }
112 };
113
114 JSStaticFunction JSFilesystemManager::m_functions[] = {
115         { "resolve", JSFilesystemManager::resolve, kJSPropertyAttributeNone },
116         { "getStorage", JSFilesystemManager::getStorage, kJSPropertyAttributeNone },
117         { "listStorages", JSFilesystemManager::getStorageList, kJSPropertyAttributeNone },
118         { "addStorageStateChangeListener", JSFilesystemManager::addStorageStateListener, kJSPropertyAttributeNone },
119         { "removeStorageStateChangeListener", JSFilesystemManager::removeStorageStateListener, kJSPropertyAttributeNone },
120         { 0, 0, 0 }
121 };
122
123 const JSClassRef JSFilesystemManager::getClassRef()
124 {
125         if (!m_classRef) {
126                 m_classRef = JSClassCreate(&m_classInfo);
127         }
128         return m_classRef;
129 }
130
131 const JSClassDefinition* JSFilesystemManager::getClassInfo()
132 {
133         return &m_classInfo;
134 }
135
136 void JSFilesystemManager::initialize(JSContextRef context,
137         JSObjectRef object)
138 {
139         PrivateObject* privateObject = new PrivateObject(context);
140         if (!JSObjectSetPrivate(object, privateObject)) {
141                 delete privateObject;
142         }
143         else {
144                 IWrtWrapperPtr wrt = WrtWrappersMgr::getInstance().getWrtWrapper(context);
145                 WidgetDB::Api::IWidgetDBPtr widgetDB = WidgetDB::Api::getWidgetDB(wrt->getWidgetId());
146
147                 Assert(wrt && "WrtWrapper not found, not a GLOBAL context supplied?");
148
149                 LogDebug(widgetDB->getWidgetInstallationPath());
150                 std::string wgtpackage = "wgt-package";
151                 std::string wgtprivate = "wgt-private";
152                 std::string wgtprivatetemp = "wgt-private-tmp";
153                 
154                 Api::Filesystem::IManager::getInstance().addWidgetStorage(wgtpackage, widgetDB->getWidgetInstallationPath());
155                 Api::Filesystem::IManager::getInstance().addWidgetStorage(wgtprivate, widgetDB->getWidgetPersistentStoragePath());
156                 Api::Filesystem::IManager::getInstance().addWidgetStorage(wgtprivatetemp, widgetDB->getWidgetTemporaryStoragePath());
157         
158         }
159 }
160
161 void JSFilesystemManager::finalize(JSObjectRef object)
162 {
163         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(object));
164         if (privateObject) {
165                 JSObjectSetPrivate(object, NULL);
166                 delete privateObject;
167         }
168 }
169
170 JSValueRef JSFilesystemManager::getMaxPathLength(JSContextRef context,
171                 JSObjectRef object,
172                 JSStringRef propertyName,
173                 JSValueRef* exception)
174 {
175         ConverterPtr converter = ConverterFactory::getConverter(context);
176         try {
177                 return converter->toJSValueRef(Api::Filesystem::IManager::getInstance().getMaxPathLength());
178         } catch (const WrtDeviceApis::Commons::ConversionException& ex) {
179                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, "IO error");
180         }
181         return JSValueMakeUndefined(context);
182 }
183
184 JSValueRef JSFilesystemManager::getStorage(JSContextRef context,
185                 JSObjectRef object,
186                 JSObjectRef thisObject,
187                 size_t argc,
188                 const JSValueRef argv[],
189                 JSValueRef* exception)
190 {
191         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
192         if (!privateObject) {
193                 return JSValueMakeUndefined(context);
194         }
195
196         if (argc < 2) {
197                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
198         }
199
200         JSContextRef globalContext = privateObject->getContext();
201         ConverterPtr converter = ConverterFactory::getConverter(globalContext);
202
203         try {
204
205                 JSValueRef onSuccess = getFunction(globalContext, argv[1]);
206                 JSValueRef onError = NULL;
207                 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
208                         
209                 if (argc > 2) {
210                         onError = getFunctionOrNull(globalContext, argv[2]);
211                 }
212
213                 cbm->setOnSuccess(onSuccess);
214                 cbm->setOnError(onError);
215                 
216                 if (JSValueIsNull(context, argv[0]) || JSValueIsUndefined(context, argv[0]) || !JSValueIsString(context, argv[0])) {
217                         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, "Invalid values error");
218                 }
219
220                 Api::Filesystem::EventGetStoragePtr event(new Api::Filesystem::EventGetStorage());
221                 event->setLabel(converter->toString(argv[0]));
222                 event->setForAsynchronousCall(&ResponseDispatcher::getInstance()); 
223                 event->setPrivateData(DPL::StaticPointerCast<WrtDeviceApis::Commons::IEventPrivateData > (cbm));
224
225
226                 Api::Filesystem::IManager::getInstance().getStorage(event);
227
228         } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
229                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, ex.GetMessage());
230         } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
231                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
232         } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
233                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
234         } catch(const WrtDeviceApis::Commons::Exception& ex) {
235                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, ex.GetMessage());
236         }
237
238         return JSValueMakeNull(context);
239 }
240
241 JSValueRef JSFilesystemManager::getStorageList(JSContextRef context,
242                 JSObjectRef object,
243                 JSObjectRef thisObject,
244                 size_t argc,
245                 const JSValueRef argv[],
246                 JSValueRef* exception)
247 {
248         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
249         if (!privateObject) {
250                 return JSValueMakeUndefined(context);
251         }
252
253         if (argc < 1) {
254                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
255         }
256                 
257
258         JSContextRef globalContext = privateObject->getContext();
259         ConverterPtr converter = ConverterFactory::getConverter(globalContext);
260         
261         try {
262
263                 JSValueRef onSuccess = getFunction(globalContext, argv[0]);
264                 JSValueRef onError = NULL;
265                 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
266                         
267                 if (argc > 1) {
268                         onError = getFunctionOrNull(globalContext, argv[1]);
269                 }
270
271                 cbm->setOnSuccess(onSuccess);
272                 cbm->setOnError(onError);
273                 
274
275                 Api::Filesystem::EventListStoragesPtr event(new Api::Filesystem::EventListStorages());
276                 event->setForAsynchronousCall(&ResponseDispatcher::getInstance()); 
277                 event->setPrivateData(DPL::StaticPointerCast<WrtDeviceApis::Commons::IEventPrivateData > (cbm));
278                 Api::Filesystem::IManager::getInstance().listStorages(event);
279
280         } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
281                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, ex.GetMessage());
282         } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
283                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
284         } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
285                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
286         } catch(const WrtDeviceApis::Commons::Exception& ex) {
287                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, ex.GetMessage());
288         }
289
290         return JSValueMakeNull(context);
291 }
292
293 JSValueRef JSFilesystemManager::addStorageStateListener(JSContextRef context, 
294                 JSObjectRef object,
295                 JSObjectRef thisObject,
296                 size_t argc,
297                 const JSValueRef argv[],
298                 JSValueRef* exception)
299 {
300         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
301         if (!privateObject) {
302                 return JSValueMakeUndefined(context);
303         }
304
305         if (argc < 1) {
306                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
307         }
308
309         JSContextRef globalContext = privateObject->getContext();
310         JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
311         ConverterPtr converter = ConverterFactory::getConverter(globalContext);
312
313         try {
314                 if (JSValueIsNull(context, argv[0]) || JSValueIsUndefined(context, argv[0])) {
315                         cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::INVALID_VALUES_ERROR, "Invalid values error"));
316                         return JSValueMakeNull(context);
317                 } else if (!JSObjectIsFunction(context, converter->toJSObjectRef(argv[0]))) {
318                         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
319                 }
320                 cbm->setOnSuccess(argv[0]);
321
322                 Api::Filesystem::EventStorageStateChangedEmitterPtr emitter(new Api::Filesystem::EventStorageStateChangedEmitter);
323                 emitter->setListener(&StorageStaticController::getInstance());
324                 emitter->setEventPrivateData(DPL::StaticPointerCast<Api::Filesystem::EventStorageStateChanged::PrivateDataType>(cbm));
325                 long id = Api::Filesystem::IManager::getInstance().addStorageStateChangeListener(emitter);
326                 return converter->toJSValueRefLong(id);
327         } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
328                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, ex.GetMessage());
329         } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
330                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
331         } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
332                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
333         } catch(const WrtDeviceApis::Commons::Exception& ex) {
334                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, ex.GetMessage());
335         }
336
337         return JSValueMakeUndefined(context);
338 }
339
340 JSValueRef JSFilesystemManager::removeStorageStateListener(JSContextRef context,
341                 JSObjectRef object,
342                 JSObjectRef thisObject,
343                 size_t argc,
344                 const JSValueRef argv[],
345                 JSValueRef* exception)
346 {
347         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
348         if (!privateObject) {
349                 return JSValueMakeUndefined(context);
350         }
351
352         if (argc < 1) {
353                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
354         }
355
356         if (!JSValueIsNumber(context, argv[0])) {
357                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
358         }
359
360         JSContextRef globalContext = privateObject->getContext();
361         ConverterPtr converter = ConverterFactory::getConverter(globalContext);
362         
363         try {
364                 long id = static_cast<long>(converter->toLong(argv[0]));
365
366                 if (id >= 0) {
367                         Api::Filesystem::IManager::getInstance().removeStorageStateChangeListener(id);
368                 }
369         } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
370                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, ex.GetMessage());
371         } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
372                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
373         } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
374                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
375         } catch(const WrtDeviceApis::Commons::Exception& ex) {
376                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, ex.GetMessage());
377         }
378
379         return JSValueMakeUndefined(context);
380 }
381
382 JSValueRef JSFilesystemManager::resolve(JSContextRef context,
383                 JSObjectRef object,
384                 JSObjectRef thisObject,
385                 size_t argc,
386                 const JSValueRef argv[],
387                 JSValueRef* exception)
388 {
389         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
390         if (!privateObject) {
391                 return JSValueMakeUndefined(context);
392         }
393
394         if (argc < 2) {
395                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
396         }
397
398         JSContextRef globalContext = privateObject->getContext();
399         ConverterPtr converter = ConverterFactory::getConverter(globalContext);
400         
401         try {
402
403                 JSValueRef onSuccess = getFunction(globalContext, argv[1]);
404                 JSValueRef onError = NULL;
405                 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
406                         
407                 if (argc > 2) {
408                         onError = getFunctionOrNull(globalContext, argv[2]);
409                 }
410
411                 cbm->setOnSuccess(onSuccess);
412                 cbm->setOnError(onError);
413                 
414                 Api::Filesystem::IPathPtr path = Utils::fromVirtualPath(globalContext, converter->toString(argv[0]));
415                 std::string virtualPath = converter->toString(argv[0]);
416
417                 int permissions = Api::Filesystem::PERM_READ | Api::Filesystem::PERM_WRITE;
418
419                 if (argc > 3) {
420                         if (!JSValueIsNull(context, argv[3]) && !JSValueIsUndefined(context, argv[3])) {
421                                 std::string perms = converter->toString(argv[3]);
422                                 if (("r" != perms) && ("rw" != perms) && ("w" != perms) && ("a" != perms)) {
423                                         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, "Invalid values error");
424                                 } else if ("r" == perms) {
425                                         permissions = Api::Filesystem::PERM_READ;
426                                 } 
427                         }
428                 }
429
430                 PermissionsAccessInfo perms(permissions, virtualPath);
431                 AceSecurityStatus status = FILESYSTEM_PERMISSION_CHECK_ACCESS(
432                                 privateObject->getContext(),
433                                 FILESYSTEM_FUNCTION_API_MGR_RESOLVE_ID,
434                                 perms);
435
436                 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
437
438                 EventGetNodeDataPtr data(new EventGetNodeData(permissions, cbm));
439                 Api::Filesystem::EventResolvePtr event(new Api::Filesystem::EventResolve(path));
440                 event->setForAsynchronousCall(&ResponseDispatcher::getInstance()); 
441                 event->setPrivateData(DPL::StaticPointerCast<WrtDeviceApis::Commons::IEventPrivateData > (data));
442                 Api::Filesystem::IManager::getInstance().getNode(event);
443                 
444         } catch(const WrtDeviceApis::Commons::ConversionException& ex) {
445                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::IO_ERROR, ex.GetMessage());
446         } catch(const WrtDeviceApis::Commons::NotFoundException& ex) {
447                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_FOUND_ERROR, ex.GetMessage());
448         } catch (const WrtDeviceApis::Commons::UnsupportedException& ex) {
449                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, ex.GetMessage());
450         } catch(const WrtDeviceApis::Commons::InvalidArgumentException& ex) {
451                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, ex.GetMessage());
452         } catch(const WrtDeviceApis::Commons::Exception& ex) {
453                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, ex.GetMessage());
454         }
455
456         return JSValueMakeNull(context);
457 }
458 }
459 }