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