Merge "Fix MenuIconN() API" into tizen_2.1
[platform/framework/native/appfw.git] / src / io / FIo_MessagePortProxy.cpp
1 //
2 // Open Service Platform
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        FIo_MessagePortProxy.cpp
20  * @brief       This is the implementation file for the _MessagePortProxy class.
21  *
22  */
23
24 #include <string.h>
25 #include <typeinfo>
26 #include <unique_ptr.h>
27
28 #include <package_manager.h>
29
30 #include <message-port.h>
31
32 #include <FBaseSysLog.h>
33 #include <FBase_StringConverter.h>
34 #include <FApp_AppInfo.h>
35
36 #include "FIo_MessagePortProxy.h"
37
38 using namespace std;
39
40 using namespace Tizen::App;
41 using namespace Tizen::Io;
42 using namespace Tizen::Base;
43 using namespace Tizen::Base::Collection;
44 using namespace Tizen::Base::Runtime;
45
46 namespace Tizen { namespace Io
47 {
48
49 static const int MAX_MESSAGE_SIZE = 16 * 1024;
50
51 static void
52 ConvertBundleToMap(const char *pKey, const int type, const bundle_keyval_t *pVal, void *pData)
53 {
54         //SysLog(NID_IO, "CB key = %s", pKey);
55
56         HashMap* pMap = static_cast<HashMap*>(pData);
57
58         if (pKey && pVal && pMap)
59         {
60                 size_t size = 0;
61                 char* pStr = NULL;
62                 switch (type)
63                 {
64                         case BUNDLE_TYPE_STR:
65                                 bundle_keyval_get_basic_val(const_cast<bundle_keyval_t*>(pVal), reinterpret_cast<void**>(&pStr), &size);
66                                 if (pStr)
67                                 {
68                                         pMap->Add(new (std::nothrow) String(pKey), new (std::nothrow) String(pStr));
69                                 }
70
71                                 break;
72                         case BUNDLE_TYPE_BYTE:
73                                 bundle_keyval_get_basic_val(const_cast<bundle_keyval_t*>(pVal), reinterpret_cast<void**>(&pStr), &size);
74
75                                 //SysLog(NID_IO, "Bundle byte value = %s, size = %d", pStr, size);
76
77                                 if (pStr)
78                                 {
79                                         ByteBuffer* pBuffer = new (std::nothrow) ByteBuffer();
80                                         SysTryReturnVoidResult(NID_IO, pMap != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
81                                         result r = pBuffer->Construct(size);
82                                         SysTryCatch(NID_IO, r == E_SUCCESS, delete pBuffer, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
83
84                                         r = pBuffer->SetArray((const byte*)pStr, 0, size);
85                                         SysTryCatch(NID_IO, r == E_SUCCESS, delete pBuffer, E_INVALID_ARG, "[E_INVALID_ARG] The buffer argument is invalid.");
86
87                                         pBuffer->Flip();
88
89                                         pMap->Add(new (std::nothrow) String(pKey), pBuffer);
90                                 }
91
92                                 break;
93                         default:
94                                 SysLog(NID_APP, "Invalid type for %s : %d", pKey, type);
95                                 break;
96                 }
97         }
98
99 CATCH:
100         return;
101 }
102
103 static void
104 OnMessageReceived(int id, const char* remote_app_id, const char* remote_port, bool trusted_port, bundle* data)
105 {
106         SysLog(NID_IO, "Message received");
107
108         _MessagePortProxy* p = _MessagePortProxy::GetProxy();
109
110         int ret = 0;
111         char* pLocalPort = null;
112
113         ret = messageport_get_local_port_name(id, &pLocalPort);
114         if (pLocalPort == null)
115         {
116                 SysSecureLog(NID_IO, "No local port for id: %d", id);
117
118                 bundle_free(data);
119                 return;
120         }
121
122         //SysLog(NID_IO, "local port name: %s", pLocalPort);
123
124         _IMessagePortListener* pListener = null;
125         p->__listeners.GetValue(pLocalPort, pListener);
126
127         free(pLocalPort);
128
129         if (pListener != null)
130         {
131                 HashMap* pMap = new (std::nothrow) HashMap(SingleObjectDeleter);
132                 SysTryCatch(NID_IO, pMap != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
133
134                 result r = pMap->Construct();
135                 SysTryCatch(NID_IO, r == E_SUCCESS, delete pMap, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
136
137                 bundle_foreach(data, ConvertBundleToMap, pMap);
138
139                 if (remote_app_id == null) // Uni-directional
140                 {
141                         pListener->OnMessageReceivedN(pMap);
142                 }
143                 else // Bi-directional
144                 {
145                         SysSecureLog(NID_IO, "Message received from [%s:%s], trusted: %d", remote_app_id, remote_port, trusted_port);
146
147                         pListener->OnMessageReceivedN(remote_app_id, remote_port, trusted_port, pMap);
148                 }
149         }
150
151 CATCH:
152         bundle_free(data);
153 }
154
155 static void
156 OnTrustedMessageReceived(int id, const char* remote_app_id, const char* remote_port, bool trusted_port, bundle* data)
157 {
158         SysLog(NID_IO, "Trusted message received");
159
160         _MessagePortProxy* p = _MessagePortProxy::GetProxy();
161
162         int ret = 0;
163         char* pLocalPort = null;
164         ret = messageport_get_local_port_name(id, &pLocalPort);
165         if (pLocalPort == null)
166         {
167                 SysSecureLog(NID_IO, "No local port for id: %d", id);
168
169                 bundle_free(data);
170                 return;
171         }
172
173         _IMessagePortListener* pListener = null;
174         p->__trustedListeners.GetValue(pLocalPort, pListener);
175
176         free(pLocalPort);
177
178         if (pListener != null)
179         {
180                 HashMap* pMap = new (std::nothrow) HashMap(SingleObjectDeleter);
181                 SysTryCatch(NID_IO, pMap != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
182
183                 result r = pMap->Construct();
184                 SysTryCatch(NID_IO, r == E_SUCCESS, delete pMap, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
185
186                 bundle_foreach(data, ConvertBundleToMap, pMap);
187
188                 if (remote_app_id == null) // Uni-directional
189                 {
190                         pListener->OnMessageReceivedN(pMap);
191                 }
192                 else // Bi-directional
193                 {
194                         SysSecureLog(NID_IO, "Trusted message received from [%s:%s], trusted: %d", remote_app_id, remote_port, trusted_port);
195
196                         pListener->OnMessageReceivedN(remote_app_id, remote_port, trusted_port, pMap);
197                 }
198         }
199
200 CATCH:
201         bundle_free(data);
202 }
203
204 _MessagePortProxy::_MessagePortProxy(void)
205 {
206 }
207
208 _MessagePortProxy::~_MessagePortProxy(void)
209 {
210 }
211
212 result
213 _MessagePortProxy::Construct(void)
214 {
215         static _StringHashProvider hashProvider;
216         static _StringComparer stringComparer;
217
218         __listeners.Construct(0, 0, hashProvider, stringComparer);
219         __trustedListeners.Construct(0, 0, hashProvider, stringComparer);
220         __ids.Construct(0, 0, hashProvider, stringComparer);
221         __trustedIds.Construct(0, 0, hashProvider, stringComparer);
222
223         __appId = _AppInfo::GetApplicationId();
224
225         return E_SUCCESS;
226 }
227
228
229 result
230 _MessagePortProxy::RegisterMessagePort(const String& localPort, bool isTrusted,
231                                                                         const _IMessagePortListener& listener)
232 {
233         SysSecureLog(NID_IO, "Register a message port : [%ls:%ls]", __appId.GetPointer(), localPort.GetPointer());
234
235         result r = E_SUCCESS;
236         int ret = 0;
237         bool contain = false;
238
239         unique_ptr<char[]> pLocal(_StringConverter::CopyToCharArrayN(localPort));
240
241         if (!isTrusted)
242         {
243                 ret = messageport_register_local_port(pLocal.get(), OnMessageReceived);
244                 SysTryReturnResult(NID_IO, ret >= 0, E_SYSTEM, "Failed to register the local message port. %d", ret);
245
246                 __listeners.ContainsKey(localPort, contain);
247
248                 if (!contain)
249                 {
250                         __listeners.Add(localPort, const_cast<_IMessagePortListener*>(&listener));
251                         __ids.Add(localPort, ret);
252                 }
253                 else
254                 {
255                         __listeners.SetValue(localPort, const_cast<_IMessagePortListener*>(&listener));
256                         __ids.SetValue(localPort, ret);
257                 }
258
259         }
260         else
261         {
262                 ret = messageport_register_trusted_local_port(pLocal.get(), OnTrustedMessageReceived);
263                 SysTryReturnResult(NID_IO, ret >= 0, E_SYSTEM, "Failed to register the trusted local message port. %d", ret);
264
265                 __trustedListeners.ContainsKey(localPort, contain);
266
267                 if (!contain)
268                 {
269                         __trustedListeners.Add(localPort, const_cast<_IMessagePortListener*>(&listener));
270                         __trustedIds.Add(localPort, ret);
271                 }
272                 else
273                 {
274                         __trustedListeners.SetValue(localPort, const_cast<_IMessagePortListener*>(&listener));
275                         __trustedIds.SetValue(localPort, ret);
276                 }
277
278         }
279
280         return E_SUCCESS;
281 }
282
283 result
284 _MessagePortProxy::RequestRemotePort(const AppId& remoteAppId,
285                                                                         const String& remotePort,
286                                                                         bool isTrusted)
287 {
288         SysSecureLog(NID_IO, "Request a remote message port [%ls:%ls]", remoteAppId.GetPointer(), remotePort.GetPointer());
289
290         result r = E_SUCCESS;
291         int ret = 0;
292         bool exist = false;
293
294         unique_ptr<char[]> pAppId(_StringConverter::CopyToCharArrayN(remoteAppId));
295         unique_ptr<char[]> pPort(_StringConverter::CopyToCharArrayN(remotePort));
296
297         if (!isTrusted)
298         {
299                 ret = messageport_check_remote_port(pAppId.get(), pPort.get(), &exist);
300         }
301         else
302         {
303                 ret = messageport_check_trusted_remote_port(pAppId.get(), pPort.get(), &exist);
304         }
305
306         if (ret < 0)
307         {
308                 r = ConvertToResult(ret);
309
310                 SysTryReturnResult(NID_IO, r != E_CERTIFICATE_VERIFICATION_FAILED, E_CERTIFICATE_VERIFICATION_FAILED, "The target application is not signed with the same certificate.");
311
312                 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to request the remote message port.");
313
314                 return r;
315         }
316
317         SysTryReturnResult(NID_IO, exist, E_OBJ_NOT_FOUND, "The remote message port is not found.");
318
319         return E_SUCCESS;
320 }
321
322 result
323 _MessagePortProxy::SendMessage(const AppId& remoteAppId, const String& remotePort, bool isTrusted, const HashMap* pMap)
324 {
325         SysSecureLog(NID_IO, "Send a unidirectional message to remote port [%ls:%ls]", remoteAppId.GetPointer(), remotePort.GetPointer());
326
327         int ret = 0;
328         int size = 0;
329
330         // Convert Map to bundle
331         bundle* b = ConvertMapToBundleN(pMap, &size);
332         SysTryReturnResult(NID_IO, b != null, E_INVALID_ARG, "The argument is invalid.");
333         //SysTryReturnResult(NID_IO, size <= MAX_MESSAGE_SIZE, E_MAX_EXCEEDED, "The size of the message has exceeded the maximum limit.");
334
335         unique_ptr<char[]> pRemoteAppId(_StringConverter::CopyToCharArrayN(remoteAppId));
336         unique_ptr<char[]> pRemotePort(_StringConverter::CopyToCharArrayN(remotePort));
337
338         if (!isTrusted)
339         {
340                 ret = messageport_send_message(pRemoteAppId.get(), pRemotePort.get(), b);
341         }
342         else
343         {
344                 ret = messageport_send_trusted_message(pRemoteAppId.get(), pRemotePort.get(), b);
345         }
346
347         bundle_free(b);
348
349         if (ret < 0)
350         {
351                 result r = ConvertToResult(ret);
352
353                 SysTryReturnResult(NID_IO, r != E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "The remote message port is not found.");
354                 SysTryReturnResult(NID_IO, r != E_CERTIFICATE_VERIFICATION_FAILED, E_CERTIFICATE_VERIFICATION_FAILED, "The target application is not signed with the same certificate.");
355                 SysTryReturnResult(NID_IO, r != E_MAX_EXCEEDED, E_MAX_EXCEEDED, "The size of the message has exceeded the maximum limit.");
356
357                 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to request the remote message port.");
358
359                 return r;
360         }
361
362         return E_SUCCESS;
363 }
364
365 result
366 _MessagePortProxy::SendMessage(const String& localPort, bool isTrustedLocal, const AppId& remoteAppId, const String& remotePort, bool isTrustedRemote, const HashMap* pMap)
367 {
368         SysSecureLog(NID_IO, "Send a bidirectional message from [%ls:%ls] to [%ls:%ls]", __appId.GetPointer(), localPort.GetPointer(), remoteAppId.GetPointer(), remotePort.GetPointer());
369
370         result r = E_SUCCESS;
371         int id = 0;
372
373         if (!isTrustedLocal)
374         {
375                 r = __ids.GetValue(localPort, id);
376         }
377         else
378         {
379                 r = __trustedIds.GetValue(localPort, id);
380         }
381
382         SysTryReturnResult(NID_IO, r == E_SUCCESS, E_SYSTEM, "Internal system errors.");
383
384         int size = 0;
385
386         // Convert Map to bundle
387         bundle* b = ConvertMapToBundleN(pMap, &size);
388         SysTryReturnResult(NID_IO, b != null, E_INVALID_ARG, "The argument is invalid.");
389         //SysTryReturnResult(NID_IO, size <= MAX_MESSAGE_SIZE, E_MAX_EXCEEDED, "The size of the message has exceeded the maximum limit.");
390
391         unique_ptr<char[]> pRemoteAppId(_StringConverter::CopyToCharArrayN(remoteAppId));
392         unique_ptr<char[]> pRemotePort(_StringConverter::CopyToCharArrayN(remotePort));
393
394         int ret = 0;
395         if (!isTrustedRemote)
396         {
397                 ret = messageport_send_bidirectional_message(id, pRemoteAppId.get(), pRemotePort.get(), b);
398         }
399         else
400         {
401                 ret = messageport_send_bidirectional_trusted_message(id, pRemoteAppId.get(), pRemotePort.get(), b);
402         }
403
404         bundle_free(b);
405
406         if (ret < 0)
407         {
408                 result r = ConvertToResult(ret);
409
410                 SysTryReturnResult(NID_IO, r != E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "The remote message port is not found.");
411                 SysTryReturnResult(NID_IO, r != E_CERTIFICATE_VERIFICATION_FAILED, E_CERTIFICATE_VERIFICATION_FAILED, "The target application is not signed with the same certificate.");
412                 SysTryReturnResult(NID_IO, r != E_MAX_EXCEEDED, E_MAX_EXCEEDED, "The size of the message has exceeded the maximum limit.");
413
414                 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to request the remote message port.");
415
416                 return r;
417         }
418
419         return E_SUCCESS;
420 }
421
422 _MessagePortProxy*
423 _MessagePortProxy::GetProxy(void)
424 {
425         static _MessagePortProxy* pProxy = null;
426
427         if (pProxy == null)
428         {
429                 unique_ptr<_MessagePortProxy> p(new (std::nothrow) _MessagePortProxy);
430                 SysTryReturn(NID_IO, p != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
431
432                 result r = p->Construct();
433                 SysTryReturn(NID_IO, r == E_SUCCESS, null, E_SYSTEM, "[E_SYSTEM] Failed to initialize a  message port proxy.");
434
435                 pProxy = p.release();
436         }
437
438         SetLastResult(E_SUCCESS);
439         return pProxy;
440 }
441
442 result
443 _MessagePortProxy::ConvertToResult(int error)
444 {
445         SysLog(NID_IO, "Native error = %d", error);
446
447         switch (error)
448         {
449                 case MESSAGEPORT_ERROR_IO_ERROR:
450                         return E_SYSTEM;
451
452                 case MESSAGEPORT_ERROR_OUT_OF_MEMORY:
453                         return E_OUT_OF_MEMORY;
454
455                 case MESSAGEPORT_ERROR_INVALID_PARAMETER:
456                         return E_INVALID_ARG;
457
458                 case MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND:
459                         return E_OBJ_NOT_FOUND;
460
461                 case MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH:
462                         return E_CERTIFICATE_VERIFICATION_FAILED;
463
464                 case MESSAGEPORT_ERROR_MAX_EXCEEDED:
465                         return E_MAX_EXCEEDED;
466
467                 default:
468                         return E_SYSTEM;
469         }
470
471         return E_SYSTEM;
472 }
473
474 bundle*
475 _MessagePortProxy::ConvertMapToBundleN(const HashMap* pMap, int* pSize)
476 {
477         bundle *b = bundle_create();
478         int size = 0;
479
480         std::unique_ptr<IMapEnumerator> pEnum (pMap->GetMapEnumeratorN());
481         while(pEnum->MoveNext() == E_SUCCESS)
482         {
483                 const String* pKey = dynamic_cast<const String*>(pEnum->GetKey());
484                 const Object* pValue = pEnum->GetValue();
485
486                 if (pKey && pValue)
487                 {
488                         unique_ptr<char[]> pKeyData(_StringConverter::CopyToCharArrayN(*pKey));
489
490                         if (typeid(*pValue) == typeid(const String)) // String
491                         {
492                                 const String* pStr = static_cast<const String*>(pValue);
493                                 size += pStr->GetLength() * sizeof(wchar_t);
494
495                                 unique_ptr<char[]> pValueData(_StringConverter::CopyToCharArrayN(*pStr));
496
497                                 //SysLog(NID_IO, "key: %s, value: %s", pKeyData.get(), pValueData.get());
498
499                                 bundle_add(b, pKeyData.get(), pValueData.get());
500                         }
501                         else // ByteBuffer
502                         {
503                                 if (typeid(*pValue) == typeid(const ByteBuffer)) // ByteBuffer
504                                 {
505                                         const ByteBuffer* pBuffer = static_cast<const ByteBuffer*>(pValue);
506                                         size += pBuffer->GetLimit();
507
508                                         //SysLog(NID_IO, "Add a string key: %s, byte value: %s", pKeyData.get(), pBuffer->GetPointer());
509
510                                         bundle_add_byte(b, pKeyData.get(), pBuffer->GetPointer(), pBuffer->GetLimit());
511                                 }
512                                 else
513                                 {
514                                         SysLog(NID_IO, "The value type is not supported.");
515
516                                         bundle_free(b);
517                                         return null;
518                                 }
519                         }
520                 }
521                 else
522                 {
523                         SysLog(NID_IO, "The key type is not supported.");
524
525                         bundle_free(b);
526                         return null;
527                 }
528         }
529
530         *pSize = size;
531         return b;
532 }
533
534 }}