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