wrt-plugins-tizen_0.4.23
[framework/web/wrt-plugins-tizen.git] / src / MessagePort / JSLocalMessagePort.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 /**
19  * @file        JSLocalMessagePort.cpp
20  * @author      Kisub Song (kisubs.song@samsung.com)
21  * @version     0.1
22  * @brief       Implementation of the JSLocalMessagePort class
23  */
24
25 #include "JSLocalMessagePort.h"
26 #include <CommonsJavaScript/Validator.h>
27 #include <CommonsJavaScript/Converter.h>
28 #include <CommonsJavaScript/JSCallbackManager.h>
29 #include <CommonsJavaScript/JSUtils.h>
30 #include <JSWebAPIException.h>
31 #include <ArgumentValidator.h>
32 #include <TimeTracer.h>
33 #include "EventLocalMessagePortAddMessagePortListener.h"
34 #include "EventLocalMessagePortRemoveMessagePortListener.h"
35 #include "MessagePortListenerManager.h"
36 #include "MessagePortJSUtil.h"
37 #include <Logger.h>
38
39 #define TIZEN_LOCAL_MESSAGE_PORT                                "LocalMessagePort"
40
41 #define TIZEN_LOCAL_MESSAGE_PORT_MESSAGE_PORT_NAME                  "messagePortName"
42 #define TIZEN_LOCAL_MESSAGE_PORT_IS_TRUSTED                     "isTrusted"
43
44 #define TIZEN_LOCAL_MESSAGE_PORT_ADD_MESSAGE_PORT_LISTENER      "addMessagePortListener"
45 #define TIZEN_LOCAL_MESSAGE_PORT_REMOVE_MESSAGE_PORT_LISTENER   "removeMessagePortListener"
46
47 namespace DeviceAPI {
48 namespace MessagePort {
49
50 using namespace std;
51 using namespace DeviceAPI::Common;
52 using namespace WrtDeviceApis::Commons;
53 using namespace WrtDeviceApis::CommonsJavaScript;
54
55 JSClassRef JSLocalMessagePort::m_jsClassRef = NULL;
56
57 JSClassDefinition JSLocalMessagePort::m_classInfo = {
58         0,
59         kJSClassAttributeNone,
60         TIZEN_LOCAL_MESSAGE_PORT,
61         0,
62         m_property,
63         m_function,
64         Initialize,
65         Finalize,
66         NULL, //HasProperty,
67         NULL, //GetProperty,
68         NULL, //SetProperty,
69         NULL, //DeleteProperty,
70         NULL, //GetPropertyNames,
71         NULL, //CallAsFunction,
72         NULL, //CallAsConstructor,
73         NULL, //HasInstance,
74         NULL, //ConvertToType,
75 };
76
77 JSStaticValue JSLocalMessagePort::m_property[] = {
78         { TIZEN_LOCAL_MESSAGE_PORT_MESSAGE_PORT_NAME, getMessagePortName, NULL, kJSPropertyAttributeReadOnly },
79         { TIZEN_LOCAL_MESSAGE_PORT_IS_TRUSTED, getIsTrusted, NULL, kJSPropertyAttributeReadOnly },
80         { 0, 0, 0, 0 }
81 };
82
83 JSStaticFunction JSLocalMessagePort::m_function[] = {
84         { TIZEN_LOCAL_MESSAGE_PORT_ADD_MESSAGE_PORT_LISTENER, addMessagePortListener, kJSPropertyAttributeNone },
85         { TIZEN_LOCAL_MESSAGE_PORT_REMOVE_MESSAGE_PORT_LISTENER, removeMessagePortListener, kJSPropertyAttributeNone },
86         { 0, 0, 0 }
87 };
88
89 const JSClassDefinition* JSLocalMessagePort::getClassInfo()
90 {
91         return &m_classInfo;
92 }
93
94 const JSClassRef JSLocalMessagePort::getClassRef()
95 {
96         LoggerI("entered");
97         if (!m_jsClassRef) {
98                 m_jsClassRef = JSClassCreate(&m_classInfo);
99         }
100         return m_jsClassRef;
101 }
102
103 void JSLocalMessagePort::Initialize(JSContextRef context,
104                 JSObjectRef object)
105 {
106 }
107
108 void JSLocalMessagePort::Finalize(JSObjectRef object)
109 {
110         LocalMessagePortController *priv =
111                 static_cast<LocalMessagePortController*>(JSObjectGetPrivate(object));
112
113         delete priv;
114 }
115
116 bool JSLocalMessagePort::isObjectOfClass(JSContextRef context, JSValueRef value)
117 {
118         return JSValueIsObjectOfClass(context, value, getClassRef());
119 }
120
121 LocalMessagePortPtr JSLocalMessagePort::getLocalMessagePort(JSContextRef context, JSValueRef value)
122 {
123         if (!isObjectOfClass(context, value))
124                 throw TypeMismatchException("value is not a LocalMessagePort object");
125
126         JSObjectRef object = JSValueToObject(context, value, NULL);
127         if (!object)
128                 throw TypeMismatchException("value is not a object");
129
130         LocalMessagePortController *priv = static_cast<LocalMessagePortController*>(JSObjectGetPrivate(object));
131         if (!priv)
132                 throw TypeMismatchException("cannot get priv object from LocalMessagePort object");
133
134         return priv->getObject();
135 }
136
137 LocalMessagePortPtr JSLocalMessagePort::getPrivData(JSObjectRef object)
138 {
139         LocalMessagePortController *priv =
140                 static_cast<LocalMessagePortController*>(JSObjectGetPrivate(object));
141
142         if (priv)
143                 return priv->getObject();
144
145         Throw(NullPointerException);
146 }
147
148 JSValueRef JSLocalMessagePort::getMessagePortName(JSContextRef context,
149                 JSObjectRef object,
150                 JSStringRef propertyName,
151                 JSValueRef* exception)
152 {
153         try
154         {
155                 LocalMessagePortPtr localMessagePort = getPrivData(object);
156                 return JSUtil::toJSValueRef(context, localMessagePort->getMessagePortName());
157         }
158         catch(BasePlatformException &e)
159         {
160                 LoggerW("trying to get incorrect value");
161         }
162
163         return JSValueMakeUndefined(context);
164 }
165
166 JSValueRef JSLocalMessagePort::getIsTrusted(JSContextRef context,
167                 JSObjectRef object,
168                 JSStringRef propertyName,
169                 JSValueRef* exception)
170 {
171         try
172         {
173                 LocalMessagePortPtr localMessagePort = getPrivData(object);
174                 return JSUtil::toJSValueRef(context, localMessagePort->getIsTrusted());
175         }
176         catch(BasePlatformException &e)
177         {
178                 LoggerW("trying to get incorrect value");
179         }
180
181         return JSValueMakeUndefined(context);
182 }
183
184 JSValueRef JSLocalMessagePort::addMessagePortListener(JSContextRef context,
185                 JSObjectRef object,
186                 JSObjectRef thisObject,
187                 size_t argumentCount,
188                 const JSValueRef arguments[],
189                 JSValueRef* exception)
190 {
191         LoggerD("entered");
192         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
193         LocalMessagePortPtr localMessagePort;
194         JSContextRef gContext;
195         LocalMessagePortController *controller;
196
197         try
198         {
199                 controller = static_cast<LocalMessagePortController*>(JSObjectGetPrivate(thisObject));
200                 if (!controller)
201                         throw TypeMismatchException("Wrong object");
202
203                 localMessagePort = controller->getObject();
204                 gContext = controller->getContext();
205         }
206         catch(BasePlatformException &e)
207         {
208                 LoggerE("No private object");
209                 return JSWebAPIException::throwException(context, exception, e);
210         }
211
212         JSValueRef listener = NULL;
213
214         ArgumentValidator validator(context, argumentCount, arguments);
215
216         try
217         {
218                 listener = validator.toFunction(0, false);
219         }
220         catch(BasePlatformException &e)
221         {
222                 return JSWebAPIException::throwException(context, exception, e);
223         }
224
225         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
226
227         callbackManager->setOnSuccess(listener);
228
229         EventLocalMessagePortListenerEmitterPtr emitter(new EventLocalMessagePortListenerEmitter());
230
231         emitter->setEventPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager));
232         emitter->setListener(controller);
233
234         EventLocalMessagePortAddMessagePortListenerPtr dplEvent(new EventLocalMessagePortAddMessagePortListener());
235
236         dplEvent->setEmitter(emitter);
237         dplEvent->setForSynchronousCall();
238
239         Try
240         {
241                 localMessagePort->addMessagePortListener(dplEvent);
242         }
243         Catch(Exception)
244         {
245                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
246                 return JSWebAPIException::throwException(context, exception,
247                                 UnknownException("Plugin's internal error"));
248         }
249
250         if (!dplEvent->getResult() || !dplEvent->getIdIsSet())
251         {
252                 switch (dplEvent->getExceptionCode())
253                 {
254                 case ExceptionCodes::InvalidArgumentException:
255                         return JSWebAPIException::throwException(context, exception,
256                                         UnknownException("Plugin's internal error."));
257                         break;
258                 case ExceptionCodes::PlatformException:
259                         return JSWebAPIException::throwException(context, exception,
260                                         UnknownException("The method cannot proceed due to a severe system error."));
261                         break;
262                 default:
263                         return JSWebAPIException::throwException(context, exception,
264                                         UnknownException("Internal error"));
265                         break;
266                 }
267         }
268
269         long watchId = dplEvent->getId();
270
271         MessagePortsChangeListenerCancellerPtr canceller = MessagePortsChangeListenerCancellerPtr(new MessagePortsChangeListenerCanceller(gContext, thisObject, watchId));
272         DeviceAPI::Common::IListenerItemPtr listenerItem = DPL::StaticPointerCast<DeviceAPI::Common::IListenerItem>(canceller);
273         MessagePortListenerManagerSingleton::Instance().registerListener(listenerItem, gContext);
274
275         JSValueRef result;
276         try
277         {
278                 result = JSUtil::toJSValueRef(context, watchId);
279         }
280         catch(BasePlatformException &e)
281         {
282                 LoggerE("Error on conversion : " << e.getMessage());
283                 return JSWebAPIException::throwException(context, exception,
284                                 UnknownException("Internal error"));
285         }
286
287         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
288         return result;
289 }
290
291 JSValueRef JSLocalMessagePort::removeMessagePortListener(JSContextRef context,
292                 JSObjectRef object,
293                 JSObjectRef thisObject,
294                 size_t argumentCount,
295                 const JSValueRef arguments[],
296                 JSValueRef* exception)
297 {
298         LoggerD("entered");
299         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
300         LocalMessagePortPtr localMessagePort;
301         JSContextRef gContext;
302         LocalMessagePortController *controller;
303
304         try
305         {
306                 controller = static_cast<LocalMessagePortController*>(JSObjectGetPrivate(thisObject));
307                 if (!controller)
308                         throw TypeMismatchException("Wrong object");
309
310                 localMessagePort = controller->getObject();
311                 gContext = controller->getContext();
312         }
313         catch(BasePlatformException &e)
314         {
315                 LoggerE("No private object");
316                 return JSWebAPIException::throwException(context, exception, e);
317         }
318
319         long watchId = 0;
320
321         ArgumentValidator validator(context, argumentCount, arguments);
322
323         try
324         {
325                 watchId = validator.toLong(0, false);
326         }
327         catch(BasePlatformException &e)
328         {
329                 return JSWebAPIException::throwException(context, exception, e);
330         }
331
332         EventLocalMessagePortRemoveMessagePortListenerPtr dplEvent(new EventLocalMessagePortRemoveMessagePortListener());
333
334         dplEvent->setId(watchId);
335         dplEvent->setForSynchronousCall();
336
337         Try
338         {
339                 localMessagePort->removeMessagePortListener(dplEvent);
340         }
341         Catch(Exception)
342         {
343                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
344                 return JSWebAPIException::throwException(context, exception,
345                                 UnknownException("Internal error"));
346         }
347
348         MessagePortsChangeListenerCancellerPtr canceller =
349                         MessagePortsChangeListenerCancellerPtr(new MessagePortsChangeListenerCanceller(gContext, thisObject, watchId));
350         DeviceAPI::Common::IListenerItemPtr listenerItem = DPL::StaticPointerCast<DeviceAPI::Common::IListenerItem>(canceller);
351         MessagePortListenerManagerSingleton::Instance().unregisterListener(listenerItem);
352
353         if (!dplEvent->getResult())
354         {
355                 stringstream oss;
356                 switch (dplEvent->getExceptionCode())
357                 {
358                 case ExceptionCodes::InvalidArgumentException:
359                         return JSWebAPIException::throwException(context, exception,
360                                         InvalidValuesException(oss.str().c_str()));
361                         break;
362                 case ExceptionCodes::NotFoundException:
363                         oss << "No watchId (" << watchId << ") has been registered.";
364                         return JSWebAPIException::throwException(context, exception,
365                                         NotFoundException(oss.str().c_str()));
366                         break;
367                 case ExceptionCodes::PlatformException:
368                         return JSWebAPIException::throwException(context, exception,
369                                         UnknownException("The method cannot proceed due to a severe system error."));
370                         break;
371                 default:
372                         return JSWebAPIException::throwException(context, exception,
373                                         UnknownException("Internal error."));
374                         break;
375                 }
376         }
377
378         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
379         return JSValueMakeUndefined(context);
380 }
381
382 } // MessagePort
383 } // DeviceAPI