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