e11a8b3cdfe2640365a93e67435f324473cdf231
[framework/web/wrt-plugins-tizen.git] / src / Bluetooth / JSBluetoothSocket.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 <CommonsJavaScript/JSUtils.h>
21 #include <CommonsJavaScript/JSCallbackManager.h>
22 #include <CommonsJavaScript/Utils.h>
23 #include <JSTizenExceptionFactory.h>
24 #include <JSTizenException.h>
25 #include <SecurityExceptions.h>
26 #include "BluetoothFactory.h"
27 #include "BluetoothProperty.h"
28 #include <dpl/scoped_array.h>
29 #include <dpl/scoped_free.h>
30 #include "BluetoothSocketListener.h"
31 #include "JSBluetoothSocket.h"
32 #include "JSBluetoothDevice.h"
33 #include "BluetoothMultiCallback.h"
34 #include "BluetoothConverter.h"
35 #include <bluetooth.h>
36 #include "plugin_config.h"
37
38 using namespace std;
39 using namespace DPL;
40 using namespace DeviceAPI::Common;
41
42
43 namespace DeviceAPI {
44 namespace Bluetooth {
45
46
47 JSClassDefinition JSBluetoothSocket::m_classInfo =
48 {
49         0,
50         kJSClassAttributeNone,
51         "BluetoothSocket",
52         NULL,
53         m_properties,
54         m_function,
55         initialize,
56         finalize,
57         NULL,
58         NULL,
59         NULL,
60         NULL,
61         NULL,
62         NULL,
63         NULL,
64         hasInstance,
65         NULL
66 };
67
68 JSStaticValue JSBluetoothSocket::m_properties[] = 
69 {
70         {"uuid", getProperty, NULL, kJSPropertyAttributeReadOnly},
71 //      {"protocol", getProperty, NULL, kJSPropertyAttributeReadOnly},
72         {"state", getProperty, NULL, kJSPropertyAttributeReadOnly},
73         {"peer", getProperty, NULL, kJSPropertyAttributeReadOnly},
74         {"onerror", getCallback, setProperty, kJSPropertyAttributeNone},
75         {"onmessage", getCallback, setProperty, kJSPropertyAttributeNone},
76         {"onclose", getCallback, setProperty, kJSPropertyAttributeNone},
77         {0, 0, 0, 0}
78 };
79
80
81 JSStaticFunction JSBluetoothSocket::m_function[] =
82 {
83         { "writeData", JSBluetoothSocket::writeData, kJSPropertyAttributeNone },
84         { "readData", JSBluetoothSocket::readData, kJSPropertyAttributeNone },
85         { "close", JSBluetoothSocket::close, kJSPropertyAttributeNone },        
86         { 0, 0, 0 }
87 };
88
89 const JSClassRef JSBluetoothSocket::getClassRef() 
90 {
91         if (!m_jsClassRef) 
92         {
93                 m_jsClassRef = JSClassCreate(&m_classInfo);
94         }
95         return m_jsClassRef;
96 }
97
98 const JSClassDefinition* JSBluetoothSocket::getClassInfo() 
99 {
100         return &m_classInfo;
101 }
102
103 JSClassRef JSBluetoothSocket::m_jsClassRef = JSClassCreate(JSBluetoothSocket::getClassInfo());
104
105 JSObjectRef JSBluetoothSocket::m_peer = NULL;
106
107 bool JSBluetoothSocket::setProperty(JSContextRef context, 
108                                         JSObjectRef object,
109                                         JSStringRef propertyName,
110                                         JSValueRef value,
111                                         JSValueRef* exception)
112 {
113         LogDebug("OK");
114
115         try
116         {
117                 JSBluetoothSocketPriv *priv = static_cast<JSBluetoothSocketPriv*>(JSObjectGetPrivate(object));
118                 if (priv == NULL)
119                 {
120                         ThrowMsg(WrtDeviceApis::Commons::UnknownException, "private object is null");
121                 }
122
123                 IBluetoothSocketManagerPtr BluetoothSocketManager(priv->getObject());
124                 BluetoothConverter converter(priv->getContext());
125                 if (BluetoothSocketManager == NULL)
126                 {
127                         ThrowMsg(WrtDeviceApis::Commons::UnknownException, "BluetoothManager is NULL");
128                 }
129
130                 EventBTSocketNotificationEmitterPtr emitter = BluetoothSocketManager->getSocketNotifier();
131                 if (emitter == NULL)
132                 {
133                         ThrowMsg(WrtDeviceApis::Commons::UnknownException, "emitter is NULL");
134                 }
135
136                 BluetoothSocketNotifierPrivateDataPtr privData =
137                                 DPL::DynamicPointerCast<BluetoothSocketNotifierPrivateData>(emitter->getEventPrivateData());
138
139                 if (privData == NULL)
140                 {
141                         ThrowMsg(WrtDeviceApis::Commons::UnknownException, "BluetoothSocketNotifierPrivateData is NULL");
142                 }
143
144                 if(JSValueIsNull(context, value) ||
145                         JSObjectIsFunction(context, converter.toJSObjectRef(value)) )
146                 {
147                         LogDebug("Callable or null");
148                         converter.setBluetoothSocketNotifierCallback(propertyName, value, object, privData);
149                 }
150                 else
151                 {
152                         ThrowMsg(WrtDeviceApis::Commons::ConversionException, "Non callable object");
153                 }
154                 
155                 emitter->setListener(&BluetoothSocketListener::getInstance());
156                 emitter->setEventPrivateData(DPL::StaticPointerCast<WrtDeviceApis::Commons::IEventPrivateData>(privData));
157
158                 return true;
159         }
160         catch (const WrtDeviceApis::Commons::ConversionException& ex)
161         {
162                 LogError("Exception: " << ex.GetMessage());
163                 *exception = JSTizenExceptionFactory::makeErrorObject(context,
164                         JSTizenException::TYPE_MISMATCH_ERROR, "type mismatch error");
165         }       
166         catch (WrtDeviceApis::Commons::Exception& ex)
167         {
168                 LogWarning("Exception: " << ex.GetMessage());
169         }
170
171         return false;
172 }
173
174 void JSBluetoothSocket::initialize(JSContextRef context, JSObjectRef object) 
175 {
176         LogDebug("JSBluetoothSocket::initialize ");
177         
178 }
179
180 void JSBluetoothSocket::finalize(JSObjectRef object) 
181 {
182         LogDebug("JSBluetoothSocket::Finalrize");
183
184         JSBluetoothSocketPriv *priv = static_cast<JSBluetoothSocketPriv*>(JSObjectGetPrivate(object));
185
186         if (priv != NULL)
187         {
188                 delete priv;
189                 JSObjectSetPrivate(object, NULL);
190         }
191 }
192
193 bool JSBluetoothSocket::hasInstance(JSContextRef context, JSObjectRef constructor,
194                 JSValueRef possibleInstance, JSValueRef* exception) 
195 {
196         return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
197 }
198
199 JSObjectRef JSBluetoothSocket::createJSObject(JSContextRef context, BluetoothSocketData socketData)
200 {
201         IBluetoothSocketManagerPtr BluetoothSocketManager(BluetoothFactory::getInstance().getBluetoothSocketManager());
202         JSBluetoothSocketPriv* priv = new JSBluetoothSocketPriv( context, BluetoothSocketManager);
203         BluetoothSocketManager->setSocketData(socketData);
204
205         try 
206         {
207                 if (BluetoothSocketManager == NULL || priv == NULL)
208                 {
209                         LogError("BluetoothManager or event or listener NULL");
210                         Throw(WrtDeviceApis::Commons::UnknownException);        
211                 }
212
213                 BluetoothConverter converter(priv->getContext());
214                 EventBTSocketNotificationEmitterPtr emitter(new EventBTSocketNotificationEmitter);
215
216                 BluetoothSocketNotifierPrivateDataPtr privData(converter.getInitalBluetoothSocketNotifierPrivateData());
217                 emitter->setListener(&BluetoothSocketListener::getInstance());
218                 emitter->setEventPrivateData(DPL::StaticPointerCast<WrtDeviceApis::Commons::IEventPrivateData>(privData));
219                 
220                 if (BluetoothSocketManager->setSocketNotifier(emitter) != BT_ERROR_NONE)
221                 {
222                         LogError("callback set error");
223                         Throw(WrtDeviceApis::Commons::UnknownException);        
224                 }
225                 
226                 return JSObjectMake(context, getClassRef(), priv);
227         }
228         catch (WrtDeviceApis::Commons::Exception& ex) 
229         {
230                 LogError("Exception: " << ex.GetMessage());
231
232                 switch (ex.getCode())
233                 {
234                 case WrtDeviceApis::Commons::ExceptionCodes::ConversionException:
235                         return JSTizenExceptionFactory::makeErrorObject(context,
236                                 JSTizenException::TYPE_MISMATCH_ERROR, "type mismatch error");
237                 case WrtDeviceApis::Commons::ExceptionCodes::InvalidArgumentException:
238                         return JSTizenExceptionFactory::makeErrorObject(context,
239                                 JSTizenException::INVALID_VALUES_ERROR, "invalid parameter error");
240                 case WrtDeviceApis::Commons::ExceptionCodes::Exception:
241                 default:
242                         return JSTizenExceptionFactory::makeErrorObject(context,
243                                 JSTizenException::UNKNOWN_ERROR, "Unkown error");
244                 }
245         }               
246
247         
248 }
249
250 JSObjectRef JSBluetoothSocket::createJSObject(JSContextRef context, BluetoothSocketData socketData, EventBTReadDataType readData)
251 {
252         IBluetoothSocketManagerPtr BluetoothSocketManager(BluetoothFactory::getInstance().getBluetoothSocketManager());
253         JSBluetoothSocketPriv* priv = new JSBluetoothSocketPriv( context, BluetoothSocketManager);
254         BluetoothSocketManager->setSocketData(socketData);
255         BluetoothSocketManager->setReadData(readData);
256         return JSObjectMake(context, getClassRef(), priv);
257 }
258
259 JSValueRef JSBluetoothSocket::getProperty(JSContextRef context,
260                                                         JSObjectRef object,
261                                                         JSStringRef propertyName,
262                                                         JSValueRef* exception)
263 {
264         LogDebug("OK");
265
266         
267         Try
268         {
269                 if(JSStringIsEqualToUTF8CString(propertyName, "peer") && m_peer != NULL)
270                         return m_peer;
271
272                 JSBluetoothSocketPriv *priv = static_cast<JSBluetoothSocketPriv*>(JSObjectGetPrivate(object));
273                 if (priv == NULL)
274                 {
275                         ThrowMsg(WrtDeviceApis::Commons::ConversionException, "private object null");
276                 }
277
278                 IBluetoothSocketManagerPtr BluetoothSocketManager(priv->getObject());
279                 BluetoothConverter converter(priv->getContext());
280                 if (BluetoothSocketManager == NULL)
281                 {
282                         ThrowMsg(WrtDeviceApis::Commons::UnknownException, "BluetoothManager is NULL");
283                 }
284
285                 if(JSStringIsEqualToUTF8CString(propertyName, "uuid")) 
286                 {
287                         std::string uuid = BluetoothSocketManager->getUUID();
288                         return converter.toJSValueRef(uuid);
289                 }
290                 else if(JSStringIsEqualToUTF8CString(propertyName, "state")) 
291                 {
292                         unsigned short int state = BluetoothSocketManager->getState();
293                         return converter.toBluetoothStateJSValue(state);
294                 }
295                 else
296                 {
297                         BluetoothDeviceData device = BluetoothSocketManager->getPeer();
298                         m_peer = JSBluetoothDevice::createJSObject(priv->getContext(), device);
299                         return m_peer;
300                 }
301         }
302         Catch(WrtDeviceApis::Commons::Exception)
303         {
304                 LogWarning("Exception: "<<_rethrown_exception.GetMessage());
305         }
306
307         return JSValueMakeUndefined(context);
308 }
309
310 JSValueRef JSBluetoothSocket::getCallback(JSContextRef context,
311                                                         JSObjectRef object,
312                                                         JSStringRef propertyName,
313                                                         JSValueRef* exception)
314 {
315         LogDebug("OK");
316
317         Try
318         {
319                 JSBluetoothSocketPriv *priv = static_cast<JSBluetoothSocketPriv*>(JSObjectGetPrivate(object));
320                 if (priv == NULL)
321                 {
322                         ThrowMsg(WrtDeviceApis::Commons::ConversionException, "private object null");
323                 }
324
325                 IBluetoothSocketManagerPtr BluetoothSocketManager(priv->getObject());
326                 BluetoothConverter converter(priv->getContext());
327                 if (BluetoothSocketManager == NULL)
328                 {
329                         ThrowMsg(WrtDeviceApis::Commons::UnknownException, "BluetoothManager is NULL");
330                 }
331
332                 EventBTSocketNotificationEmitterPtr emitter = BluetoothSocketManager->getSocketNotifier();
333                 if (emitter == NULL)
334                 {
335                         ThrowMsg(WrtDeviceApis::Commons::UnknownException, "emitter is NULL");
336                 }
337
338                 BluetoothSocketNotifierPrivateDataPtr privData =
339                                 DPL::DynamicPointerCast<BluetoothSocketNotifierPrivateData>(emitter->getEventPrivateData());
340
341                 if (privData == NULL)
342                 {
343                         ThrowMsg(WrtDeviceApis::Commons::UnknownException, "privData NULL");
344                 }
345
346                 if(JSStringIsEqualToUTF8CString(propertyName, "onmessage"))
347                 {
348                         JSValueRef callback = privData->getOnMessage()->getOnSuccess();
349                         if(callback == NULL)
350                         {
351                                 LogDebug("callback is NULL");
352                         }
353                         else
354                         {
355                                 LogDebug("callback is not NULL");
356                                 return callback;
357                         }
358                 }
359                 else if(JSStringIsEqualToUTF8CString(propertyName, "onclose"))
360                 {
361                         JSValueRef callback = privData->getOnClose()->getOnSuccess();
362                         if(callback == NULL)
363                         {
364                                 LogDebug("callback is NULL");
365                         }
366                         else
367                         {
368                                 LogDebug("callback is not NULL");
369                                 return callback;
370                         }
371                 }
372                 else if(JSStringIsEqualToUTF8CString(propertyName, "onerror"))
373                 {
374                         JSValueRef callback = privData->getOnError()->getOnSuccess();
375                         if(callback == NULL)
376                         {
377                                 LogDebug("callback is NULL");
378                         }
379                         else
380                         {
381                                 LogDebug("callback is not NULL");
382                                 return callback;
383                         }
384                 }
385         }
386         Catch(WrtDeviceApis::Commons::Exception)
387         {
388                 LogWarning("Exception: "<<_rethrown_exception.GetMessage());
389         }
390
391         return JSValueMakeNull(context);
392 }
393
394
395 JSValueRef JSBluetoothSocket::writeData(JSContextRef context, JSObjectRef object,
396                 JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
397                 JSValueRef* exception) 
398 {
399         LogDebug("JSBluetoothSocket");
400         Converter converter(context);   
401         Try     
402         {
403                 JSBluetoothSocketPriv *priv = static_cast<JSBluetoothSocketPriv*>(JSObjectGetPrivate(thisObject));
404
405                 if (priv == NULL) 
406                 {
407                         ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Private object is NULL.");
408                 }
409
410                 if (argumentCount < 1)
411                 {
412                         LogError("argument wrong");
413                         Throw(WrtDeviceApis::Commons::ConversionException);                             
414                 }
415
416                 AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(
417                         bluetoothExportedNames[BLUETOOTH_FUNCTION_API_SOCKET_WRITE_DATA]);
418
419                 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
420
421                 IBluetoothSocketManagerPtr BluetoothSocketManager(priv->getObject());
422                 std::vector<char> data = converter.toVectorOfChars(arguments[0]);
423                 unsigned int index = 0;
424                 
425                 if (data.size() == 0)
426                 {
427                         LogError("size 0 array passed");
428                         Throw(WrtDeviceApis::Commons::ConversionException);                             
429                 }
430
431                 DPL::ScopedArray<char> buffer(new char[data.size()]);
432
433                 for (index = 0; index < data.size(); index++)
434                 {
435                         buffer[index] = data[index];
436                 }
437                 
438                 if (BluetoothSocketManager->writeData(buffer.Get(), data.size()) != BT_ERROR_NONE)
439                 {
440                         LogError("BluetoothSocket Write Error");
441                         Throw(WrtDeviceApis::Commons::UnknownException);        
442                 }
443                 
444                 return converter.toJSValueRef(data.size());
445         }
446         Catch (WrtDeviceApis::Commons::SecurityException) 
447         {
448                 LogError("permission denied error");
449                 return JSTizenExceptionFactory::postException(context, exception, 
450                         JSTizenException::PERMISSION_DENIED_ERROR, "permission denied error");  
451         }
452         Catch (WrtDeviceApis::Commons::ConversionException)
453         {
454                 LogError("ConversionException");
455                 return JSTizenExceptionFactory::postException(context, exception, 
456                                         JSTizenException::TYPE_MISMATCH_ERROR, "type mismatch error");
457
458         }
459         Catch(WrtDeviceApis::Commons::UnsupportedException)
460         {
461                 LogError("UnsupportException");
462                 return JSTizenExceptionFactory::postException(context, exception,
463                                 JSTizenException::NOT_SUPPORTED_ERROR, "Unsupport Exception");
464         }                       
465         Catch (WrtDeviceApis::Commons::Exception) 
466         {
467                 LogError("Exception");
468                 return JSTizenExceptionFactory::postException(context, exception, 
469                         JSTizenException::UNKNOWN_ERROR, "unknown error");
470         }
471 }
472
473
474 JSValueRef JSBluetoothSocket::readData(JSContextRef context, JSObjectRef object,
475                 JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
476                 JSValueRef* exception) 
477 {
478
479
480         LogDebug("JSBluetoothSocket");
481
482         Try     
483         {
484                 JSBluetoothSocketPriv *priv = static_cast<JSBluetoothSocketPriv*>(JSObjectGetPrivate(thisObject));
485                 if(!priv)
486                         ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Private object is NULL.");
487                         
488                 IBluetoothSocketManagerPtr BluetoothSocketManager(priv->getObject());
489
490                 AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(
491                         bluetoothExportedNames[BLUETOOTH_FUNCTION_API_SOCKET_READ_DATA]);
492                 
493                 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
494                 
495
496                 EventBTReadDataType     data = BluetoothSocketManager->readData();
497                 int length = data.size();
498                 LogDebug("size" << length);
499                 BluetoothConverter converter(priv->getContext());
500
501                 if (length == 0)
502                 {
503                         LogError("BluetoothSocket Read Error");
504                         Throw(WrtDeviceApis::Commons::InvalidArgumentException);        
505                 }
506
507
508                 JSObjectRef result = converter.toBluetoothByteArray(data);
509                 return result;
510         }
511         Catch (WrtDeviceApis::Commons::SecurityException) 
512         {
513                 LogError("permission denied error");
514                 return JSTizenExceptionFactory::postException(context, exception, 
515                         JSTizenException::PERMISSION_DENIED_ERROR, "permission denied error");  
516         }
517         Catch(WrtDeviceApis::Commons::UnsupportedException)
518         {
519                 LogError("UnsupportException");
520                 return JSTizenExceptionFactory::postException(context, exception,
521                                 JSTizenException::NOT_SUPPORTED_ERROR, "Unsupport Exception");
522         }                       
523         Catch (WrtDeviceApis::Commons::Exception) 
524         {
525                 LogError("Exception");
526                 return JSTizenExceptionFactory::postException(context, exception, 
527                         JSTizenException::UNKNOWN_ERROR, "unknown error");
528         }       
529 }
530
531
532 JSValueRef JSBluetoothSocket::close(JSContextRef context, JSObjectRef object,
533                 JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
534                 JSValueRef* exception) 
535 {
536         LogDebug("JSBluetoothSocket");
537
538         Try     
539         {
540                 JSBluetoothSocketPriv *priv = static_cast<JSBluetoothSocketPriv*>(JSObjectGetPrivate(thisObject));
541                 if(!priv)
542                         ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Private object is NULL.");
543
544                 IBluetoothSocketManagerPtr BluetoothSocketManager(priv->getObject());
545
546                 LogDebug(bluetoothExportedNames[BLUETOOTH_FUNCTION_API_SOCKET_CLOSE]);
547
548                 AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(
549                         bluetoothExportedNames[BLUETOOTH_FUNCTION_API_SOCKET_CLOSE]);
550
551
552                 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
553
554                 if (BluetoothSocketManager->close() != BT_ERROR_NONE)
555                 {
556                         Throw(WrtDeviceApis::Commons::UnknownException);        
557                 }
558
559                 return JSValueMakeNull(context);
560
561         }
562         Catch (WrtDeviceApis::Commons::SecurityException) 
563         {
564                 LogError("permission denied error");
565                 return JSTizenExceptionFactory::postException(context, exception, 
566                         JSTizenException::PERMISSION_DENIED_ERROR, "permission denied error");  
567         }
568         Catch(WrtDeviceApis::Commons::UnsupportedException)
569         {
570                 LogError("UnsupportException");
571                 return JSTizenExceptionFactory::postException(context, exception,
572                                 JSTizenException::NOT_SUPPORTED_ERROR, "Unsupport Exception");
573         }                       
574         Catch (WrtDeviceApis::Commons::Exception) 
575         {
576                 LogError("Exception");
577                 return JSTizenExceptionFactory::postException(context, exception, 
578                         JSTizenException::UNKNOWN_ERROR, "unknown error");
579         }               
580 }
581
582
583 }
584 }
585