wrt-plugins-tizen_0.4.23
[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 <vector>
19
20 #include <SecurityExceptions.h>
21 #include <JSUtil.h>
22 #include <JSWebAPIException.h>
23 #include <ArgumentValidator.h>
24 #include <GlobalContextManager.h>
25 #include <PlatformException.h>
26 #include <MultiCallbackUserData.h>
27
28 #include "plugin_config.h"
29 #include "JSBluetoothSocket.h"
30 #include "BluetoothSocket.h"
31 #include "BluetoothAdapter.h"
32
33 #include <TimeTracer.h>
34 #include <Logger.h>
35
36 using namespace WrtDeviceApis::Commons;
37 using namespace DeviceAPI::Common;
38
39 namespace DeviceAPI {
40 namespace Bluetooth {
41
42 JSClassDefinition JSBluetoothSocket::m_classInfo = {
43     0,
44     kJSClassAttributeNone,
45     "BluetoothSocket",
46     NULL, //ParentClass
47     m_property, //StaticValues
48     m_function, //StaticFunctions
49     initialize, //Initialize
50     finalize, //Finalize
51     NULL, //HasProperty,
52     NULL, //GetProperty,
53     NULL, //SetProperty,
54     NULL, //DeleteProperty,
55     NULL, //GetPropertyNames,
56     NULL, //CallAsFunction,
57     NULL, //CallAsConstructor,
58     NULL, //HasInstance,
59     NULL //ConvertToType
60 };
61
62 JSStaticValue JSBluetoothSocket::m_property[] = {
63     { BLUETOOTH_SOCKET_UUID, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
64     { BLUETOOTH_SOCKET_STATE, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
65     { BLUETOOTH_SOCKET_PEER, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
66     { BLUETOOTH_SOCKET_ONMESSAGE, getProperty, setProperty, kJSPropertyAttributeNone|kJSPropertyAttributeDontDelete },
67     { BLUETOOTH_SOCKET_ONCLOSE, getProperty, setProperty, kJSPropertyAttributeNone|kJSPropertyAttributeDontDelete },
68     { BLUETOOTH_SOCKET_ONERROR, getProperty, setProperty, kJSPropertyAttributeNone|kJSPropertyAttributeDontDelete },
69     { 0, 0, 0, 0 }
70 };
71
72 JSStaticFunction JSBluetoothSocket::m_function[] = {
73     { BLUETOOTH_SOCKET_API_WRITE_DATA, writeData, kJSPropertyAttributeNone },
74     { BLUETOOTH_SOCKET_API_READ_DATA, readData, kJSPropertyAttributeNone },
75     { BLUETOOTH_SOCKET_API_CLOSE, close, kJSPropertyAttributeNone },
76     { 0, 0, 0 }
77 };
78
79 JSClassRef JSBluetoothSocket::m_jsClassRef = JSClassCreate(JSBluetoothSocket::getClassInfo());
80
81 const JSClassRef JSBluetoothSocket::getClassRef()
82 {
83     if (!m_jsClassRef) {
84         m_jsClassRef = JSClassCreate(&m_classInfo);
85     }
86     return m_jsClassRef;
87 }
88
89 const JSClassDefinition* JSBluetoothSocket::getClassInfo()
90 {
91     return &m_classInfo;
92 }
93
94 JSObjectRef JSBluetoothSocket::createJSObject(JSContextRef context, BluetoothSocketPtr socket)
95 {
96     return JSObjectMake(context, getClassRef(), static_cast<void*>(socket));
97 }
98
99 void JSBluetoothSocket::initialize(JSContextRef context, JSObjectRef object)
100 {
101     LoggerD("Enter");  // do nothing
102 }
103
104 void JSBluetoothSocket::finalize(JSObjectRef object)
105 {
106     BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(object));
107     if (priv) {
108         JSObjectSetPrivate(object, NULL);
109         delete priv;
110     }
111 }
112
113 JSValueRef JSBluetoothSocket::getProperty(JSContextRef context,
114         JSObjectRef object,
115         JSStringRef propertyName,
116         JSValueRef* exception)
117 {
118     LoggerD("Enter");
119
120     try {
121         BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(object));
122         if (!priv) {
123             throw TypeMismatchException("Private object is NULL");
124         }
125
126         if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_UUID)) {
127             return JSUtil::toJSValueRef(context, priv->getUUID());
128         }
129         else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_STATE)) {
130             LoggerD("get state");
131             std::string state;
132             if(priv->getConnectionState()) {
133                 state = "OPEN";                
134             }
135             else {
136                 state = "CLOSED";
137             }
138             LoggerD("state: " << state);
139             return JSUtil::toJSValueRef(context, state);
140         }
141         else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_PEER)) {
142             return priv->getPeer(context);
143         }
144         else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_ONMESSAGE)) {
145             return priv->getOnMessage(context);
146         }
147         else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_ONCLOSE)) {
148             return priv->getOnClose(context);
149         }
150         else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_ONERROR)) {
151             return priv->getOnError(context);
152         }
153     } catch (const BasePlatformException &err) {
154         LoggerW("Getting property is failed: " << err.getMessage().c_str());
155     }
156
157     return NULL;
158 }
159
160 bool JSBluetoothSocket::setProperty(JSContextRef context,
161         JSObjectRef object,
162         JSStringRef propertyName,
163         JSValueRef value,
164         JSValueRef* exception)
165 {
166     try {
167         BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(object));
168         if (!priv) {
169             throw TypeMismatchException("Private object is NULL");
170         }
171
172         if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_ONMESSAGE)) {
173             JSObjectRef object = NULL;
174             if(!JSValueIsNull(context, value)) {
175                 if(!JSValueIsObject(context, value)) {
176                     throw TypeMismatchException("Value is not Object");
177                 }
178
179                 JSValueRef ex;
180                 object = JSValueToObject(context, value, &ex);
181                 if(ex){
182                     throw TypeMismatchException("Can't convert to Object");
183                 }                
184
185                 if(!JSObjectIsFunction(context, object)) {
186                     throw TypeMismatchException("Not function");
187                 }
188             }
189             else {
190                 LoggerD("onmessage() is NULL");
191             }
192             
193             return priv->setOnMessage(context, object);
194         }
195         else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_ONCLOSE)) {
196             JSObjectRef object = NULL;
197             if(!JSValueIsNull(context, value)) {
198                 if(!JSValueIsObject(context, value)) {
199                     throw TypeMismatchException("Value is not Object");
200                 }
201
202                 JSValueRef ex;
203                 object = JSValueToObject(context, value, &ex);
204                 if(ex){
205                     throw TypeMismatchException("Can't convert to Object");
206                 }                
207
208                 if(!JSObjectIsFunction(context, object)) {
209                     throw TypeMismatchException("Not function");
210                 }
211             }
212             else {
213                 LoggerD("onclose() is NULL");
214             }
215             
216             return priv->setOnClose(context, object);
217         }
218         else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_ONERROR)) {
219             JSObjectRef object = NULL;
220             if(!JSValueIsNull(context, value)) {
221                 if(!JSValueIsObject(context, value)) {
222                     throw TypeMismatchException("Value is not Object");
223                 }
224
225                 JSValueRef ex;
226                 object = JSValueToObject(context, value, &ex);
227                 if(ex){
228                     throw TypeMismatchException("Can't convert to Object");
229                 }                
230
231                 if(!JSObjectIsFunction(context, object)) {
232                     throw TypeMismatchException("Not function");
233                 }
234             }
235             else {
236                 LoggerD("onerror() is NULL");
237             }
238             
239             return priv->setOnError(context, object);
240         }
241     } catch (const BasePlatformException &err) {
242         JSWebAPIException::throwException(context, exception, err);
243     }
244
245     return false;
246 }
247
248 JSValueRef JSBluetoothSocket::writeData(JSContextRef context,
249         JSObjectRef object,
250         JSObjectRef thisObject,
251         size_t argumentCount,
252         const JSValueRef arguments[],
253         JSValueRef* exception)
254 {
255     LoggerD("Enter");
256     TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
257
258     // Access Check
259     AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_SOCKET_API_WRITE_DATA);
260     TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
261
262     try {
263         // Check whether Bluetooth is supported or not
264         if(!BluetoothAdapter::isBluetoothSupported()) {
265             throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
266         }
267     
268         // Private Object
269         BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(thisObject));
270         if (!priv) {
271             throw DeviceAPI::Common::UnknownException("Private object is NULL.");
272         }
273     
274         ArgumentValidator validator(context, argumentCount, arguments);
275
276         JSObjectRef dataArrayObj  = validator.toArrayObject(0);  // data
277         size_t size = JSGetArrayLength(context, dataArrayObj);
278         char *buffer = new char[size];
279         for(size_t i = 0; i < size; ++i) {
280             JSValueRef element = JSGetArrayElement(context, dataArrayObj, i);
281             buffer[i] = static_cast<char>(JSUtil::JSValueToByte(context, element));
282         }
283         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
284
285         return JSUtil::toJSValueRef(context, priv->writeData(buffer, size));
286     } catch (const BasePlatformException &err) {
287         return JSWebAPIException::throwException(context, exception, err);
288     } catch (...) {
289         DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothSocket.writeData().");
290         return JSWebAPIException::throwException(context, exception, err);
291     }
292 }
293
294 JSValueRef JSBluetoothSocket::readData(JSContextRef context,
295         JSObjectRef object,
296         JSObjectRef thisObject,
297         size_t argumentCount,
298         const JSValueRef arguments[],
299         JSValueRef* exception)
300 {
301     LoggerD("Enter");
302     TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
303     
304     // Access Check
305     AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_SOCKET_API_READ_DATA);
306     TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
307
308     try {
309         // Check whether Bluetooth is supported or not
310         if(!BluetoothAdapter::isBluetoothSupported()) {
311             throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
312         }
313     
314         // Private Object
315         BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(thisObject));
316         if (!priv) {
317             throw DeviceAPI::Common::UnknownException("Private object is NULL.");
318         }
319
320         std::vector<signed char> data = priv->readData();
321         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
322         
323         return JSUtil::toJSValueRef_(context, data);
324     } catch (const BasePlatformException &err) {
325         return JSWebAPIException::throwException(context, exception, err);
326     } catch (...) {
327         DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothSocket.readData().");
328         return JSWebAPIException::throwException(context, exception, err);
329     }
330 }
331
332 JSValueRef JSBluetoothSocket::close(JSContextRef context,
333         JSObjectRef object,
334         JSObjectRef thisObject,
335         size_t argumentCount,
336         const JSValueRef arguments[],
337         JSValueRef* exception)
338 {
339     LoggerD("Enter");
340     TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
341     
342     // Access Check
343     AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_SOCKET_API_CLOSE);
344     TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
345
346     try {
347         // Check whether Bluetooth is supported or not
348         if(!BluetoothAdapter::isBluetoothSupported()) {
349             throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
350         }
351     
352         // Private Object
353         BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(thisObject));
354         if (!priv) {
355             throw DeviceAPI::Common::UnknownException("Private object is NULL.");
356         }
357
358         priv->close();
359         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
360         
361         return JSValueMakeUndefined(context);
362     } catch (const BasePlatformException &err) {
363         return JSWebAPIException::throwException(context, exception, err);
364     } catch (...) {
365         DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothSocket.close().");
366         return JSWebAPIException::throwException(context, exception, err);
367     }
368 }
369
370
371
372 } // Bluetooth
373 } // DeviceAPI