Update change log and spec for wrt-plugins-tizen_0.4.70
[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 <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     LoggerD("Enter");
164     
165     try {
166         BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(object));
167         if (!priv) {
168             throw TypeMismatchException("Private object is NULL");
169         }
170
171         if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_ONMESSAGE)) {
172             JSObjectRef object = NULL;
173             if(!JSValueIsNull(context, value)) {
174                 if(!JSValueIsObject(context, value)) {
175                     throw TypeMismatchException("Value is not Object");
176                 }
177
178                 object = JSUtil::JSValueToObject(context, value);
179
180                 if(!JSObjectIsFunction(context, object)) {
181                     throw TypeMismatchException("Not function");
182                 }
183             }
184             else {
185                 LoggerD("onmessage() is NULL");
186             }
187             
188             return priv->setOnMessage(context, object);
189         }
190         else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_ONCLOSE)) {
191             JSObjectRef object = NULL;
192             if(!JSValueIsNull(context, value)) {
193                 if(!JSValueIsObject(context, value)) {
194                     throw TypeMismatchException("Value is not Object");
195                 }
196
197                 object = JSUtil::JSValueToObject(context, value);
198
199                 if(!JSObjectIsFunction(context, object)) {
200                     throw TypeMismatchException("Not function");
201                 }
202             }
203             else {
204                 LoggerD("onclose() is NULL");
205             }
206             
207             return priv->setOnClose(context, object);
208         }
209         else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_ONERROR)) {
210             JSObjectRef object = NULL;
211             if(!JSValueIsNull(context, value)) {
212                 if(!JSValueIsObject(context, value)) {
213                     throw TypeMismatchException("Value is not Object");
214                 }
215
216                 object = JSUtil::JSValueToObject(context, value);
217
218                 if(!JSObjectIsFunction(context, object)) {
219                     throw TypeMismatchException("Not function");
220                 }
221             }
222             else {
223                 LoggerD("onerror() is NULL");
224             }
225             
226             return priv->setOnError(context, object);
227         }
228     } catch (const BasePlatformException &err) {
229         JSWebAPIErrorFactory::postException(context, exception, err);
230     }
231
232     return false;
233 }
234
235 JSValueRef JSBluetoothSocket::writeData(JSContextRef context,
236         JSObjectRef object,
237         JSObjectRef thisObject,
238         size_t argumentCount,
239         const JSValueRef arguments[],
240         JSValueRef* exception)
241 {
242         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
243
244     try {
245         // Private Object
246         BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(thisObject));
247         if (!priv) {
248             throw DeviceAPI::Common::UnknownException("Private object is NULL.");
249         }
250
251                 // Access Check    
252             TIME_TRACER_ITEM_BEGIN("writeData::ACE", 1);        
253                 TIZEN_CHECK_ACCESS(context, exception, priv, BLUETOOTH_SOCKET_API_WRITE_DATA);          
254             TIME_TRACER_ITEM_END("writeData::ACE", 1);
255
256         ArgumentValidator validator(context, argumentCount, arguments);
257
258         JSObjectRef dataArrayObj  = validator.toArrayObject(0);  // data
259         size_t size = JSGetArrayLength(context, dataArrayObj);
260         char *buffer = new char[size];
261         for(size_t i = 0; i < size; ++i) {
262             JSValueRef element = JSGetArrayElement(context, dataArrayObj, i);
263             buffer[i] = static_cast<char>(JSUtil::JSValueToByte(context, element));
264         }
265
266         JSValueRef result = JSUtil::toJSValueRef(context, priv->writeData(buffer, size));
267         delete buffer;
268         TIME_TRACER_ITEM_END(__FUNCTION__, 1);;
269
270         return result;
271     } catch (const BasePlatformException &err) {
272         return JSWebAPIErrorFactory::postException(context, exception, err);
273     } catch (...) {
274         DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothSocket.writeData().");
275         return JSWebAPIErrorFactory::postException(context, exception, err);
276     }
277 }
278
279 JSValueRef JSBluetoothSocket::readData(JSContextRef context,
280         JSObjectRef object,
281         JSObjectRef thisObject,
282         size_t argumentCount,
283         const JSValueRef arguments[],
284         JSValueRef* exception)
285 {
286         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
287
288
289     try {
290         // Private Object
291         BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(thisObject));
292         if (!priv) {
293             throw DeviceAPI::Common::UnknownException("Private object is NULL.");
294         }
295                 
296                 // Access Check
297                 TIME_TRACER_ITEM_BEGIN("readData::ACE", 1);
298                 TIZEN_CHECK_ACCESS(context, exception, priv, BLUETOOTH_SOCKET_API_READ_DATA);           
299                 TIME_TRACER_ITEM_END("readData::ACE", 1);
300                 
301
302         std::vector<signed char> data = priv->readData();
303         TIME_TRACER_ITEM_END(__FUNCTION__, 1);
304         
305         return JSUtil::toJSValueRef_(context, data);
306     } catch (const BasePlatformException &err) {
307         return JSWebAPIErrorFactory::postException(context, exception, err);
308     } catch (...) {
309         DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothSocket.readData().");
310         return JSWebAPIErrorFactory::postException(context, exception, err);
311     }
312 }
313
314 JSValueRef JSBluetoothSocket::close(JSContextRef context,
315         JSObjectRef object,
316         JSObjectRef thisObject,
317         size_t argumentCount,
318         const JSValueRef arguments[],
319         JSValueRef* exception)
320 {
321     TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);;
322
323     try {
324         // Private Object
325         BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(thisObject));
326         if (!priv) {
327             throw DeviceAPI::Common::UnknownException("Private object is NULL.");
328         }
329
330                 // Access Check
331                 TIME_TRACER_ITEM_BEGIN("close::ACE", 1);
332                 TIZEN_CHECK_ACCESS(context, exception, priv, BLUETOOTH_SOCKET_API_CLOSE);               
333                 TIME_TRACER_ITEM_END("close::ACE", 1);
334                 
335
336         priv->close();
337         TIME_TRACER_ITEM_END(__FUNCTION__, 1);;
338         
339         return JSValueMakeUndefined(context);
340     } catch (const BasePlatformException &err) {
341         return JSWebAPIErrorFactory::postException(context, exception, err);
342     } catch (...) {
343         DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothSocket.close().");
344         return JSWebAPIErrorFactory::postException(context, exception, err);
345     }
346 }
347
348
349
350 } // Bluetooth
351 } // DeviceAPI