Merge "Update for handling callback of threads" into tizen_2.1
[platform/framework/native/appfw.git] / src / app / FApp_AppControlImpl.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                FApp_AppControlImpl.cpp
20  * @brief               This is the implementation for the Application Control class.
21  */
22
23 #include <new>
24 #include <typeinfo>
25 #include <unique_ptr.h>
26
27 #include <appsvc/appsvc.h>
28
29 #include <FAppAppControl.h>
30 #include <FAppAppManager.h>
31 #include <FAppPkgPackageAppInfo.h>
32 #include <FAppIAppControlEventListener.h>
33 #include <FAppIAppControlResponseListener.h>
34 #include <FBaseColHashMap.h>
35 #include <FBaseSysLog.h>
36
37 #include <FBaseRt_LibraryImpl.h>
38 #include <FIo_DirectoryImpl.h>
39
40 #include "FApp_AppControlImpl.h"
41 #include "FApp_AppControlManager.h"
42 #include "FApp_AppArg.h"
43 #include "FApp_AppImpl.h"
44 #include "FApp_AppControlRegistry.h"
45 #include "FApp_AppMessageImpl.h"
46 #include "FApp_AppInfo.h"
47 #include "FAppPkg_PackageManagerImpl.h"
48 #include "FApp_Aul.h"
49 #include "FApp_AppControlEventArg.h"
50 #include "FApp_AppControlResponseEvent.h"
51 #include "FBaseRt_ThreadImpl.h"
52
53 using namespace Tizen::Base;
54 using namespace Tizen::Base::Collection;
55 using namespace Tizen::Base::Runtime;
56 using namespace Tizen::App;
57 using namespace Tizen::App::Package;
58 using namespace Tizen::Io;
59
60 namespace
61 {
62
63 static const int _REQ_ID_INVALID = -1;
64
65 }
66
67 namespace Tizen { namespace App
68 {
69
70 const wchar_t TIZEN_OPERATION_MAIN[] = L"http://tizen.org/appcontrol/operation/main";
71 const char TIZEN_APPCONTROL_DATA_LEGACY[] = "http://tizen.org/appcontrol/data/legacyresult";
72
73 _AppControlImpl::_AppControlImpl(const AppControl& value)
74         : _appControl(value)
75         , _reqId(_REQ_ID_INVALID)
76         , _property(_APPCONTROL_PROPERTY_NONE)
77         , _processId(_REQ_ID_INVALID)
78 {
79         __appControlResponseEventList.Construct();
80 }
81
82 _AppControlImpl::~_AppControlImpl(void)
83 {
84         IEnumeratorT<int>* pEnum = __appControlResponseEventList.GetEnumeratorN();
85         IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = null;
86         if(pEnum != null)
87         {
88                 pResponseEventContainer = _AppControlManager::GetInstance()->GetAppControlResponseEventContainer();
89         }
90
91         while(pEnum->MoveNext() == E_SUCCESS)
92         {
93                 int reqId;
94                 pEnum->GetCurrent(reqId);
95                 if (pResponseEventContainer != null)
96                 {
97                         _AppControlResponseEvent* pResponseEvent = null;
98                         pResponseEventContainer->GetValue(reqId, pResponseEvent);
99                         delete pResponseEvent;
100
101                         pResponseEventContainer->Remove(reqId);
102                         SysLog(NID_APP, "pResponseEvent gets deleted. reqId(%d)", reqId);
103                 }
104         }
105         delete pEnum;
106 }
107
108 AppControl*
109 _AppControlImpl::CreateN(const String& path, const String& aId, const String& oId, const String& name, int prop)
110 {
111         SysTryReturn(NID_APP, !path.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] Path is empty.");
112         SysTryReturn(NID_APP, !aId.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] Provider Id is empty.");
113         SysTryReturn(NID_APP, !oId.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] Operation Id is empty.");
114
115         AppControl* pAc = new (std::nothrow) AppControl;
116         SysTryReturn(NID_APP, pAc != null, null, E_OUT_OF_MEMORY, "AppControl allocation failure.");
117
118         _AppControlImpl* pImpl = pAc->__pAppControlImpl;
119         SysTryReturn(NID_APP, pImpl != null, null, E_OUT_OF_MEMORY, "AppControlImpl instance must not be null.");
120
121         pImpl->_path = path;
122         pImpl->_provider = aId;
123         pImpl->_opId = oId;
124         // [FIXME] Proper App name setting
125         pImpl->_appName = name;
126         pImpl->_property = prop;
127
128         return pAc;
129 }
130
131 AppControl*
132 _AppControlImpl::CreateN(const AppId& appId, const String& operationId, bool changeAppId)
133 {
134         SysTryReturn(NID_APP, !appId.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] appId is empty.");
135
136         AppControl* pAc = new (std::nothrow) AppControl;
137         SysTryReturn(NID_APP, pAc != null, null, E_OUT_OF_MEMORY, "AppControl allocation failure.");
138
139         _AppControlImpl* pImpl = pAc->__pAppControlImpl;
140         SysTryReturn(NID_APP, pImpl != null, null, E_OUT_OF_MEMORY, "AppControlImpl instance must not be null.");
141
142         pImpl->_path = appId;
143         pImpl->_provider = appId;
144         pImpl->_opId = operationId;
145         //pImpl->_appName = appId;
146         pImpl->_property |= (_APPCONTROL_PROPERTY_OSP | _APPCONTROL_PROPERTY_PUBLIC);
147
148         if (changeAppId)
149         {
150                 pImpl->_property |= _APPCONTROL_PROPERTY_APPID_CHANGE;
151         }
152
153         return pAc;
154 }
155
156 AppControl*
157 _AppControlImpl::CreateN(const AppControl& ac)
158 {
159         const _AppControlImpl* pImpl = GetInstance(ac);
160         SysTryReturn(NID_APP, pImpl != null, null, E_INVALID_STATE, "AppControlImpl instance must not be null.");
161
162         return CreateN(pImpl->_path, pImpl->_provider, pImpl->_opId, pImpl->_appName, pImpl->_property);
163 }
164
165 const _AppControlImpl*
166 _AppControlImpl::GetInstance(const AppControl& ac)
167 {
168         return ac.__pAppControlImpl;
169 }
170
171 _AppControlImpl*
172 _AppControlImpl::GetInstance(AppControl& ac)
173 {
174         return ac.__pAppControlImpl;
175 }
176
177 result
178 _AppControlImpl::Start(const IList* pDataList, IAppControlEventListener* pListener)
179 {
180         SysLog(NID_APP, "Enter");
181         result r = E_SYSTEM;
182
183         if (_property & _APPCONTROL_PROPERTY_SLP)
184         {
185                 r = StartNative(pDataList, pListener);
186         }
187         else if (_property & _APPCONTROL_PROPERTY_OSP)
188         {
189                 r = StartOsp(pDataList, pListener);
190         }
191         else
192         {
193                 SysLogException(NID_APP, E_SYSTEM, "[E_SYSTEM] Invalid AppControl type(property %d)", _property);
194         }
195         SysLog(NID_APP, "Exit");
196
197         return r;
198 }
199
200 result
201 _AppControlImpl::Start(const String* pUriData, const String* pDataType, const IMap* pExtraData, IAppControlResponseListener* pListener)
202 {
203         SysLog(NID_APP, "Enter");
204         result r = E_SYSTEM;
205
206         if (_property & _APPCONTROL_PROPERTY_SLP)
207         {
208                 r = StartNative(pUriData, pDataType, pExtraData, pListener);
209         }
210         else if (_property & _APPCONTROL_PROPERTY_OSP)
211         {
212                 r = StartOsp(pUriData, pDataType, pExtraData, pListener);
213         }
214         else
215         {
216                 SysLogException(NID_APP, E_SYSTEM, "[E_SYSTEM] Invalid AppControl type(property %d)", _property);
217         }
218         SysLog(NID_APP, "Exit");
219
220         return r;
221 }
222
223 result
224 _AppControlImpl::FindAndStart(const String& operationId, const String* pUriPattern, const String* pDataType, const String* pCategory, const IMap* pExtraData, IAppControlResponseListener* pListener)
225 {
226         // [FIXME] valid argument size checking required
227         SysLog(NID_APP, "Enter");
228
229         std::unique_ptr<bundle, BundleDeleter> pBundle(bundle_create());
230         SysTryReturnResult(NID_APP, pBundle.get(), E_OUT_OF_MEMORY, "Bundle creation failure.");
231
232         _AppMessageImpl::SetOperation(pBundle.get(), operationId);
233
234         if (pUriPattern)
235         {
236                 _AppMessageImpl::SetUri(pBundle.get(), *pUriPattern);
237         }
238
239         if (pDataType)
240         {
241                 String mimeType = *pDataType;
242
243                 if ((*pDataType)[0] == L'.')
244                 {
245                         SysLog(NID_APP, "Extension to MIME conversion for %ls", pDataType->GetPointer());
246
247 #if 0
248                         String ext;
249                         pDataType->SubString(1, ext);
250
251                         result r = _AppControlManager::GetMimeFromExt(ext, mimeType);
252
253                         SysTryReturn(NID_APP, !IsFailed(r), null, r, "[%s] MIME type conversion failure for %ls.", GetErrorMessage(r), ext.GetPointer());
254
255                         pMimeType = &mimeType;
256
257                         SysLog(NID_APP, "Conversion : %ls -> %ls.", pDataType->GetPointer(), pMimeType->GetPointer());
258 #endif
259                 }
260
261                 _AppMessageImpl::SetMime(pBundle.get(), mimeType);
262         }
263
264         if (pCategory)
265         {
266                 _AppMessageImpl::SetCategory(pBundle.get(), *pCategory);
267         }
268
269         return StartImplicit(pBundle.get(), pExtraData, pListener);
270 }
271
272 result
273 _AppControlImpl::StartOsp(const IList* pDataList, IAppControlEventListener* pListener)
274 {
275         SysLog(NID_APP, "Enter");
276         result r = E_SUCCESS;
277
278         _AppArg* pArg = new (std::nothrow) _AppArg;
279         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
280
281         pArg->Construct(*this, pDataList);
282
283         _AppControlManager* pImpl = _AppControlManager::GetInstance();
284         int req = _REQ_ID_INVALID;
285
286         if (pListener)
287         {
288                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCbLegacy, pListener, _property);
289                 req = reqObj.GetRequestNumber();
290
291                 _processId = pImpl->Launch(_path, pArg, req);
292
293                 if (_processId < 0)
294                 {
295                         reqObj.Invalidate();
296                         r = GetLastResult();
297                         SysLog(NID_APP, "[%s]Launching(%ls) is failed" , GetErrorMessage(r), _path.GetPointer());
298                         return r;
299                 }
300         }
301         else
302         {
303                 _processId = pImpl->Launch(_path, pArg);
304                 delete pArg;
305                 SysTryReturnResult(NID_APP, _processId >= 0, GetLastResult(), "Launching(%ls) is failed", _path.GetPointer());
306         }
307         SysLog(NID_APP, "Exit");
308
309         return r;
310 }
311
312 result
313 _AppControlImpl::StartOsp(const String* pUriData, const String* pMimeType, const IMap* pDataList, IAppControlResponseListener* pListener)
314 {
315         SysLog(NID_APP, "Enter");
316         result r = E_SUCCESS;
317
318         _AppArg* pArg = new (std::nothrow) _AppArg;
319         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
320
321         pArg->Construct(*this, pUriData, pMimeType, pDataList);
322
323         _AppControlManager* pImpl = _AppControlManager::GetInstance();
324         int req = _REQ_ID_INVALID;
325
326         if (pListener)
327         {
328                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCb, pListener, _property);
329                 req = reqObj.GetRequestNumber();
330
331                 if (_ThreadImpl::GetCurrentThreadImpl()->GetThreadType() == THREAD_TYPE_EVENT_DRIVEN)
332                 {
333                         _AppControlResponseEvent* pAppControlResponseEvent = new (std::nothrow) _AppControlResponseEvent();
334                         if (pAppControlResponseEvent != null)
335                         {
336                                 r = pAppControlResponseEvent->Construct();
337                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::Construct() is failed", GetErrorMessage(r));
338
339                                 r = pAppControlResponseEvent->AddListener(*this, true);
340                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::AddListener() is failed", GetErrorMessage(r));
341
342                                 IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = pImpl->GetAppControlResponseEventContainer();
343                                 if (pResponseEventContainer != null)
344                                 {
345                                         pResponseEventContainer->Add(req, pAppControlResponseEvent);
346                                         __appControlResponseEventList.Add(req);
347                                         SysLog(NID_APP, "pResponseEvent gets added. reqId(%d)", req);
348                                 }
349                         }
350                 }
351
352                 _processId = pImpl->Launch(_path, pArg, req);           
353                 if (_processId < 0)
354                 {
355                         reqObj.Invalidate();
356                         r = GetLastResult();
357                         SysLog(NID_APP, "[%s]Launching(%ls) is failed" , GetErrorMessage(r), _path.GetPointer());
358                         return r;
359                 }
360         }
361         else
362         {
363                 _processId = pImpl->Launch(_path, pArg);
364                 delete pArg;
365                 SysTryReturnResult(NID_APP, _processId >= 0, GetLastResult(), "Launching(%ls) is failed", _path.GetPointer());
366         }
367         SysLog(NID_APP, "Exit");
368
369         return r;
370 }
371
372 result
373 _AppControlImpl::StartImplicit(bundle* pBundle, const IList* pDataList, IAppControlEventListener* pListener)
374 {
375         SysLog(NID_APP, "Enter");
376         result r = E_SUCCESS;
377
378         _AppArg* pArg = new (std::nothrow) _AppArg;
379         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
380
381         pArg->Construct(pBundle);
382
383         _AppMessageImpl::AddData(pArg->GetBundle(), pDataList);
384
385         _AppControlManager* pImpl = _AppControlManager::GetInstance();
386         int req = _REQ_ID_INVALID;
387
388         if (pListener)
389         {
390                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCbLegacy, pListener, _APPCONTROL_PROPERTY_NONE);
391                 req = reqObj.GetRequestNumber();
392
393                 r = pImpl->LaunchAppImplicit(pArg, req);
394                 SysTryCatch(NID_APP, r == E_SUCCESS, reqObj.Invalidate(), r, "[%s] Propagating." , GetErrorMessage(r));
395         }
396         else
397         {
398                 r = pImpl->LaunchAppImplicit(pArg, -1);
399                 delete pArg;
400         }
401
402         // [FIXME] launch registration is not working correctly
403         SysLog(NID_APP, "Exit");
404
405 CATCH:
406         return r;
407 }
408
409 result
410 _AppControlImpl::StartImplicit(bundle* pBundle, const IMap* pData, IAppControlResponseListener* pListener)
411 {
412         SysLog(NID_APP, "Enter");
413         result r = E_SUCCESS;
414
415         _AppArg* pArg = new (std::nothrow) _AppArg;
416         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
417
418         pArg->Construct(pBundle);
419
420         _AppArg::AddStrMap(pArg->GetBundle(), pData);
421
422         _AppControlManager* pImpl = _AppControlManager::GetInstance();
423         int req = _REQ_ID_INVALID;
424
425         if (pListener)
426         {
427                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCb, pListener, _APPCONTROL_PROPERTY_NONE);
428                 req = reqObj.GetRequestNumber();
429
430                 if (_ThreadImpl::GetCurrentThreadImpl()->GetThreadType() == THREAD_TYPE_EVENT_DRIVEN)
431                 {
432                         _AppControlResponseEvent* pAppControlResponseEvent = new (std::nothrow) _AppControlResponseEvent();
433
434                         if (pAppControlResponseEvent != null)
435                         {
436                                 r = pAppControlResponseEvent->Construct();
437                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::Construct() is failed", GetErrorMessage(r));
438
439                                 r = pAppControlResponseEvent->AddListener(*pImpl, true);
440                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::AddListener() is failed", GetErrorMessage(r));
441
442                                 IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = pImpl->GetAppControlResponseEventContainer();
443                                 if (pResponseEventContainer != null)
444                                 {
445                                         pResponseEventContainer->Add(req, pAppControlResponseEvent);
446                                         SysLog(NID_APP, "pResponseEvent gets added. reqId(%d)", req);
447                                 }
448                         }
449                 }
450                 r = pImpl->LaunchAppImplicit(pArg, req);
451                 SysTryCatch(NID_APP, r == E_SUCCESS, reqObj.Invalidate(), r, "[%s] Propagating." , GetErrorMessage(r));
452         }
453         else
454         {
455                 r = pImpl->LaunchAppImplicit(pArg, -1);
456                 delete pArg;
457         }
458         SysLog(NID_APP, "Exit");
459
460         // [FIXME] launch registration is not working correctly
461
462 CATCH:
463
464         return r;
465 }
466
467 result
468 _AppControlImpl::AppControlCbLegacy(void* data, _AppArg* pArg, _AppArg* pResArg, service_result_e res, int prop, int reqId)
469 {
470         SysLog(NID_APP, "Result value %d", res);
471
472         SysTryReturnResult(NID_APP, data && pResArg && pArg, E_SYSTEM, "Invalid result (callback, result, arg) = (0x%x, 0x%x, 0x%x).",
473                                           data, pResArg,
474                                           pArg);
475
476         bundle* b = pResArg->GetBundle();
477         SysTryReturnResult(NID_APP, b != NULL, E_SYSTEM, "Invalid result bundle.");
478
479         IAppControlEventListener* pListener = static_cast<IAppControlEventListener*>(data);
480         SysTryReturnResult(NID_APP, typeid(pListener) == typeid(IAppControlEventListener*), E_SYSTEM, "Invalid result callback");
481
482         bundle* inb = pArg->GetBundle();
483         SysTryReturnResult(NID_APP, inb != NULL, E_SYSTEM, "Empty caller bundle.");
484
485         String oId;
486
487         AppId provider = pResArg->GetCalleeAppId();
488
489         const char* p = appsvc_get_operation(inb);
490         if (p)
491         {
492                 oId = p;
493         }
494
495         SysLog(NID_APP, "Invoking callback with (%ls, %ls)", provider.GetPointer(), oId.GetPointer());
496
497         if (prop & _APPCONTROL_PROPERTY_ALIAS)
498         {
499                 const _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
500                 pEntry = _AppControlRegistry::GetInstance()->GetReverseAppControlAliasEntry(provider, oId);
501                 if (pEntry)
502                 {
503                         provider = pEntry->provider;
504                         oId = pEntry->operation;
505
506                         SysLog(NID_APP, "Legacy AppControl name (%ls, %ls).", provider.GetPointer(), oId.GetPointer());
507                 }
508         }
509
510         if (prop & _APPCONTROL_PROPERTY_APPID_CHANGE)
511         {
512                 String tmp = _AppControlRegistry::GetInstance()->GetReverseAliasAppId(provider);
513                 if (!tmp.IsEmpty())
514                 {
515                         SysLog(NID_APP, "AppId change (%ls -> %ls).", provider.GetPointer(), tmp.GetPointer());
516
517                         provider = tmp;
518                 }
519         }
520
521         std::unique_ptr<HashMap> pMap(pResArg->GetArgMapN());
522
523         ArrayList list(SingleObjectDeleter);
524         _AppArg::FillLegacyAppControlResult(list, res, pMap.get(), provider);
525
526         // proper callback invokation
527         pListener->OnAppControlCompleted(provider, oId, &list);
528
529         return E_SUCCESS;
530 }
531
532 result
533 _AppControlImpl::AppControlCb(void* data, _AppArg* pArg, _AppArg* pResArg, service_result_e res, int prop, int reqId)
534 {
535         SysLog(NID_APP, "Result value %d", res);
536
537         SysTryReturnResult(NID_APP, data && pResArg && pArg, E_SYSTEM, "Invalid result (callback, result, arg) = (0x%x, 0x%x, 0x%x).",
538                                           data, pResArg,
539                                           pArg);
540
541         bundle* b = pResArg->GetBundle();
542         SysTryReturnResult(NID_APP, b != NULL, E_SYSTEM, "Invalid result bundle.");
543
544         IAppControlResponseListener* pListener = static_cast<IAppControlResponseListener*>(data);
545         SysTryReturnResult(NID_APP, typeid(pListener) == typeid(IAppControlResponseListener*), E_SYSTEM, "Invalid result callback");
546
547         bundle* inb = pArg->GetBundle();
548         SysTryReturnResult(NID_APP, inb != NULL, E_SYSTEM, "Empty caller bundle.");
549
550         String oId;
551
552         AppId provider = pResArg->GetCalleeAppId();
553
554         const char* p = appsvc_get_operation(inb);
555         if (p)
556         {
557                 oId = p;
558         }
559
560         SysLog(NID_APP, "Invoking callback with (%ls, %ls)", provider.GetPointer(), oId.GetPointer());
561
562         if (prop & _APPCONTROL_PROPERTY_ALIAS)
563         {
564                 const _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
565                 pEntry = _AppControlRegistry::GetInstance()->GetReverseAppControlAliasEntry(provider, oId);
566                 if (pEntry)
567                 {
568                         provider = pEntry->provider;
569                         oId = pEntry->operation;
570
571                         SysLog(NID_APP, "Legacy AppControl name (%ls, %ls).", provider.GetPointer(), oId.GetPointer());
572                 }
573         }
574
575         if (prop & _APPCONTROL_PROPERTY_APPID_CHANGE)
576         {
577                 String tmp = _AppControlRegistry::GetInstance()->GetReverseAliasAppId(provider);
578                 if (!tmp.IsEmpty())
579                 {
580                         SysLog(NID_APP, "AppId change (%ls -> %ls).", provider.GetPointer(), tmp.GetPointer());
581
582                         provider = tmp;
583                 }
584         }
585
586         std::unique_ptr<HashMap> pMap(pResArg->GetArgMapN());
587
588         AppCtrlResult ret = APP_CTRL_RESULT_FAILED;
589         // to prevent enum overflow;
590         int resCode = res;
591         switch(resCode)
592         {
593         case SERVICE_RESULT_SUCCEEDED:
594                 ret = APP_CTRL_RESULT_SUCCEEDED;
595                 break;
596         case SERVICE_RESULT_FAILED:
597                 ret = APP_CTRL_RESULT_CANCELED;
598                 break;
599         case SERVICE_RESULT_CANCELED:
600                 ret = APP_CTRL_RESULT_ABORTED;
601                 break;
602         case APPSVC_OSP_RES_FAIL:
603                 ret = APP_CTRL_RESULT_FAILED;
604                 break;
605         case APPSVC_OSP_RES_TERMINATE:
606                 ret = APP_CTRL_RESULT_TERMINATED;
607                 break;
608         default:
609                 ret = APP_CTRL_RESULT_FAILED;
610                 break;
611         }
612
613         SysLog(NID_APP, "Result code : 0x%x.", ret);
614
615         // proper callback invokation
616         _AppControlResponseEvent* pResponseEvent = null;
617         _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(reqId, pResponseEvent);
618
619         if (pResponseEvent != null)
620         {
621                 _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_COMPLETE, provider, oId, E_SUCCESS, ret, pMap.get(), reqId);
622                 pResponseEvent->Fire(*pResponseEventArg);
623                 SysLog(NID_APP, "OnAppControlCompleteResponseReceived, pResponseEvent is Fired");
624         }
625         else
626         {
627                 pListener->OnAppControlCompleteResponseReceived(provider, oId, ret, pMap.get());
628                 SysLog(NID_APP, "OnAppControlCompleteResponseReceived, Called");
629         }
630
631         return E_SUCCESS;
632 }
633
634 result
635 _AppControlImpl::StartNative(const IList* pDataList, IAppControlEventListener* pListener)
636 {
637         SysLog(NID_APP, "Enter");
638         _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
639         SysTryReturnResult(NID_APP, pInfo == null, E_IN_PROGRESS, "Request ID %d is already in progress.", _reqId);
640
641         int req = _REQ_ID_INVALID;
642         _LibraryImpl* pLib = null;
643
644         pLib = new (std::nothrow) _LibraryImpl;
645         SysTryReturnResult(NID_APP, pLib != null, E_OUT_OF_MEMORY, "Failed to allocate libraryimpl.");
646
647         unsigned long option = _LIBRARY_LOAD_OPTION_LAZY;
648         option |= _LIBRARY_LOAD_OPTION_NODELETE;
649
650         result r = pLib->Construct(_path, option);
651         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
652
653         if (pListener)
654         {
655                 _InProcessInfo* pItem = new (std::nothrow) _InProcessInfo(_provider, _opId, _property, true, *pLib, pListener);
656                 if (pItem)
657                 {
658                         req = _AppControlManager::GetInstance()->__inAppManager.InsertItem(pItem);
659                 }
660         }
661         r = InvokeStartAppControl(*pLib, req, _provider, _opId, pDataList);
662
663         if (pListener == null)
664         {
665                 delete pLib;
666         }
667
668         // after acquring request number, pLib should be managed from the list, not CATCH
669         if (IsFailed(r))
670         {
671                 SetLastResult(E_SYSTEM);
672                 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
673                 SysLog(NID_APP, "[E_SYSTEM] A system error has occurred with %s.", GetErrorMessage(r));
674
675                 return E_SYSTEM;
676         }
677
678         _reqId = req;
679
680         SysLog(NID_APP, "Exit");
681         return E_SUCCESS;
682
683 CATCH:
684         delete pLib;
685
686         switch (r)
687         {
688         case E_LIBRARY_NOT_FOUND:
689                 r = E_OBJ_NOT_FOUND;
690                 break;
691         default:
692                 r = E_SYSTEM;
693                 break;
694         }
695
696         return r;
697 }
698
699 result
700 _AppControlImpl::StartNative(const String* pUriData, const String* pMimeType, const IMap* pDataList, IAppControlResponseListener* pListener)
701 {
702         SysLog(NID_APP, "Enter");
703         _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
704         SysTryReturnResult(NID_APP, pInfo == null, E_IN_PROGRESS, "Request ID %d is already in progress.", _reqId);
705
706         int req = _REQ_ID_INVALID;
707         _LibraryImpl* pLib = null;
708
709         pLib = new (std::nothrow) _LibraryImpl;
710         SysTryReturnResult(NID_APP, pLib != null, E_OUT_OF_MEMORY, "Failed to allocate libraryimpl.");
711
712         unsigned long option = _LIBRARY_LOAD_OPTION_LAZY;
713         option |= _LIBRARY_LOAD_OPTION_NODELETE;
714
715         result r = pLib->Construct(_path, option);
716
717         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
718
719         if (pListener)
720         {
721                 _InProcessInfo* pItem = new (std::nothrow) _InProcessInfo(_provider, _opId, _property, false, *pLib, pListener);
722                 if (pItem)
723                 {
724                         req = _AppControlManager::GetInstance()->__inAppManager.InsertItem(pItem);
725                 }
726
727                 if (_ThreadImpl::GetCurrentThreadImpl()->GetThreadType() == THREAD_TYPE_EVENT_DRIVEN)
728                 {
729                         _AppControlResponseEvent* pAppControlResponseEvent = new (std::nothrow) _AppControlResponseEvent();
730
731                         if (pAppControlResponseEvent != null)
732                         {
733                                 r = pAppControlResponseEvent->Construct();
734                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::Construct() is failed", GetErrorMessage(r));
735
736                                 r = pAppControlResponseEvent->AddListener(*this, true);
737                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::AddListener() is failed", GetErrorMessage(r));
738
739                                 IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = _AppControlManager::GetInstance()->GetAppControlResponseEventContainer();
740                                 if (pResponseEventContainer != null)
741                                 {
742                                         int responseEventRequestId = RESPONSE_EVENT_REQID_MAGIC + req;
743                                         pResponseEventContainer->Add(responseEventRequestId, pAppControlResponseEvent);
744                                         __appControlResponseEventList.Add(responseEventRequestId);
745                                         SysLog(NID_APP, "pResponseEvent gets added. reqId(%d)", responseEventRequestId);
746                                 }
747                         }
748                 }
749         }
750         r = InvokeStartAppControl(*pLib, req, _provider, _opId, pUriData, pMimeType, pDataList);
751
752         if (pListener == null)
753         {
754                 delete pLib;
755         }
756
757         // after acquring request number, pLib should be managed from the list, not CATCH
758         if (IsFailed(r))
759         {
760                 SetLastResult(E_SYSTEM);
761                 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
762                 SysLog(NID_APP, "[E_SYSTEM] A system error has occurred with %s.", GetErrorMessage(r));
763
764                 return E_SYSTEM;
765         }
766
767         _reqId = req;
768         SysLog(NID_APP, "Exit");
769
770         return E_SUCCESS;
771
772 CATCH:
773         delete pLib;
774
775         switch (r)
776         {
777         case E_LIBRARY_NOT_FOUND:
778                 r = E_OBJ_NOT_FOUND;
779                 break;
780         default:
781                 r = E_SYSTEM;
782                 break;
783         }
784
785         return r;
786 }
787
788 result
789 _AppControlImpl::InvokeStartAppControl(_LibraryImpl& lib, int req, const String& appId, const String& oId, const IList* pList)
790 {
791         SysLog(NID_APP, "Legacy stuff for converting argument");
792
793         HashMap map(SingleObjectDeleter);
794         HashMap* pMap = null;
795         if (pList)
796         {
797                 map.Construct();
798
799                 _AppArg::FillMapFromList(&map, pList);
800
801                 pMap = &map;
802         }
803
804         return InvokeStartAppControl(lib, req, appId, oId, null, null, pMap);
805 }
806
807
808 result
809 _AppControlImpl::InvokeStartAppControl(_LibraryImpl& lib, int req, const String& appId, const String& oId, const String* pUri, const String* pMime, const IMap* pMap)
810 {
811         result (*pFunc)(int req, const String&, const String&, const String*, const String*, const IMap*) = null;
812
813         pFunc =
814                 reinterpret_cast<result (*)(int, const String&, const String&, const String*, const String*, const IMap*)>(lib.GetProcAddress(L"StartAppControl"));
815         SysTryReturnResult(NID_APP, pFunc != null, E_OBJ_NOT_FOUND, "Entry \"StartAppControl\" not found for %ls", appId.GetPointer());
816
817         const String* pActualUri = (pUri && !(pUri->IsEmpty())) ? pUri : null;
818         const String* pActualMime = (pMime && !(pMime->IsEmpty())) ? pMime : null;
819         return (*pFunc)(req, appId, oId, pActualUri, pActualMime, pMap);
820 }
821
822 static bool
823 IsValidAppControl(const String& appcontrolID)
824 {
825         return ((appcontrolID == L"osp.appcontrol.provider.audio")
826                 || (appcontrolID == L"osp.appcontrol.provider.bluetooth")
827                 || (appcontrolID == L"osp.appcontrol.provider.calendar")
828                 || (appcontrolID == L"osp.appcontrol.provider.camera")
829                 || (appcontrolID == L"osp.appcontrol.provider.contact")
830                 || (appcontrolID == L"osp.appcontrol.provider.certificatemanager")
831                 || (appcontrolID == L"osp.appcontrol.provider.email")
832                 || (appcontrolID == L"osp.appcontrol.provider.image")
833                 || (appcontrolID == L"osp.appcontrol.provider.media")
834                 || (appcontrolID == L"osp.appcontrol.provider.message")
835                 || (appcontrolID == L"osp.appcontrol.provider.video")
836                 || (appcontrolID == L"osp.appcontrol.provider.imageeditor")
837                 || (appcontrolID == L"osp.appcontrol.provider.allshare")
838                 || (appcontrolID == L"tizen.filemanager")
839                 || (appcontrolID == L"tizen.camera")
840                 || (appcontrolID == L"tizen.gallery")
841                 || (appcontrolID == L"tizen.imageviewer")
842                 || (appcontrolID == L"tizen.videoplayer")
843                 || (appcontrolID == L"tizen.memo")
844                 || (appcontrolID == L"tizen.contacts")
845                 || (appcontrolID == L"tizen.calendar")
846                 || (appcontrolID == L"tizen.events")
847                 || (appcontrolID == L"tizen.email")
848                 || (appcontrolID == L"tizen.settings")
849                 || (appcontrolID == L"tizen.messages")
850                 || (appcontrolID == L"tizen.musicplayer")
851                 || (appcontrolID == L"tizen.bluetooth")
852                 || (appcontrolID == L"samsung.snote")
853                 || (appcontrolID == L"0pnxz8hbsr.MyFiles")
854                 || (appcontrolID == L"hdufar9ycj.Camera")
855                 || (appcontrolID == L"ijudt7w61q.Gallery")
856                 || (appcontrolID == L"jysyv9o1dc.ImageViewer")
857                 || (appcontrolID == L"npwf0scb88.VideoPlayer")
858                 || (appcontrolID == L"zunqjlsnce.Memo")
859                 || (appcontrolID == L"f9uev8hsyo.Contacts")
860                 || (appcontrolID == L"ph1vq2phrp.Calendar")
861                 || (appcontrolID == L"vxqbrefica.Email")
862                 || (appcontrolID == L"kto5jikgul.Settings")
863                 || (appcontrolID == L"8r4r5ddzzn.Messages")
864                 || (appcontrolID == L"dhrul6qzj3.MusicPlayer")
865                 || (appcontrolID == L"smemo-efl"));
866 }
867
868 result
869 _AppControlImpl::Stop(void)
870 {
871         const String appcontrolID(GetAppControlProviderId());
872         SysTryReturnResult(NID_APP, IsValidAppControl(appcontrolID), E_INVALID_OPERATION, "Invalid appcontrolID(%ls)", appcontrolID.GetPointer());
873
874         if (_property & _APPCONTROL_PROPERTY_SLP)
875         {       
876                 SysTryReturnResult(NID_APP, _reqId != _REQ_ID_INVALID, E_INVALID_OPERATION, "Invalid request ID .");
877
878                 _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
879                 SysTryReturnResult(NID_APP, pInfo != null, E_INVALID_OPERATION, "Request ID %d is not found.", _reqId);
880                 
881                 result (*pStop)(int req) = null;
882                 pStop = reinterpret_cast<result (*)(int)>(pInfo->pLib->GetProcAddress(L"TerminateAppControl"));
883                 SysTryReturnResult(NID_APP, pStop != null, E_SYSTEM, "No TerminateAppControl() function.");
884                 
885                 (*pStop)(_reqId);
886                 
887                 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(_reqId);
888                 
889                 _reqId = _REQ_ID_INVALID;
890         }
891         else if (_property & _APPCONTROL_PROPERTY_OSP)
892         {
893                 _Aul::TerminateApplicationByPid(_processId);
894         }
895
896         return E_SUCCESS;
897 }
898
899 String
900 _AppControlImpl::GetAppName(void)
901 {
902         if ((_property & _APPCONTROL_PROPERTY_OSP) && _appName.IsEmpty())
903         {
904                 const AppId& appId = _path;
905
906                 std::unique_ptr<PackageAppInfo> pInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
907
908                 if (pInfo.get())
909                 {
910                         const String& name = pInfo->GetAppName();
911                         if (name == L"_AppControl")
912                         {
913                                 // workaround for special case: requery with actual appId
914                                 const PackageId& packageId = _PackageManagerImpl::GetPackageIdByAppId(appId);
915                                 const String& defaultName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(packageId);
916
917                                 const String& convertedAppId = packageId + L'.' + defaultName;
918
919                                 std::unique_ptr<PackageAppInfo> pNewInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(convertedAppId));
920
921                                 if (pNewInfo.get())
922                                 {
923                                         _appName = pNewInfo->GetAppName();
924                                 }
925                                 else
926                                 {
927                                         SysLog(NID_APP, "No default applicaiton information, possible database error.");
928                                 }
929                         }
930                         else
931                         {
932                                 _appName = pInfo->GetAppName();
933                         }
934                         SysLog(NID_APP, "Initializing AppName(%ls) for %ls.", _appName.GetPointer(), appId.GetPointer());
935                 }
936         }
937
938         return _appName;
939 }
940
941 String
942 _AppControlImpl::GetAppId(void) const
943 {
944         return (_property & _APPCONTROL_PROPERTY_OSP) ? _path : _provider;
945 }
946
947 const String&
948 _AppControlImpl::GetAppControlProviderId(void) const
949 {
950         return _provider;
951 }
952
953 const String&
954 _AppControlImpl::GetOperationId(void) const
955 {
956         return _opId;
957 }
958
959 IList*
960 _AppControlImpl::GetCategoryListN(void) const
961 {
962         const AppId& appId = GetAppId();
963         SysTryReturn(NID_APP, !appId.IsEmpty(), null, E_SYSTEM, "[E_SYSTEM] Empty appId.");
964
965         SysLog(NID_APP, "Acquiring category for appId %ls.", appId.GetPointer());
966
967         std::unique_ptr<PackageAppInfo> pAppInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
968         SysTryReturn(NID_APP, pAppInfo.get() != null, null, E_SYSTEM, "[E_SYSTEM] Getting PackageAppInfo failed.");
969
970         return pAppInfo->GetAppCategoryListN();
971 }
972
973 void
974 _AppControlImpl::StopAppControlResponseListener(IAppControlResponseListener* pListener)
975 {
976         _AppControlManager::GetInstance()->__listenerList.Add(pListener);
977 }
978
979 void
980 _AppControlImpl::OnAppControlResponseEventReceivedN(const Tizen::Base::Runtime::IEventArg* arg)
981 {
982         const _AppControlResponseEventArg* pEventArg = dynamic_cast<const _AppControlResponseEventArg*>(arg);
983
984         if (pEventArg != null)
985         {
986                 IAppControlResponseListener* pResponseListener = pEventArg->GetListener();
987
988                 if(pResponseListener != null)
989                 {
990                         if(pEventArg->GetType() == _APPCONTROL_RESPONSETYPE_COMPLETE)
991                         {
992                                 pResponseListener->OnAppControlCompleteResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData());
993                                 SysLog(NID_APP, "OnAppControlCompleteResponseReceived called");
994
995                                 _AppControlResponseEvent* pResponseEvent = null;
996                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
997                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
998                                 delete pResponseEvent;
999                                 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
1000                         }
1001                         else
1002                         {
1003                                 SysLog(NID_APP, "Unexpected AppControlResponseType(%d)", pEventArg->GetType());
1004                         }
1005                 }
1006                 else
1007                 {
1008                         SysLog(NID_APP, "Invalid ResponseListener");
1009                 }
1010         }
1011         else
1012         {
1013                 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);
1014         }
1015
1016 }
1017 }}    //Tizen::App