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