Update change log and spec for wrt-plugins-tizen_0.4.70
[framework/web/wrt-plugins-tizen.git] / src / NFC / JSNFCTag.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 #include <CommonsJavaScript/Validator.h>
18 #include <Commons/Exception.h>
19 #include <CommonsJavaScript/PrivateObject.h>
20 #include <CommonsJavaScript/JSUtils.h>
21 #include <CommonsJavaScript/JSCallbackManager.h>
22 #include <CommonsJavaScript/Utils.h>
23 #include <JSWebAPIErrorFactory.h>
24 #include <SecurityExceptions.h>
25 #include <ArgumentValidator.h>
26 #include <GlobalContextManager.h>
27 #include <PlatformException.h>
28
29 #include "JSNFCTag.h"
30 #include "JSNdefMessage.h"
31 #include "JSNFCManager.h"
32 #include "NFCConverter.h"
33 #include "ResponseDispatcher.h"
34 #include "NFCFactory.h"
35 #include "EventTagAction.h"
36 #include "NFCAsyncCallbackManager.h"
37 #include "plugin_config_impl.h"
38 #include <Logger.h>
39
40 using namespace DeviceAPI::Common;
41 using namespace WrtDeviceApis::Commons;
42 using namespace WrtDeviceApis::CommonsJavaScript;
43
44
45 #define TIZEN_NFCTAG_ATTRIBUTENAME "NFCTag"
46
47 #define TIZEN_NFCTAG_TYPE "type"
48 #define TIZEN_NFCTAG_ISSUPPORTEDNDEF "isSupportedNDEF"
49 #define TIZEN_NFCTAG_NDEFSIZE "ndefSize"
50 #define TIZEN_NFCTAG_PROPERTIES "properties"
51 #define TIZEN_NFCTAG_ISCONNECTED "isConnected"
52
53 namespace DeviceAPI {
54 namespace NFC {
55
56  JSClassDefinition JSNFCTag::m_classInfo =
57 {
58     0,
59     kJSClassAttributeNone,
60     TIZEN_NFCTAG_ATTRIBUTENAME,
61     0,
62     m_property,
63     m_function,
64     initialize,
65     finalize,
66     NULL, //hasProperty,
67     NULL,
68     NULL, //setProperty,
69     NULL, //DeleteProperty,
70     NULL, //GetPropertyNames,
71     NULL, //CallAsFunction,
72     NULL, //CallAsConstructor,
73     hasInstance, //HasInstance,
74     NULL  //ConvertToType
75 };
76
77 JSStaticValue JSNFCTag::m_property[] =
78 {
79     //NFCTagProperties
80     { TIZEN_NFCTAG_TYPE, getProperty, 
81             NULL, kJSPropertyAttributeReadOnly},
82     { TIZEN_NFCTAG_ISSUPPORTEDNDEF, getProperty, 
83             NULL, kJSPropertyAttributeReadOnly},
84     { TIZEN_NFCTAG_NDEFSIZE, getProperty, 
85             NULL, kJSPropertyAttributeReadOnly},
86     { TIZEN_NFCTAG_PROPERTIES, getProperty, 
87             NULL, kJSPropertyAttributeReadOnly},
88     { TIZEN_NFCTAG_ISCONNECTED, getProperty, 
89             NULL, kJSPropertyAttributeReadOnly},
90     { 0, 0, 0, 0 }
91 };
92
93 JSStaticFunction JSNFCTag::m_function[] = {
94     {"readNDEF", JSNFCTag::readNDEF, kJSPropertyAttributeNone},
95     {"writeNDEF", JSNFCTag::writeNDEF, kJSPropertyAttributeNone},
96     {"transceive", JSNFCTag::transceive, kJSPropertyAttributeNone},
97     { 0, 0, 0}
98 };
99
100 JSClassRef JSNFCTag::m_jsClassRef = JSClassCreate(JSNFCTag::getClassInfo());
101
102 JSObjectRef JSNFCTag::createJSObject(JSContextRef context, void *tagHandle, EventNFCChangedPrivateDataPtr eventNFCChangedPriv) {
103         LoggerD("entered");
104
105         INFCTagPtr nfcTag = NFCFactory::getInstance().createNFCTagObject(tagHandle);
106         
107         NFCTagPrivObject *priv = new NFCTagPrivObject(context, nfcTag);
108
109         if (!priv) {
110                 ThrowMsg(NullPointerException, "Can not new a NFCTag object");
111         }
112
113         priv->copyAceCheckAccessFunction(eventNFCChangedPriv.Get());
114         return JSObjectMake(context, getClassRef(), priv);
115 }
116
117 void JSNFCTag::initialize(JSContextRef context, JSObjectRef object)
118 {
119 }
120
121 void JSNFCTag::finalize(JSObjectRef object)
122 {
123         LoggerD( "entered" );
124         NFCTagPrivObject *priv = static_cast<NFCTagPrivObject*>( JSObjectGetPrivate( object ) ) ;
125         JSObjectSetPrivate(object, NULL);
126         LoggerD("Deleting NFCTag object");
127         delete priv;
128 }
129
130
131 const JSClassRef JSNFCTag::getClassRef()
132 {
133         if (!m_jsClassRef) {
134                 m_jsClassRef = JSClassCreate(&m_classInfo);
135         }
136         return m_jsClassRef;
137 }
138
139 const JSClassDefinition* JSNFCTag::getClassInfo()
140 {
141         return &m_classInfo;
142 }
143
144 JSValueRef JSNFCTag::getProperty(JSContextRef context, JSObjectRef object,
145         JSStringRef propertyName, JSValueRef* exception)
146 {
147         LoggerD("Enter");
148
149         Try     {
150                 NFCTagPrivObject* privateObject = static_cast<NFCTagPrivObject*>(JSObjectGetPrivate(object));
151                 if (!privateObject) {
152                         LoggerE("Private object is not set.");
153                         ThrowMsg(NullPointerException, "Private object not initialized");
154                 }
155
156                 INFCTagPtr nfcTag(privateObject->getObject());
157                 NFCConverter convert(context);
158
159                 LoggerD("propertyName : " << convert.toString(propertyName));
160                 if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_NFCTAG_TYPE)) {
161                         return convert.toJSValueRef(convert.toNfcTagTypeString(nfcTag->getTagType()));
162                 } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_NFCTAG_ISSUPPORTEDNDEF)) {
163                         return convert.toJSValueRef(nfcTag->isNDEFSupport());
164                 } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_NFCTAG_NDEFSIZE)) {
165                         return convert.toJSValueRefLong(nfcTag->getNdefSize());
166                 } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_NFCTAG_PROPERTIES)) {
167                         LoggerD("get Properties");
168                         return convert.toJSValueRef(nfcTag->getProperties());
169                 } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_NFCTAG_ISCONNECTED)) {
170                         return convert.toJSValueRef(nfcTag->isConnected());
171                 }
172         } Catch (NullPointerException) {
173                 LoggerE("NullPointerException: " << _rethrown_exception.GetMessage());
174         } Catch (ConversionException) {
175                 LoggerE("ConversionException: " << _rethrown_exception.GetMessage());
176         } Catch (WrtDeviceApis::Commons::UnknownException) {
177                 LoggerE("UnknownExceptionException: " << _rethrown_exception.GetMessage());
178         } Catch (PlatformException) {
179                 LoggerE("PlatformExceptionException: " << _rethrown_exception.GetMessage());
180         } Catch (WrtDeviceApis::Commons::Exception) {
181                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
182         }
183         return JSValueMakeUndefined(context);
184 }
185
186 bool JSNFCTag::hasInstance(JSContextRef context,
187         JSObjectRef constructor,
188         JSValueRef possibleInstance,
189         JSValueRef* exception)
190 {
191     return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
192 }
193
194 JSValueRef JSNFCTag::readNDEF(JSContextRef context,
195         JSObjectRef object,
196         JSObjectRef thisObject,
197         size_t argumentCount,
198         const JSValueRef arguments[],
199         JSValueRef* exception)
200 {
201         LoggerD("Entered ");
202
203         NFCTagPrivObject* privateObject = static_cast<NFCTagPrivObject*>(JSObjectGetPrivate(thisObject));
204         if (NULL == privateObject) {
205                 LoggerE("private object is null");
206                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
207         }
208
209         TIZEN_CHECK_ACCESS(context, exception, privateObject,
210         NFC_FUNCTION_API_TAG_FUNCS);
211
212         JSContextRef global_context = GlobalContextManager::getInstance()->getGlobalContext(context);
213     JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(global_context, NULL, NULL, true, true);
214
215         Try {
216                 ArgumentValidator validator(context, argumentCount, arguments);
217
218                 // successCallback
219                 if (validator.toFunction(0))
220                         callbackManager->setOnSuccess(arguments[0]);
221                 // errorCallback
222                 if (validator.toFunction(1, true))
223                         callbackManager->setOnError(arguments[1]);
224
225                 EventTagActionReadPtr event(new EventTagActionRead());
226                 event->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager) );
227                 event->setForAsynchronousCall(&NFCResponseDispatcher::getInstance());
228                 callbackManager->setObject(thisObject);
229                 INFCTagPtr nfcTag(privateObject->getObject());
230                 nfcTag->readNdef(event);
231                 NFCAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, global_context);
232                 return JSValueMakeUndefined(context);
233     } Catch (BasePlatformException) {
234         LoggerE(_rethrown_exception.getName() << ": " << _rethrown_exception.getMessage());
235         return JSWebAPIErrorFactory::postException(context, exception, _rethrown_exception);
236         } Catch (ConversionException) {
237                 LoggerE("readNDEF : ConversionException");
238                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
239         } Catch (UnsupportedException) {
240                 LoggerE("UnsupportedException: " << _rethrown_exception.GetMessage());
241                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, "Not Support NDEF");
242         } Catch (InvalidArgumentException) {
243                 LoggerE("readNDEF InvalidArgumentException");
244                 callbackManager->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid Values"));
245                 return JSValueMakeUndefined(context);
246         } Catch (PlatformException) {
247                 LoggerE("PlatformException: " << _rethrown_exception.GetMessage());
248                 callbackManager->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, "Service Not Available"));
249                 return JSValueMakeUndefined(context);
250         } Catch (WrtDeviceApis::Commons::UnknownException) {
251                 LoggerE("UnknownException: " << _rethrown_exception.GetMessage());
252         } Catch (WrtDeviceApis::Commons::Exception) {
253                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
254         }
255
256         callbackManager->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::UNKNOWN_ERROR,"Unknown Error"));
257         return JSValueMakeUndefined(context);
258 }
259
260 JSValueRef JSNFCTag::writeNDEF(JSContextRef context,
261         JSObjectRef object,
262         JSObjectRef thisObject,
263         size_t argumentCount,
264         const JSValueRef arguments[],
265         JSValueRef* exception)
266 {
267         LoggerD("Entered ");
268
269         NFCTagPrivObject* privateObject = static_cast<NFCTagPrivObject*>(JSObjectGetPrivate(thisObject));
270         if (NULL == privateObject) {
271                 LoggerE("private object is null");
272                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
273         }
274
275         TIZEN_CHECK_ACCESS(context, exception, privateObject,
276         NFC_FUNCTION_API_TAG_FUNCS);
277
278         JSContextRef global_context = GlobalContextManager::getInstance()->getGlobalContext(context);
279         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(global_context, NULL, NULL, true, true);
280         Try {
281                 ArgumentValidator validator(context, argumentCount, arguments);
282
283                 // ndefMessage
284                 JSObjectRef ndefMessageObj = validator.toObject(0, JSNdefMessage::getClassRef(), false);
285                 // successCallback
286                 if (validator.toFunction(1, true))
287                         callbackManager->setOnSuccess(arguments[1]);
288                 // errorCallback
289                 if (validator.toFunction(2, true))
290                         callbackManager->setOnError(arguments[2]);
291
292                 EventTagActionWritePtr event(new EventTagActionWrite());
293                 void *messageHandle = NULL;
294                 try {
295                         NdefMessagePrivObject* ndefMessagePrivateObj = static_cast<NdefMessagePrivObject*>(JSObjectGetPrivate(ndefMessageObj));
296                         if (!ndefMessagePrivateObj) {
297                                 LogError("NDEF Message Private object is not set.");
298                                 ThrowMsg(ConversionException, "Private object is not set");
299                         }
300                         INdefMessagePtr ndefMessage(ndefMessagePrivateObj->getObject());
301                         JSValueRef recordsValue = (ndefMessage->mLocalProperty).getProperty(global_context, TIZEN_NDEFMESSAGE_RECORDS);
302                         NFCConverter convert(global_context);
303                         std::vector<void *> records = convert.toVectorOfRecordHandles(recordsValue);
304                         messageHandle = ndefMessage->makeNdefMessageHandle(records);
305                 } catch (WrtDeviceApis::Commons::Exception& err) {
306                         LoggerE(err.GetClassName() << ":"<<err.GetMessage());
307                         ThrowMsg(InvalidArgumentException, "Invalid NDEF Message");
308                 }
309                 if (messageHandle == NULL)
310                         ThrowMsg(InvalidArgumentException, "Invalid NDEF Message");
311         
312                 event->writeNdef(messageHandle);
313                 event->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager));
314                 event->setForAsynchronousCall(&NFCResponseDispatcher::getInstance());
315                 callbackManager->setObject(thisObject);
316                 INFCTagPtr nfcTag(privateObject->getObject());
317                 nfcTag->writeNdef(event);
318                 NFCAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, global_context);
319                 return JSValueMakeUndefined(context);
320     } Catch (BasePlatformException) {
321         LoggerE(_rethrown_exception.getName() << ": " << _rethrown_exception.getMessage());
322         return JSWebAPIErrorFactory::postException(context, exception, _rethrown_exception);
323         } Catch (ConversionException) {
324                 LoggerE("writeNDEF : ConversionException");
325                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
326         } Catch (UnsupportedException) {
327                 LoggerE("UnsupportedException: " << _rethrown_exception.GetMessage());
328                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, "Not Support NDEF");
329         } Catch (InvalidArgumentException) {
330                 LoggerE("writeNDEF InvalidArgumentException");
331                 callbackManager->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage()));
332                 return JSValueMakeUndefined(context);
333         } Catch (PlatformException) {
334                 LoggerE("PlatformException: " << _rethrown_exception.GetMessage());
335                 callbackManager->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, "Service Not Available"));
336                 return JSValueMakeUndefined(context);
337         } Catch (WrtDeviceApis::Commons::UnknownException) {
338                 LoggerE("UnknownException: " << _rethrown_exception.GetMessage());
339         } Catch (WrtDeviceApis::Commons::Exception) {
340                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
341         }
342
343         callbackManager->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::UNKNOWN_ERROR,"Unknown Error"));
344         return JSValueMakeUndefined(context);
345 }
346
347 JSValueRef JSNFCTag::transceive(JSContextRef context,
348         JSObjectRef object,
349         JSObjectRef thisObject,
350         size_t argumentCount,
351         const JSValueRef arguments[],
352         JSValueRef* exception)
353 {
354         LoggerD("Entered ");
355
356         NFCTagPrivObject* privateObject = static_cast<NFCTagPrivObject*>(JSObjectGetPrivate(thisObject));
357         if (NULL == privateObject) {
358                 LoggerE("private object is null");
359                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
360         }
361
362         TIZEN_CHECK_ACCESS(context, exception, privateObject,
363         NFC_FUNCTION_API_TAG_FUNCS);
364
365         JSContextRef global_context = GlobalContextManager::getInstance()->getGlobalContext(context);
366         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(global_context, NULL, NULL, true, true);
367         Try {
368                 ArgumentValidator validator(context, argumentCount, arguments);
369
370                 // ndefMessage
371                 JSObjectRef dataObj = validator.toArrayObject(0);
372                 
373                 // successCallback
374                 if (validator.toFunction(1))
375                         callbackManager->setOnSuccess(arguments[1]);
376                 // errorCallback
377                 if (validator.toFunction(2, true))
378                         callbackManager->setOnError(arguments[2]);
379
380                 EventTagActionTransceivePtr event(new EventTagActionTransceive());
381                 std::vector<unsigned char> data;
382                 if (dataObj) {
383                         NFCConverter convert(context);
384                         data= convert.toVectorOfOctets(arguments[0]);
385                 }
386                 event->transceive(data);
387                 event->setPrivateData( DPL::StaticPointerCast<IEventPrivateData>(callbackManager) );
388                 event->setForAsynchronousCall(&NFCResponseDispatcher::getInstance());
389                 callbackManager->setObject(thisObject);
390                 INFCTagPtr nfcTag(privateObject->getObject());
391                 nfcTag->transceive(event);
392                 NFCAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, global_context);
393                 return JSValueMakeUndefined(context);
394     } Catch (BasePlatformException) {
395         LoggerE(_rethrown_exception.getName() << ": " << _rethrown_exception.getMessage());
396         return JSWebAPIErrorFactory::postException(context, exception, _rethrown_exception);
397         } Catch (ConversionException) {
398                 LoggerE("transceive : ConversionException");
399                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
400         } Catch (InvalidArgumentException) {
401                 LoggerE("transceive InvalidArgumentException");
402                 callbackManager->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid Values"));
403                 return JSValueMakeUndefined(context);
404         } Catch (PlatformException) {
405                 LoggerE("PlatformException: " << _rethrown_exception.GetMessage());
406                 callbackManager->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, "Service Not Available"));
407                 return JSValueMakeUndefined(context);
408         } Catch (WrtDeviceApis::Commons::UnknownException) {
409                 LoggerE("UnknownException: " << _rethrown_exception.GetMessage());
410         } Catch (WrtDeviceApis::Commons::Exception) {
411                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
412         }
413
414         callbackManager->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::UNKNOWN_ERROR,"Unknown Error"));
415         return JSValueMakeUndefined(context);
416 }
417
418
419 }
420 }