Beta merge 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
37 #include "JSFile.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"
44
45 using namespace WrtDeviceApis::Commons;
46 using namespace WrtDeviceApis::CommonsJavaScript;
47 using namespace TizenApis::Commons;
48
49
50 namespace {
51 const char* PLUGIN_NAME = "filesystem";
52 const char* PROPERTY_MAXPATHLENGTH = "maxPathLength";
53
54 JSValueRef getFunctionOrNull(JSContextRef ctx, JSValueRef arg)
55 {
56         if (Validator(ctx).isCallback(arg)) {
57                 return arg;
58         } else if (!JSValueIsNull(ctx, arg) && !JSValueIsUndefined(ctx, arg)) {
59                 ThrowMsg(ConversionException, "Not a function nor JS null.");
60         }
61         return NULL;
62 }
63
64
65 JSValueRef getFunction(JSContextRef ctx, JSValueRef arg)
66 {
67         if (Validator(ctx).isCallback(arg)) {
68                 return arg;
69         } else if (JSValueIsNull(ctx, arg) || JSValueIsUndefined(ctx, arg)) {
70                 ThrowMsg(InvalidArgumentException, "JS null passed as function.");
71         }
72         ThrowMsg(ConversionException, "Not a function nor JS null.");
73 }
74
75 }
76
77
78
79 namespace TizenApis {
80 namespace Tizen1_0 {
81
82 JSClassRef JSFilesystemManager::m_classRef = 0;
83
84 JSClassDefinition JSFilesystemManager::m_classInfo = {
85         0,
86         kJSClassAttributeNone,
87         PLUGIN_NAME,
88         0,
89         m_properties,
90         m_functions,
91         initialize,
92         finalize,
93         NULL,
94         NULL,
95         NULL,
96         NULL,
97         NULL,
98         NULL,
99         NULL,
100         NULL,
101         NULL
102 };
103
104 JSStaticValue JSFilesystemManager::m_properties[] = {
105         { PROPERTY_MAXPATHLENGTH, getMaxPathLength, NULL, kJSPropertyAttributeReadOnly },
106         { 0, 0, 0, 0 }
107 };
108
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 },
115         { 0, 0, 0 }
116 };
117
118 const JSClassRef JSFilesystemManager::getClassRef()
119 {
120         if (!m_classRef) {
121                 m_classRef = JSClassCreate(&m_classInfo);
122         }
123         return m_classRef;
124 }
125
126 const JSClassDefinition* JSFilesystemManager::getClassInfo()
127 {
128         return &m_classInfo;
129 }
130
131 void JSFilesystemManager::initialize(JSContextRef context,
132         JSObjectRef object)
133 {
134         PrivateObject* privateObject = new PrivateObject(context);
135         if (!JSObjectSetPrivate(object, privateObject)) {
136                 delete privateObject;
137         }
138 }
139
140 void JSFilesystemManager::finalize(JSObjectRef object)
141 {
142         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(object));
143         if (privateObject) {
144                 JSObjectSetPrivate(object, NULL);
145                 delete privateObject;
146         }
147 }
148
149 JSValueRef JSFilesystemManager::getMaxPathLength(JSContextRef context,
150                 JSObjectRef object,
151                 JSStringRef propertyName,
152                 JSValueRef* exception)
153 {
154         ConverterPtr converter = ConverterFactory::getConverter(context);
155         try {
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");
159         }
160         return JSValueMakeUndefined(context);
161 }
162
163 JSValueRef JSFilesystemManager::getStorage(JSContextRef context,
164                 JSObjectRef object,
165                 JSObjectRef thisObject,
166                 size_t argc,
167                 const JSValueRef argv[],
168                 JSValueRef* exception)
169 {
170         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
171         if (!privateObject) {
172                 return JSValueMakeUndefined(context);
173         }
174
175         if (argc < 2) {
176                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
177         }
178
179         JSContextRef globalContext = privateObject->getContext();
180         ConverterPtr converter = ConverterFactory::getConverter(globalContext);
181
182         try {
183
184                 JSValueRef onSuccess = getFunction(globalContext, argv[1]);
185                 JSValueRef onError = NULL;
186                 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
187                         
188                 if (argc > 2) {
189                         onError = getFunctionOrNull(globalContext, argv[2]);
190                 }
191
192                 cbm->setOnSuccess(onSuccess);
193                 cbm->setOnError(onError);
194                 
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");
197                 }
198
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));
203
204
205                 Api::Filesystem::IManager::getInstance().getStorage(event);
206
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());
215         }
216
217         return JSValueMakeNull(context);
218 }
219
220 JSValueRef JSFilesystemManager::getStorageList(JSContextRef context,
221                 JSObjectRef object,
222                 JSObjectRef thisObject,
223                 size_t argc,
224                 const JSValueRef argv[],
225                 JSValueRef* exception)
226 {
227         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
228         if (!privateObject) {
229                 return JSValueMakeUndefined(context);
230         }
231
232         if (argc < 1) {
233                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
234         }
235                 
236
237         JSContextRef globalContext = privateObject->getContext();
238         ConverterPtr converter = ConverterFactory::getConverter(globalContext);
239         
240         try {
241
242                 JSValueRef onSuccess = getFunction(globalContext, argv[0]);
243                 JSValueRef onError = NULL;
244                 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
245                         
246                 if (argc > 1) {
247                         onError = getFunctionOrNull(globalContext, argv[1]);
248                 }
249
250                 cbm->setOnSuccess(onSuccess);
251                 cbm->setOnError(onError);
252                 
253
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);
258
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());
267         }
268
269         return JSValueMakeNull(context);
270 }
271
272 JSValueRef JSFilesystemManager::addStorageStateListener(JSContextRef context, 
273                 JSObjectRef object,
274                 JSObjectRef thisObject,
275                 size_t argc,
276                 const JSValueRef argv[],
277                 JSValueRef* exception)
278 {
279         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
280         if (!privateObject) {
281                 return JSValueMakeUndefined(context);
282         }
283
284         if (argc < 1) {
285                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
286         }
287
288         JSContextRef globalContext = privateObject->getContext();
289         JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
290         ConverterPtr converter = ConverterFactory::getConverter(globalContext);
291
292         try {
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");
298                 }
299                 cbm->setOnSuccess(argv[0]);
300
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());
314         }
315
316         return JSValueMakeUndefined(context);
317 }
318
319 JSValueRef JSFilesystemManager::removeStorageStateListener(JSContextRef context,
320                 JSObjectRef object,
321                 JSObjectRef thisObject,
322                 size_t argc,
323                 const JSValueRef argv[],
324                 JSValueRef* exception)
325 {
326         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
327         if (!privateObject) {
328                 return JSValueMakeUndefined(context);
329         }
330
331         if (argc < 1) {
332                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
333         }
334
335         if (!JSValueIsNumber(context, argv[0])) {
336                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
337         }
338
339         JSContextRef globalContext = privateObject->getContext();
340         ConverterPtr converter = ConverterFactory::getConverter(globalContext);
341         
342         try {
343                 long id = static_cast<long>(converter->toLong(argv[0]));
344
345                 if (id >= 0) {
346                         Api::Filesystem::IManager::getInstance().removeStorageStateChangeListener(id);
347                 }
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());
356         }
357
358         return JSValueMakeUndefined(context);
359 }
360
361 JSValueRef JSFilesystemManager::resolve(JSContextRef context,
362                 JSObjectRef object,
363                 JSObjectRef thisObject,
364                 size_t argc,
365                 const JSValueRef argv[],
366                 JSValueRef* exception)
367 {
368         PrivateObject* privateObject = static_cast<PrivateObject*>(JSObjectGetPrivate(thisObject));
369         if (!privateObject) {
370                 return JSValueMakeUndefined(context);
371         }
372
373         if (argc < 2) {
374                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type missmatch error");
375         }
376
377         JSContextRef globalContext = privateObject->getContext();
378         ConverterPtr converter = ConverterFactory::getConverter(globalContext);
379         
380         try {
381
382                 JSValueRef onSuccess = getFunction(globalContext, argv[1]);
383                 JSValueRef onError = NULL;
384                 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
385                         
386                 if (argc > 2) {
387                         onError = getFunctionOrNull(globalContext, argv[2]);
388                 }
389
390                 cbm->setOnSuccess(onSuccess);
391                 cbm->setOnError(onError);
392                 
393                 Api::Filesystem::IPathPtr path = Utils::fromVirtualPath(globalContext, converter->toString(argv[0]));
394                 std::string virtualPath = converter->toString(argv[0]);
395
396                 int permissions = Api::Filesystem::PERM_READ | Api::Filesystem::PERM_WRITE;
397
398                 if (argc > 3) {
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;
405                                 } 
406                         }
407                 }
408
409                 PermissionsAccessInfo perms(permissions, virtualPath);
410                 AceSecurityStatus status = FILESYSTEM_PERMISSION_CHECK_ACCESS(
411                                 privateObject->getContext(),
412                                 FILESYSTEM_FUNCTION_API_MGR_RESOLVE_ID,
413                                 perms);
414
415                 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
416
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);
422                 
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());
433         }
434
435         return JSValueMakeNull(context);
436 }
437 }
438 }