Update change log and spec for wrt-plugins-tizen_0.4.70
[platform/framework/web/wrt-plugins-tizen.git] / src / NFC / JSNFCTarget.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
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
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16 //
17
18 #include <CommonsJavaScript/Validator.h>
19 #include <Commons/Exception.h>
20 #include <CommonsJavaScript/PrivateObject.h>
21 #include <CommonsJavaScript/JSUtils.h>
22 #include <CommonsJavaScript/JSCallbackManager.h>
23 #include <CommonsJavaScript/Utils.h>
24 #include <JSWebAPIErrorFactory.h>
25 #include <SecurityExceptions.h>
26 #include <ArgumentValidator.h>
27 #include <GlobalContextManager.h>
28 #include <PlatformException.h>
29
30 #include "JSNFCTarget.h"
31 #include "JSNFCManager.h"
32 #include "JSNdefMessage.h"
33 #include "NFCConverter.h"
34 #include "ResponseDispatcher.h"
35 #include "NFCAsyncCallbackManager.h"
36 #include "NFCListenerManager.h"
37 #include "NFCFactory.h"
38 #include "EventTargetAction.h"
39 #include "plugin_config_impl.h"
40 #include <Logger.h>
41
42
43 using namespace DeviceAPI::Common;
44 using namespace WrtDeviceApis::Commons;
45 using namespace WrtDeviceApis::CommonsJavaScript;
46
47
48 #define TIZEN_NFCTARGET_ATTRIBUTENAME "NFCTarget"
49
50 #define TIZEN_NFCTARGET_ISCONNECTED "isConnected"
51
52 namespace DeviceAPI {
53 namespace NFC {
54
55  JSClassDefinition JSNFCTarget::m_classInfo =
56 {
57     0,
58     kJSClassAttributeNone,
59     TIZEN_NFCTARGET_ATTRIBUTENAME,
60     0,
61     m_property,
62     m_function,
63     initialize,
64     finalize,
65     NULL, //hasProperty,
66     NULL,
67     NULL, //setProperty,
68     NULL, //DeleteProperty,
69     NULL, //GetPropertyNames,
70     NULL, //CallAsFunction,
71     NULL, //CallAsConstructor,
72     hasInstance, //HasInstance,
73     NULL  //ConvertToType
74 };
75
76 JSStaticValue JSNFCTarget::m_property[] =
77 {
78     //NFCTargetProperties
79     { TIZEN_NFCTARGET_ISCONNECTED, getProperty,
80             NULL, kJSPropertyAttributeReadOnly},
81     { 0, 0, 0, 0 }
82 };
83
84 JSStaticFunction JSNFCTarget::m_function[] = {
85     {"setReceiveNDEFListener", JSNFCTarget::setReceiveNDEFListener, kJSPropertyAttributeNone},
86     {"unsetReceiveNDEFListener", JSNFCTarget::unsetReceiveNDEFListener, kJSPropertyAttributeNone},
87     {"sendNDEF", JSNFCTarget::sendNDEF, kJSPropertyAttributeNone},
88     { 0, 0, 0}
89 };
90
91 JSClassRef JSNFCTarget::m_jsClassRef = JSClassCreate(JSNFCTarget::getClassInfo());
92
93 JSObjectRef JSNFCTarget::createJSObject(JSContextRef context, void *tagHandle, EventNFCChangedPrivateDataPtr eventNFCChangedPriv) {
94         LoggerD("entered");
95
96         INFCTargetPtr nfcTarget = NFCFactory::getInstance().createNFCTargetObject(tagHandle);
97
98         NFCTargetPrivObject *priv = new NFCTargetPrivObject(context, nfcTarget);
99
100         if (!priv) {
101                 ThrowMsg(NullPointerException, "Can not new a NFCTarget object");
102         }
103
104         priv->copyAceCheckAccessFunction(eventNFCChangedPriv.Get());
105         return JSObjectMake(context, getClassRef(), priv);
106 }
107
108 void JSNFCTarget::initialize(JSContextRef context, JSObjectRef object)
109 {
110 }
111
112 void JSNFCTarget::finalize(JSObjectRef object)
113 {
114         LoggerD( "entered" );
115         NFCTargetPrivObject *priv = static_cast<NFCTargetPrivObject*>( JSObjectGetPrivate( object ) ) ;
116         JSObjectSetPrivate(object, NULL);
117         LoggerD("Deleting timezone object");
118         delete priv;
119 }
120
121
122 const JSClassRef JSNFCTarget::getClassRef()
123 {
124         if (!m_jsClassRef) {
125                 m_jsClassRef = JSClassCreate(&m_classInfo);
126         }
127         return m_jsClassRef;
128 }
129
130 const JSClassDefinition* JSNFCTarget::getClassInfo()
131 {
132         return &m_classInfo;
133 }
134
135 JSValueRef JSNFCTarget::getProperty(JSContextRef context, JSObjectRef object,
136         JSStringRef propertyName, JSValueRef* exception)
137 {
138         LoggerD("Enter");
139
140         Try     {
141                 if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_NFCTARGET_ISCONNECTED)) {
142                         NFCTargetPrivObject* privateObject = static_cast<NFCTargetPrivObject*>(JSObjectGetPrivate(object));
143                         if (!privateObject) {
144                                 LoggerE("Private object is not set.");
145                                 ThrowMsg(NullPointerException, "Private object not initialized");
146                         }
147
148                         INFCTargetPtr nfcTarget(privateObject->getObject());
149                         NFCConverter convert(context);
150                         return convert.toJSValueRef(nfcTarget->isConnected());
151                 }
152         } Catch (ConversionException) {
153                 LoggerE("ConversionException: " << _rethrown_exception.GetMessage());
154         } Catch (NullPointerException) {
155                 LoggerE("NullPointerException: " << _rethrown_exception.GetMessage());
156         } Catch (WrtDeviceApis::Commons::UnknownException) {
157                 LoggerE("UnknownExceptionException: " << _rethrown_exception.GetMessage());
158         } Catch (PlatformException) {
159                 LoggerE("PlatformExceptionException: " << _rethrown_exception.GetMessage());
160         } Catch (WrtDeviceApis::Commons::Exception) {
161                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
162         }
163         return JSValueMakeUndefined(context);
164 }
165
166 bool JSNFCTarget::hasInstance(JSContextRef context,
167         JSObjectRef constructor,
168         JSValueRef possibleInstance,
169         JSValueRef* exception)
170 {
171     return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
172 }
173
174 JSValueRef JSNFCTarget::setReceiveNDEFListener(JSContextRef context,
175         JSObjectRef object,
176         JSObjectRef thisObject,
177         size_t argumentCount,
178         const JSValueRef arguments[],
179         JSValueRef* exception)
180 {
181         LoggerD("Entered ");
182
183         NFCTargetPrivObject* privateObject = static_cast<NFCTargetPrivObject*>(JSObjectGetPrivate(thisObject));
184         if (NULL == privateObject) {
185                 LoggerE("private object is null");
186                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
187         }
188
189         TIZEN_CHECK_ACCESS(context, exception, privateObject,
190         NFC_FUNCTION_API_P2P_FUNCS);
191
192         Try {
193                 ArgumentValidator validator(context, argumentCount, arguments);
194                 JSValueRef onSuccessForCbm = NULL;
195                 // NDEFMessageReadCallback
196                 if (validator.toFunction(0))
197                         onSuccessForCbm = arguments[0];
198
199                 JSContextRef global_context = GlobalContextManager::getInstance()->getGlobalContext(context);
200                 JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(global_context, onSuccessForCbm, NULL, true, true);
201
202                 EventTargetActionReceiveEmitterPtr emitter(new EventTargetActionReceiveEmitter);
203                 emitter->setListener(&NFCResponseDispatcher::getInstance());
204                 emitter->setEventPrivateData(DPL::StaticPointerCast<EventTargetActionReceive::PrivateDataType>(callbackManager));
205                 INFCTargetPtr nfcTarget(privateObject->getObject());
206                 nfcTarget->setReceiveNDEFListener(emitter);
207
208                 NFCListenerCancellerPtr canceller = NFCListenerCancellerPtr(new NFCListenerCanceller(global_context, thisObject, static_cast<long>(ID_NFCPEER_RECEIVENDEF_LISTENER)));
209                 IListenerItemPtr listenerItem = DPL::StaticPointerCast<IListenerItem>(canceller);
210                 NFCListenerManagerSingleton::Instance().registerListener(listenerItem, global_context);
211
212                 return JSValueMakeUndefined(context);
213     } Catch (BasePlatformException) {
214         LoggerE(_rethrown_exception.getName() << ": " << _rethrown_exception.getMessage());
215         return JSWebAPIErrorFactory::postException(context, exception, _rethrown_exception);
216         } Catch (ConversionException) {
217                 LoggerE("setReceiveNDEFListener : ConversionException");
218                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
219         } Catch (PlatformException) {
220                 LoggerE("PlatformException: " << _rethrown_exception.GetMessage());
221                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, "Service Not Available");
222         } Catch (WrtDeviceApis::Commons::UnknownException) {
223                 LoggerE("UnknownException: " << _rethrown_exception.GetMessage());
224         } Catch (WrtDeviceApis::Commons::Exception) {
225                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
226         }
227
228         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
229 }
230
231 JSValueRef JSNFCTarget::unsetReceiveNDEFListener(JSContextRef context,
232         JSObjectRef object,
233         JSObjectRef thisObject,
234         size_t argumentCount,
235         const JSValueRef arguments[],
236         JSValueRef* exception)
237 {
238         LoggerD("Entered ");
239         Try {
240                 NFCTargetPrivObject* privateObject = static_cast<NFCTargetPrivObject*>(JSObjectGetPrivate(thisObject));
241                 if (NULL == privateObject) {
242                         LoggerE("private object is null");
243                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
244                 }
245
246                 TIZEN_CHECK_ACCESS(context, exception, privateObject,
247                 NFC_FUNCTION_API_P2P_FUNCS);
248
249                 INFCTargetPtr nfcTarget(privateObject->getObject());
250                 nfcTarget->unsetReceiveNDEFListener();
251
252                 JSContextRef global_context = GlobalContextManager::getInstance()->getGlobalContext(context);
253                 NFCListenerCancellerPtr canceller = NFCListenerCancellerPtr(new NFCListenerCanceller(global_context, thisObject,  static_cast<long>(ID_NFCPEER_RECEIVENDEF_LISTENER)));
254                 IListenerItemPtr listenerItem = DPL::StaticPointerCast<IListenerItem>(canceller);
255                 NFCListenerManagerSingleton::Instance().unregisterListener(listenerItem);
256
257                 return JSValueMakeUndefined(context);
258         } Catch (WrtDeviceApis::Commons::UnknownException) {
259                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
260         } Catch(NullPointerException) {
261                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
262                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
263         } Catch (PlatformException) {
264                 LoggerE("PlatformException: " << _rethrown_exception.GetMessage());
265                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, "Service Not Available");
266         } Catch (WrtDeviceApis::Commons::Exception) {
267                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
268         }
269
270         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
271 }
272
273 JSValueRef JSNFCTarget::sendNDEF(JSContextRef context,
274         JSObjectRef object,
275         JSObjectRef thisObject,
276         size_t argumentCount,
277         const JSValueRef arguments[],
278         JSValueRef* exception)
279 {
280         LoggerD("Entered ");
281
282         NFCTargetPrivObject* privateObject = static_cast<NFCTargetPrivObject*>(JSObjectGetPrivate(thisObject));
283         if (NULL == privateObject) {
284                 LoggerE("private object is null");
285                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
286         }
287
288         TIZEN_CHECK_ACCESS(context, exception, privateObject,
289         NFC_FUNCTION_API_P2P_FUNCS);
290
291         JSContextRef global_context = GlobalContextManager::getInstance()->getGlobalContext(context);
292
293         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(global_context, NULL, NULL, true, true);
294         Try {
295                 ArgumentValidator validator(context, argumentCount, arguments);
296
297                 // ndefMessage
298                 JSObjectRef ndefMessageObj = validator.toObject(0, JSNdefMessage::getClassRef());
299                 // successCallback
300                 if (validator.toFunction(1, true))
301                         callbackManager->setOnSuccess(arguments[1]);
302                 // errorCallback
303                 if (validator.toFunction(2, true))
304                         callbackManager->setOnError(arguments[2]);
305
306                 void *messageHandle = NULL;
307                 try {
308                         NdefMessagePrivObject* ndefMessagePrivateObj = static_cast<NdefMessagePrivObject*>(JSObjectGetPrivate(ndefMessageObj));
309                         if (!ndefMessagePrivateObj) {
310                                 LogError("NDEF Message Private object is not set.");
311                                 ThrowMsg(ConversionException, "Private object is not set");
312                         }
313                         INdefMessagePtr ndefMessage(ndefMessagePrivateObj->getObject());
314                         JSValueRef recordsValue = (ndefMessage->mLocalProperty).getProperty(global_context, TIZEN_NDEFMESSAGE_RECORDS);
315                         NFCConverter convert(global_context);
316                         std::vector<void *> records = convert.toVectorOfRecordHandles(recordsValue);
317                         messageHandle = ndefMessage->makeNdefMessageHandle(records);
318                 } catch (WrtDeviceApis::Commons::Exception& err) {
319                         LoggerE(err.GetClassName() << ":"<<err.GetMessage());
320                         ThrowMsg(InvalidArgumentException, "Invalid NDEF Message");
321                 }
322                 if (messageHandle == NULL)
323                         ThrowMsg(InvalidArgumentException, "Invalid NDEF Message");
324         
325                 EventTargetActionSendPtr event(new EventTargetActionSend(messageHandle));
326                 callbackManager->setObject(thisObject);
327                 event->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager));
328                 event->setForAsynchronousCall(&NFCResponseDispatcher::getInstance());
329                 INFCTargetPtr nfcTarget(privateObject->getObject());
330                 nfcTarget->sendNDEF(event);
331                 NFCAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, global_context);
332                 return JSValueMakeUndefined(context);
333     } Catch (BasePlatformException) {
334         LoggerE(_rethrown_exception.getName() << ": " << _rethrown_exception.getMessage());
335         return JSWebAPIErrorFactory::postException(context, exception, _rethrown_exception);
336         } Catch (ConversionException) {
337                 LoggerE("sendNDEF : ConversionException");
338                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
339         } Catch (InvalidArgumentException) {
340                 LoggerE("sendNDEF InvalidArgumentException");
341                 callbackManager->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::INVALID_VALUES_ERROR,  _rethrown_exception.GetMessage()));
342                 return JSValueMakeUndefined(context);
343         } Catch (PlatformException) {
344                 LoggerE("PlatformException: " << _rethrown_exception.GetMessage());
345                 callbackManager->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, "Service Not Available"));
346                 return JSValueMakeUndefined(context);
347         } Catch (WrtDeviceApis::Commons::UnknownException) {
348                 LoggerE("UnknownException: " << _rethrown_exception.GetMessage());
349         } Catch (WrtDeviceApis::Commons::Exception) {
350                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
351         }
352
353         callbackManager->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::UNKNOWN_ERROR,"Unknown Error"));
354         return JSValueMakeUndefined(context);
355 }
356
357 }
358 }