Update change log and spec for wrt-plugins-tizen_0.4.13
[framework/web/wrt-plugins-tizen.git] / src / SecureElement / JSSESession.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
19 #include <dpl/log/log.h>
20 #include <CommonsJavaScript/Converter.h>
21 #include <CommonsJavaScript/Validator.h>
22 #include <Commons/Exception.h>
23 #include <CommonsJavaScript/PrivateObject.h>
24 #include <CommonsJavaScript/JSUtils.h>
25 #include <CommonsJavaScript/JSCallbackManager.h>
26 #include <CommonsJavaScript/Utils.h>
27 #include <JSTizenExceptionFactory.h>
28 #include <JSTizenException.h>
29 #include <SecurityExceptions.h>
30 #include "SEFactory.h"
31 #include "SEResponseDispatcher.h"
32 #include "JSSESession.h"
33 #include "SEConverter.h"
34 #include "SEAsyncCallbackManager.h"
35 #include "plugin_config.h"
36
37
38 using namespace DeviceAPI::Common;
39 using namespace WrtDeviceApis::Commons;
40 using namespace WrtDeviceApis::CommonsJavaScript;
41 using namespace DPL;
42
43 #define TIZEN_SESESSION_ATTRIBUTENAME "Session"
44 #define TIZEN_SESESSION_ISCLOSED "isClosed"
45
46 namespace DeviceAPI {
47 namespace SecureElement {
48
49  JSClassDefinition JSSESession::m_classInfo =
50 {
51     0,
52     kJSClassAttributeNone,
53     TIZEN_SESESSION_ATTRIBUTENAME,
54     0,
55     m_property,
56     m_function,
57     initialize,
58     finalize,
59     NULL, //hasProperty,
60     NULL,
61     NULL, //setProperty,
62     NULL, //DeleteProperty,
63     NULL, //GetPropertyNames,
64     NULL, //CallAsFunction,
65     NULL, //CallAsConstructor,
66     hasInstance, //HasInstance,
67     NULL  //ConvertToType
68 };
69
70 JSStaticFunction JSSESession::m_function[] = {
71     {"openBasicChannel", JSSESession::openBasicChannel, kJSPropertyAttributeNone},
72     {"openLogicalChannel", JSSESession::openLogicalChannel, kJSPropertyAttributeNone},
73     {"getATR", JSSESession::getATR, kJSPropertyAttributeNone},
74     {"close", JSSESession::close, kJSPropertyAttributeNone},
75     {"closeChannels", JSSESession::closeChannels, kJSPropertyAttributeNone},
76     { 0, 0, 0}
77 };
78
79 JSStaticValue JSSESession::m_property[] =
80 {
81         {TIZEN_SESESSION_ISCLOSED,  getProperty, NULL, kJSPropertyAttributeReadOnly},
82         { 0, 0, 0, 0 }
83 };
84 JSClassRef JSSESession::m_jsClassRef = JSClassCreate(JSSESession::getClassInfo());
85
86 JSValueRef JSSESession::getProperty(JSContextRef context, JSObjectRef object,
87         JSStringRef propertyName, JSValueRef* exception)
88 {
89         LogDebug("Enter");
90
91         Try     {
92                 Converter convert(context);
93
94                 if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SESESSION_ISCLOSED)) {
95                         SESessionPrivObject* privateObject = static_cast<SESessionPrivObject*>(JSObjectGetPrivate(object));
96                         if (NULL == privateObject) {
97                                 ThrowMsg(NullPointerException, "Private object not set.");
98                         }
99                         ISESessionPtr seSession = privateObject->getObject();
100                         
101                         return convert.toJSValueRef(seSession->isClosed());
102                 }
103         } Catch (ConversionException) {
104                 LogError("ConversionException: " << _rethrown_exception.GetMessage());
105         } Catch (NullPointerException) {
106                 LogError("NullPointerException: " << _rethrown_exception.GetMessage());
107         } Catch (UnknownException) {
108                 LogError("UnknownExceptionException: " << _rethrown_exception.GetMessage());
109         } Catch (PlatformException) {
110                 LogError("PlatformExceptionException: " << _rethrown_exception.GetMessage());
111         } Catch (WrtDeviceApis::Commons::Exception) {
112                 LogError("Exception: " << _rethrown_exception.GetMessage());
113         }
114
115     return JSValueMakeUndefined(context);
116 }
117
118 JSObjectRef JSSESession::createJSObject(JSContextRef context, void *session) {
119         LogDebug("entered");
120
121         ISESessionPtr seSession = SEFactory::getInstance().createSESessionObject(session);
122         
123         SESessionPrivObject *priv = new SESessionPrivObject(context, seSession);
124
125         if (!priv) {
126                 ThrowMsg(NullPointerException, "Can not new a SecureElement object");
127         }
128
129         return JSObjectMake(context, getClassRef(), priv);
130 }
131
132 void JSSESession::initialize(JSContextRef context, JSObjectRef object)
133 {
134 }
135
136 void JSSESession::finalize(JSObjectRef object)
137 {
138         LogDebug( "entered" );
139         SESessionPrivObject *priv = static_cast<SESessionPrivObject*>( JSObjectGetPrivate( object ) ) ;
140         JSObjectSetPrivate(object, NULL);
141         LogDebug("Deleting SecureElement object");
142         delete priv;
143 }
144
145
146 const JSClassRef JSSESession::getClassRef()
147 {
148         if (!m_jsClassRef) {
149                 m_jsClassRef = JSClassCreate(&m_classInfo);
150         }
151         return m_jsClassRef;
152 }
153
154 const JSClassDefinition* JSSESession::getClassInfo()
155 {
156         return &m_classInfo;
157 }
158
159 bool JSSESession::hasInstance(JSContextRef context,
160         JSObjectRef constructor,
161         JSValueRef possibleInstance,
162         JSValueRef* exception)
163 {
164     return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
165 }
166
167 JSValueRef JSSESession::getATR(JSContextRef context,
168         JSObjectRef object,
169         JSObjectRef thisObject,
170         size_t argumentCount,
171         const JSValueRef arguments[],
172         JSValueRef* exception)
173 {
174     AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
175     TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
176
177         Try {
178                 SESessionPrivObject* privateObject = static_cast<SESessionPrivObject*>(JSObjectGetPrivate(thisObject));
179                 if (NULL == privateObject) {
180                         LogError("private object is null");
181                         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
182                 }
183
184                 ISESessionPtr seSession(privateObject->getObject());
185                 SEConverter convert(context);
186                 return convert.toJSValueRef(seSession->getATR());
187         } Catch (WrtDeviceApis::Commons::Exception) {
188                 LogError("Exception: " << _rethrown_exception.GetMessage());
189         }
190         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown Error");
191 }
192
193 JSValueRef JSSESession::close(JSContextRef context,
194         JSObjectRef object,
195         JSObjectRef thisObject,
196         size_t argumentCount,
197         const JSValueRef arguments[],
198         JSValueRef* exception)
199 {
200     AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
201     TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
202
203         Try {
204                 SESessionPrivObject* privateObject = static_cast<SESessionPrivObject*>(JSObjectGetPrivate(thisObject));
205                 if (NULL == privateObject) {
206                         LogError("private object is null");
207                         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
208                 }
209
210                 ISESessionPtr seSession(privateObject->getObject());
211                 seSession->close();
212                 return JSValueMakeUndefined(context);
213         } Catch (WrtDeviceApis::Commons::Exception) {
214                 LogError("Exception: " << _rethrown_exception.GetMessage());
215         }
216         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown Error");
217 }
218
219 JSValueRef JSSESession::closeChannels(JSContextRef context,
220         JSObjectRef object,
221         JSObjectRef thisObject,
222         size_t argumentCount,
223         const JSValueRef arguments[],
224         JSValueRef* exception)
225 {
226     AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
227     TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
228
229         Try {
230                 SESessionPrivObject* privateObject = static_cast<SESessionPrivObject*>(JSObjectGetPrivate(thisObject));
231                 if (NULL == privateObject) {
232                         LogError("private object is null");
233                         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
234                 }
235
236                 ISESessionPtr seSession(privateObject->getObject());
237                 seSession->closeChannels();
238                 return JSValueMakeUndefined(context);
239         } Catch (WrtDeviceApis::Commons::Exception) {
240                 LogError("Exception: " << _rethrown_exception.GetMessage());
241         }
242         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown Error");
243 }
244
245 JSValueRef JSSESession::openBasicChannel(JSContextRef context,
246         JSObjectRef object,
247         JSObjectRef thisObject,
248         size_t argumentCount,
249         const JSValueRef arguments[],
250         JSValueRef* exception)
251 {
252         LogDebug("Entered ");
253
254     AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
255     TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
256
257         Validator validator(context, exception);
258
259         if ((argumentCount < 2) || JSValueIsNull(context, arguments[0]) || JSValueIsUndefined(context, arguments[0]) || !JSIsArrayValue(context, arguments[0])) {
260                 /* 1st argument is mandatory. And 1st argument must be Array. */
261                 LogError("AID TypeMismatchException!");
262                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
263         }
264
265         if (JSValueIsNull(context, arguments[1]) || JSValueIsUndefined(context, arguments[1]) || !validator.isCallback(arguments[1])) {
266                 /* 2st argument is mandatory. And 1st argument must be Array. */
267                 LogError("SEChannelSuccessCallback TypeMismatchException!");
268                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
269         }
270
271         if ((argumentCount > 2) && !JSValueIsNull(context, arguments[2]) && !JSValueIsUndefined(context, arguments[2])) {
272                 if (!validator.isCallback(arguments[2])) {
273                         /* 3nd argument must be Callback. */
274                         LogError("ErrorCallback TypeMismatchException!");
275                         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
276                 }
277         }
278
279         JSValueRef onSuccessForCbm = NULL, onErrorForCbm = NULL;
280         if (validator.isCallback(arguments[1])) {
281                 onSuccessForCbm = arguments[1];
282         }
283
284         if ((argumentCount > 2) && validator.isCallback(arguments[2])) {
285                 onErrorForCbm = arguments[2];
286         }
287
288         SESessionPrivObject* privateObject = static_cast<SESessionPrivObject*>(JSObjectGetPrivate(thisObject));
289         if (NULL == privateObject) {
290                 LogError("private object is null");
291                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
292         }
293
294         ISESessionPtr seSession(privateObject->getObject());
295         Converter convert(context);
296         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(privateObject->getContext(), onSuccessForCbm, onErrorForCbm, true, true);
297         Try {
298                 std::vector<unsigned char> aid = convert.toVectorOfUChars(arguments[0]);
299                 if ((aid.size() < 5) || (aid.size() > 16)) {
300                         LogError("wrong aid length : " << aid.size());
301                         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, "Wrong AID length");
302                 }
303                 EventSEOpenChannelPtr event(new EventSEOpenChannel(aid, true));
304                 event->setPrivateData( StaticPointerCast<IEventPrivateData>(callbackManager) );
305                 event->setForAsynchronousCall(&SEResponseDispatcher::getInstance());
306
307                 seSession->openChannel(event);
308
309                 SEAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, privateObject->getContext());
310
311                 return JSValueMakeUndefined(context);
312         } Catch (ConversionException) {
313                 LogError("ConversionException");
314                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
315         } Catch (UnknownException) {
316                 LogError("UnknownException: " << _rethrown_exception.GetMessage());
317         } Catch (WrtDeviceApis::Commons::Exception) {
318                 LogError("Exception: " << _rethrown_exception.GetMessage());
319         }
320
321         callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR,"Unknown Error"));
322         return JSValueMakeUndefined(context);
323 }
324
325 JSValueRef JSSESession::openLogicalChannel(JSContextRef context,
326         JSObjectRef object,
327         JSObjectRef thisObject,
328         size_t argumentCount,
329         const JSValueRef arguments[],
330         JSValueRef* exception)
331 {
332         LogDebug("Entered ");
333
334     AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
335     TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
336
337         Validator validator(context, exception);
338
339         if ((argumentCount < 2) || JSValueIsNull(context, arguments[0]) || JSValueIsUndefined(context, arguments[0]) || !JSIsArrayValue(context, arguments[0])) {
340                 /* 1st argument is mandatory. And 1st argument must be Array. */
341                 LogError("AID TypeMismatchException!");
342                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
343         }
344
345         if (JSValueIsNull(context, arguments[1]) || JSValueIsUndefined(context, arguments[1]) || !validator.isCallback(arguments[1])) {
346                 /* 2st argument is mandatory. And 1st argument must be Array. */
347                 LogError("SEChannelSuccessCallback TypeMismatchException!");
348                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
349         }
350
351         if ((argumentCount > 2) && !JSValueIsNull(context, arguments[2]) && !JSValueIsUndefined(context, arguments[2])) {
352                 if (!validator.isCallback(arguments[2])) {
353                         /* 3nd argument must be Callback. */
354                         LogError("ErrorCallback TypeMismatchException!");
355                         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
356                 }
357         }
358
359         JSValueRef onSuccessForCbm = NULL, onErrorForCbm = NULL;
360         if (validator.isCallback(arguments[1])) {
361                 onSuccessForCbm = arguments[1];
362         }
363
364         if ((argumentCount > 2) && validator.isCallback(arguments[2])) {
365                 onErrorForCbm = arguments[2];
366         }
367
368         SESessionPrivObject* privateObject = static_cast<SESessionPrivObject*>(JSObjectGetPrivate(thisObject));
369         if (NULL == privateObject) {
370                 LogError("private object is null");
371                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
372         }
373
374         ISESessionPtr seSession(privateObject->getObject());
375         Converter convert(context);
376         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(privateObject->getContext(), onSuccessForCbm, onErrorForCbm, true, true);
377         Try {
378                 std::vector<unsigned char> aid = convert.toVectorOfUChars(arguments[0]);
379                 if ((aid.size() < 5) || (aid.size() > 16)) {
380                         LogError("wrong aid length : " << aid.size());
381                         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, "Wrong AID length");
382                 }
383                 EventSEOpenChannelPtr event(new EventSEOpenChannel(aid, false));
384                 event->setPrivateData( StaticPointerCast<IEventPrivateData>(callbackManager) );
385                 event->setForAsynchronousCall(&SEResponseDispatcher::getInstance());
386
387                 seSession->openChannel(event);
388
389                 SEAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, privateObject->getContext());
390
391                 return JSValueMakeUndefined(context);
392         } Catch (ConversionException) {
393                 LogError("ConversionException");
394                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
395         } Catch (UnknownException) {
396                 LogError("UnknownException: " << _rethrown_exception.GetMessage());
397         } Catch (WrtDeviceApis::Commons::Exception) {
398                 LogError("Exception: " << _rethrown_exception.GetMessage());
399         }
400
401         callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR,"Unknown Error"));
402         return JSValueMakeUndefined(context);
403 }
404
405 }
406 }