Resolve result cancel issue of DataControl provider.
[platform/framework/native/appfw.git] / src / app / FApp_AppArg.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18 * @file     FApp_AppArg.cpp
19 * @brief        This is the implementation for the _AppArg.cpp class.
20 */
21
22 #include <cstdio>
23 #include <cstdlib>
24 #include <vector>
25 #include <new>
26 #include <typeinfo>
27 #include <unique_ptr.h>
28
29 #include <aul.h>
30 #include <app.h>
31 #include <appsvc/appsvc.h>
32 #include <Ecore_X.h>
33
34 #include <FBaseInteger.h>
35 #include <FBaseColArrayList.h>
36 #include <FBaseColHashMap.h>
37 #include <FBaseUtilStringTokenizer.h>
38
39 #include <FBaseSysLog.h>
40 #include <FBase_StringConverter.h>
41
42 #include "FApp_MapDataControlImpl.h"
43 #include "FApp_AppControlImpl.h"
44 #include "FApp_SqlDataControlImpl.h"
45 #include "FApp_AppControlEventArg.h"
46 #include "FApp_AppArg.h"
47 #include "FApp_AppMessageImpl.h"
48 #include "FAppPkg_PackageManagerImpl.h"
49
50 using namespace Tizen::Base;
51 using namespace Tizen::Base::Collection;
52 using namespace Tizen::Base::Utility;
53 using namespace Tizen::App::Package;
54
55
56 extern "C" int appsvc_allow_transient_app(bundle*, Ecore_X_Window);
57
58 namespace Tizen { namespace App
59 {
60
61 static const char OSP_V_LAUNCH_TYPE_LAUNCH[] = "launch";
62 static const char OSP_V_LAUNCH_TYPE_APPCONTROL[] = "appcontrol";
63 static const char OSP_V_LAUNCH_TYPE_DATACONTROL[] = "datacontrol";
64 static const char OSP_V_LAUNCH_TYPE_CONDTION[] = "condition";
65 static const char OSP_V_REQUEST_TYPE_SQL_QUERY[] = "sql_query";
66 static const char OSP_V_REQUEST_TYPE_SQL_INSERT[] = "sql_insert";
67 static const char OSP_V_REQUEST_TYPE_SQL_UPDATE[] = "sql_update";
68 static const char OSP_V_REQUEST_TYPE_SQL_DELETE[] = "sql_delete";
69 static const char OSP_V_REQUEST_TYPE_MAP_QEURY[] = "map_query";
70 static const char OSP_V_REQUEST_TYPE_MAP_INSERT[] = "map_insert";
71 static const char OSP_V_REQUEST_TYPE_MAP_UPDATE[] = "map_update";
72 static const char OSP_V_REQUEST_TYPE_MAP_DELETE[] = "map_delete";
73 static const char OSP_V_VERSION_2_1_0_3[] = "ver_2.1.0.3";
74 static const char BUNDLE_KEY_PREFIX_AUL[] = "__AUL_";
75 static const char BUNDLE_KEY_PREFIX_SERVICE[] = "__APP_SVC_";
76 static const char BUNDLE_KEY_PREFIX_OSP[] = "__OSP_";
77 const char TIZEN_NOTIFICATION_DATA[] = "http://tizen.org/appcontrol/data/notification";
78
79 static const char SAMSUNG_ACCOUNT_KEY_CLIENT_ID[] = "client_id";
80 static const char SAMSUNG_ACCOUNT_KEY_CLIENT_SECRET[] = "client_secret";
81 static const char SAMSUNG_ACCOUNT_KEY_SERVICE_CATEGORY[] = "service_category";
82
83 static const char SMS_KEY_SERVICE_CALLER[] = "service_caller";
84 static const char SMS_KEY_SERVICE_DATA[] = "service_data";
85
86
87 _AppArg::_AppArg(void)
88         : __pBundle(null)
89 {
90 }
91
92
93 _AppArg::~_AppArg(void)
94 {
95         if (__pBundle)
96         {
97                 bundle_free(__pBundle);
98         }
99 }
100
101
102 result
103 _AppArg::Construct(const String& argText)
104 {
105         __pBundle = bundle_create();
106         SysTryReturnResult(NID_APP, __pBundle != null, E_OUT_OF_MEMORY, "Bundle creation failure.");
107
108         return CreateLaunchArg(__pBundle, argText);
109 }
110
111
112 result
113 _AppArg::Construct(const IList* pList)
114 {
115         __pBundle = bundle_create();
116         SysTryReturnResult(NID_APP, __pBundle != null, E_OUT_OF_MEMORY, "Bundle creation failure.");
117
118         return CreateLaunchArg(__pBundle, pList);
119 }
120
121
122 result
123 _AppArg::Construct(const _AppControlImpl& ac, const IList* pList)
124 {
125         __pBundle = bundle_create();
126         SysTryReturnResult(NID_APP, __pBundle != null, E_OUT_OF_MEMORY, "Bundle creation failure.");
127
128         return CreateAppControlArg(__pBundle, ac, pList);
129 }
130
131
132 result
133 _AppArg::Construct(const _AppControlImpl& ac, const String* pUri, const String* pMime, const IMap* pList)
134 {
135         __pBundle = bundle_create();
136         SysTryReturnResult(NID_APP, __pBundle != null, E_OUT_OF_MEMORY, "Bundle creation failure.");
137
138         return CreateAppControlArg(__pBundle, ac, pUri, pMime, pList);
139 }
140
141
142 result
143 _AppArg::Construct(const _AppMessageImpl& msg, const String& oId, const String* pUri, const String* pMime)
144 {
145         __pBundle = bundle_dup(const_cast<bundle*>(msg.GetBundle()));
146         SysTryReturnResult(NID_APP, __pBundle != null, E_OUT_OF_MEMORY, "Bundle creation failure.");
147
148         return CreateAppControlArg(__pBundle, oId, pUri, pMime, null);
149 }
150
151
152 result
153 _AppArg::Construct(const _SqlDataControlImpl& dc, _DataControlRequestType requestType, const IList* pList)
154 {
155         __pBundle = bundle_create();
156         SysTryReturnResult(NID_APP, __pBundle != null, E_OUT_OF_MEMORY, "Bundle creation failure.");
157
158         return CreateSqlDataControlArg(__pBundle, dc, requestType, pList);
159 }
160
161
162 result
163 _AppArg::Construct(const _MapDataControlImpl& dc, _DataControlRequestType requestType, const IList* pList)
164 {
165         __pBundle = bundle_create();
166         SysTryReturnResult(NID_APP, __pBundle != null, E_OUT_OF_MEMORY, "Bundle creation failure.");
167
168         return CreateMapDataControlArg(__pBundle, dc, requestType, pList);
169 }
170
171
172 result
173 _AppArg::ConstructResult(const _AppArg& arg, const IList* pList)
174 {
175         int ret = aul_create_result_bundle(arg.GetBundle(), &__pBundle);
176         SysTryReturnResult(NID_APP, __pBundle != null, E_INVALID_STATE, "Bundle creatioin from service handle failure : %d.", ret);
177
178         return CreateResultArg(__pBundle, pList);
179 }
180
181
182 result
183 _AppArg::ConstructResult(const _AppArg& arg, const IMap* pMap)
184 {
185         int ret = aul_create_result_bundle(arg.GetBundle(), &__pBundle);
186         SysTryReturnResult(NID_APP, __pBundle != null, E_INVALID_STATE, "Bundle creatioin from service handle failure : %d.", ret);
187
188         return CreateResultArg(__pBundle, pMap);
189 }
190
191
192 result
193 _AppArg::Construct(bundle* b)
194 {
195         __pBundle = bundle_dup(b);
196         SysTryReturnResult(NID_APP, __pBundle != null, E_INVALID_STATE, "Bundle creatioin from service handle failure.");
197
198         return E_SUCCESS;
199 }
200
201
202 result
203 _AppArg::ConstructForAppLaunchCondition(const String& condition, const IList* pList)
204 {
205         __pBundle = bundle_create();
206         SysTryReturnResult(NID_APP, __pBundle != null, E_OUT_OF_MEMORY, "Bundle creation failure.");
207
208         return CreateAppLaunchConditionArg(__pBundle, condition, pList);
209 }
210
211 result
212 _AppArg::ConstructForAppLaunchCondition(const String& condition, const IList* pList, const IMap* pMap)
213 {
214         __pBundle = bundle_create();
215         SysTryReturnResult(NID_APP, __pBundle != null, E_OUT_OF_MEMORY, "Bundle creation failure.");
216
217         CreateAppLaunchConditionArg(__pBundle, condition, pList);
218
219         return CreateResultArg(__pBundle, pMap);
220 }
221
222 ArrayList*
223 _AppArg::GetArgListN(int num) const
224 {
225         bundle* pBundle = __pBundle;
226         SysTryReturn(NID_APP, pBundle != null, null, E_INVALID_STATE, "[E_INVALID_STATE] Improper bundle state.");
227
228         ArrayList* pList = new (std::nothrow) ArrayList();
229         SysTryReturn(NID_APP, pList != null, null, E_OUT_OF_MEMORY, "ArrayList creation failure.");
230
231         pList->Construct();
232
233         const char* p = NULL;
234         _AppHandler launch_type = GetHandler(pBundle);
235
236         switch (launch_type)
237         {
238         case _APP_HANDLER_APPCONTROL:
239                 // request Id
240                 // [FIXME] proper request Id required
241                 pList->Add(*new (std::nothrow) String(GetRequestId(num)));
242
243                 // category
244                 p = appsvc_get_category(pBundle);
245                 if (p)
246                 {
247                         pList->Add(*new (std::nothrow) String(p));
248                 }
249                 else
250                 {
251                         pList->Add(*new (std::nothrow) String(L""));
252                 }
253
254                 // MIME type
255                 p = appsvc_get_mime(pBundle);
256                 if (p)
257                 {
258                         pList->Add(*new (std::nothrow) String(p));
259                 }
260                 else
261                 {
262                         pList->Add(*new (std::nothrow) String(L""));
263                 }
264
265                 // URI scheme
266                 p = appsvc_get_uri(pBundle);
267                 if (p)
268                 {
269                         pList->Add(*new (std::nothrow) String(p));
270                 }
271                 else
272                 {
273                         pList->Add(*new (std::nothrow) String(L""));
274                 }
275
276                 break;
277
278         case _APP_HANDLER_DATACONTROL:
279                 // appId
280                 AddListFromBundle(pList, pBundle, OSP_K_APPID);
281                 // request type
282                 AddListFromBundle(pList, pBundle, OSP_K_DATACONTROL_REQUEST_TYPE);
283                 // reqId
284                 AddListFromBundle(pList, pBundle, OSP_K_REQUEST_ID);
285                 // providerId
286                 AddListFromBundle(pList, pBundle, OSP_K_DATACONTROL_PROVIDER);
287                 break;
288
289         case _APP_HANDLER_LAUNCH_COND:
290                 pList->Add(*new (std::nothrow) String(LEGACY_LAUNCH_REASON_CONDITIONAL));
291                 AddListFromBundle(pList, pBundle, OSP_K_COND);
292                 break;
293
294         case _APP_HANDLER_LAUNCH_NORMAL:
295                 pList->Add(*new (std::nothrow) String(LEGACY_LAUNCH_REASON_NORMAL));
296                 pList->Add(*new (std::nothrow) String(L"osp.operation.MAIN"));
297                 break;
298
299         default:
300                 SysLog(NID_APP, "Invalid handler type");
301                 break;
302         }
303
304         SetArgList(__pBundle, pList);
305
306         return pList;
307 }
308
309
310 ArrayList*
311 _AppArg::GetArgListN(void) const
312 {
313         SysTryReturn(NID_APP, __pBundle != null, null, E_INVALID_STATE, "[E_INVALID_STATE] Improper bundle state.");
314
315         ArrayList* pList = new (std::nothrow) ArrayList();
316         SysTryReturn(NID_APP, pList != null, null, E_OUT_OF_MEMORY, "ArrayList creation failure.");
317
318         pList->Construct();
319
320         SetArgList(__pBundle, pList);
321
322         return pList;
323 }
324
325 // the returned map is allocated using SingleObjectDeleter
326 HashMap*
327 _AppArg::GetArgMapN(void) const
328 {
329         SysTryReturn(NID_APP, __pBundle != null, null, E_INVALID_STATE, "[E_INVALID_STATE] Improper bundle state.");
330
331         HashMap* pHashMap = new (std::nothrow) HashMap(SingleObjectDeleter);
332         SysTryReturn(NID_APP, pHashMap != null, null, E_OUT_OF_MEMORY, "HashMap creation failure.");
333
334         pHashMap->Construct();
335
336         SetArgMap(__pBundle, pHashMap);
337
338         if (pHashMap->GetCount() == 0)
339         {
340                 delete pHashMap;
341                 return null;
342         }
343
344         ArrayList* pList = _AppMessageImpl::GetValueArrayN(__pBundle, OSP_K_ARG);
345         if (pList)
346         {
347                 pHashMap->Add(new (std::nothrow) String(TIZEN_APPCONTROL_DATA_LEGACY), pList);
348         }
349         return pHashMap;
350 }
351
352 static bool
353 IsInternalKey(const char* pKey)
354 {
355         if (strncmp(BUNDLE_KEY_PREFIX_AUL, pKey, strlen(BUNDLE_KEY_PREFIX_AUL)) == 0)
356         {
357                 return true;
358         }
359
360         if (strncmp(BUNDLE_KEY_PREFIX_SERVICE, pKey, strlen(BUNDLE_KEY_PREFIX_SERVICE)) == 0)
361         {
362                 return true;
363         }
364
365         if (strncmp(BUNDLE_KEY_PREFIX_OSP, pKey, strlen(BUNDLE_KEY_PREFIX_OSP)) == 0)
366         {
367                 return true;
368         }
369
370         return false;
371 }
372
373 static void
374 BundleIterFnCb(const char* pKey, const int type, const bundle_keyval_t* pVal, void* pData)
375 {
376         HashMap* pMap = static_cast<HashMap*>(pData);
377
378         if (pKey && pVal && pMap)
379         {
380                 if (IsInternalKey(pKey))
381                 {
382                         //SysLog(NID_APP, "(%s)", pKey);
383                         return;
384                 }
385
386                 size_t size = 0;
387                 char* pStr = NULL;
388                 switch (type)
389                 {
390                 case BUNDLE_TYPE_STR:
391                         bundle_keyval_get_basic_val(const_cast<bundle_keyval_t*>(pVal), reinterpret_cast<void**>(&pStr), &size);
392                         if (pStr)
393                         {
394                                 pMap->Add(new (std::nothrow) String(pKey), new (std::nothrow) String(pStr));
395                         }
396                         break;
397                 case BUNDLE_TYPE_STR_ARRAY:
398                         {
399                                 void** pArr = NULL;
400                                 bundle_keyval_get_array_val(const_cast<bundle_keyval_t*>(pVal), &pArr, &size, NULL);
401                                 if (pArr && size > 0)
402                                 {
403                                         ArrayList* pList = new (std::nothrow) ArrayList(SingleObjectDeleter);
404                                         if (pList)
405                                         {
406                                                 pList->Construct();
407
408                                                 for (size_t i = 0; i < size; i++)
409                                                 {
410                                                         // type unsafe ugly static casting required
411                                                         pList->Add(new (std::nothrow) String(static_cast<char*>(*(pArr + i))));
412                                                 }
413
414                                                 const int count = pList->GetCount();
415                                                 if (count != 0)
416                                                 {
417                                                         SysLog(NID_APP, "Adding %d elements for %s", count, pKey);
418                                                         pMap->Add(new (std::nothrow) String(pKey), pList);
419                                                 }
420                                                 else
421                                                 {
422                                                         SysLog(NID_APP, "No object for %s", pKey);
423                                                         delete pList;
424                                                 }
425                                         }
426                                 }
427                                 else
428                                 {
429                                         SysLog(NID_APP, "No entry for str array %s(%d)", pKey, size);
430                                 }
431                         }
432                         break;
433                 case BUNDLE_TYPE_BYTE:
434                         bundle_keyval_get_basic_val(const_cast<bundle_keyval_t*>(pVal), reinterpret_cast<void**>(&pStr), &size);
435
436                         SysLog(NID_IO, "Bundle byte value = %s, size = %d", pStr, size);
437
438                         if (pStr)
439                         {
440                                 ByteBuffer* pBuffer = new (std::nothrow) ByteBuffer();
441                                 SysTryLog(NID_IO, pBuffer != null, "The memory is insufficient.");
442                                 result r = pBuffer->Construct(size);
443                                 SysTryLog(NID_IO, r == E_SUCCESS, "Constructing pBuffer is failed.");
444
445                                 r = pBuffer->SetArray((const byte*)pStr, 0, size);
446                                 SysTryLog(NID_IO, r == E_SUCCESS, "SetArray()for ByteBuffer is failed.");
447
448                                 pBuffer->Flip();
449
450                                 pMap->Add(new (std::nothrow) String(pKey), pBuffer);
451                         }
452                         break;
453                 default:
454                         SysLog(NID_APP, "Invalid type for %s : %d", pKey, type);
455                         break;
456                 }
457         }
458 }
459
460 result
461 _AppArg::SetArgMap(bundle* pBundle, HashMap* pMap)
462 {
463         bundle_foreach(pBundle, BundleIterFnCb, reinterpret_cast<void*>(pMap));
464
465         return E_SUCCESS;
466 }
467
468 result
469 _AppArg::SetArgList(bundle* pBundle, ArrayList* pList)
470 {
471         // actual argument below
472         int len = 0;
473         const char** pa = appsvc_get_data_array(pBundle, OSP_K_ARG, &len);
474         if (pa)
475         {
476                 for (int i = 0; i < len; i++)
477                 {
478                         if (pa[i])
479                         {
480                                 //SysLog(NID_APP, "%d/%dth arg [%s]", i, len, pa[i]);
481                                 pList->Add(*new (std::nothrow) String(pa[i]));
482                         }
483                 }
484         }
485
486         const char* p = appsvc_get_uri(pBundle);
487         if (p)
488         {
489                 pList->Add(*new (std::nothrow) String(p));
490                 SysLog(NID_APP, "argument is %s", p);
491         }
492
493         String tmp;
494         p = appsvc_get_data(pBundle, SMS_KEY_SERVICE_CALLER);
495         if (p)
496         {
497                 tmp.Format(60, L"%s:%s", SMS_KEY_SERVICE_CALLER, p);
498                 pList->Add(*new (std::nothrow) String(tmp));
499                 SysLog(NID_APP, "service_caller is %s", p);
500         }
501         
502         p = appsvc_get_data(pBundle, SMS_KEY_SERVICE_DATA);
503         if (p)
504         {
505                 tmp.Format(60, L"%s:%s", SMS_KEY_SERVICE_DATA, p);
506                 pList->Add(*new (std::nothrow) String(tmp));
507                 SysLog(NID_APP, "service_data is set");
508         }
509         
510         p = appsvc_get_data(pBundle, SAMSUNG_ACCOUNT_KEY_CLIENT_ID);
511         if (p)
512         {
513                 tmp.Format(60, L"%s:%s", SAMSUNG_ACCOUNT_KEY_CLIENT_ID, p);
514                 pList->Add(*new (std::nothrow) String(tmp));
515                 SysLog(NID_APP, "client_id is %s", p);
516         }
517         
518         p = appsvc_get_data(pBundle, SAMSUNG_ACCOUNT_KEY_CLIENT_SECRET);
519         if (p)
520         {
521                 tmp.Format(60, L"%s:%s", SAMSUNG_ACCOUNT_KEY_CLIENT_SECRET, p);
522                 pList->Add(*new (std::nothrow) String(tmp));
523                 SysLog(NID_APP, "client_secret is %s", p);
524         }
525
526         p = appsvc_get_data(pBundle, SAMSUNG_ACCOUNT_KEY_SERVICE_CATEGORY);
527         if (p)
528         {
529                 tmp.Format(60, L"%s:%s", SAMSUNG_ACCOUNT_KEY_SERVICE_CATEGORY, p);
530                 pList->Add(*new (std::nothrow) String(tmp));
531                 SysLog(NID_APP, "service_category is %s", p);
532         }
533
534         return E_SUCCESS;
535 }
536
537
538 String
539 _AppArg::GetValue(const char* key) const
540 {
541         const char* p = appsvc_get_data(__pBundle, key);
542         return String(p);
543 }
544
545
546 _AppHandler
547 _AppArg::GetHandler(bundle* b)
548 {
549         SysTryReturn(NID_APP, b != null, _APP_HANDLER_NONE, E_INVALID_STATE, "[E_INVALID_STATE] Improper bundle state.");
550
551         const char* p = null;
552
553         p = appsvc_get_data(b, OSP_K_LAUNCH_TYPE);
554
555         if (p)
556         {
557                 if (strcmp(p, OSP_V_LAUNCH_TYPE_DATACONTROL) == 0)
558                 {
559                         return _APP_HANDLER_DATACONTROL;
560                 }
561
562                 if (strcmp(p, OSP_V_LAUNCH_TYPE_APPCONTROL) == 0)
563                 {
564                         SysLog(NID_APP, "Building AppControl arguments.");
565
566                         return _APP_HANDLER_APPCONTROL;
567                 }
568                 else
569                 {
570                         // not appcontrol nor datacontrol => normal launch or condlaunch
571                         p = appsvc_get_data(b, OSP_K_COND);
572                         if (p)
573                         {
574                                 SysLog(NID_APP, "Building Conditional AppLaunch arguments.");
575                                 return _APP_HANDLER_LAUNCH_COND;
576                         }
577                         else
578                         {
579                                 SysLog(NID_APP, "Building Normal AppLaunch arguments.");
580                                 return _APP_HANDLER_LAUNCH_NORMAL;
581                         }
582                 }
583         }
584
585         // fallback
586         return _APP_HANDLER_APPCONTROL;
587 }
588
589
590 int
591 _AppArg::GetCallerPid(bundle* pBundle)
592 {
593         const char* pBundleValue = bundle_get_val(pBundle, AUL_K_ORG_CALLER_PID);
594         if (pBundleValue == NULL)
595         {
596                 pBundleValue = bundle_get_val(pBundle, AUL_K_CALLER_PID);
597         }
598
599         SysTryReturn(NID_APP, pBundleValue != null, -1, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] Object not found.");
600
601         return atoi(pBundleValue);
602 }
603
604
605 AppId
606 _AppArg::GetCallerAppId(void) const
607 {
608         const char* pBundleValue = bundle_get_val(__pBundle, AUL_K_CALLER_APPID);
609
610         return String(pBundleValue);
611 }
612
613
614 AppId
615 _AppArg::GetCalleeAppId(void) const
616 {
617         const char* pBundleValue = bundle_get_val(__pBundle, AUL_K_CALLEE_APPID);
618
619         String retVal = pBundleValue;
620
621         String temp;
622         // [INFO] ugly code for submode callee
623         retVal.SubString(11, temp);
624         if (temp == L"_AppControl")
625         {
626                 String id;
627                 retVal.SubString(0, 10, id);
628                 const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(id);
629
630                 retVal = id + L'.' + name;
631                 SysLog(NID_APP, "Converted caller Id is %ls", retVal.GetPointer());
632         }
633
634         return retVal;
635 }
636
637
638 void
639 _AppArg::AddListFromBundle(ArrayList* pList, bundle* bk, const char* key)
640 {
641         bundle* pBundle = bk;
642
643         const char* p = appsvc_get_data(pBundle, key);
644         if (p)
645         {
646                 pList->Add(*new (std::nothrow) String(p));
647         }
648         else
649         {
650                 pList->Add(*new (std::nothrow) String(L""));
651         }
652 }
653
654
655 result
656 _AppArg::AddStrArray(bundle* b, const String& key, const IList* pList)
657 {
658         std::unique_ptr<char[]> pKey(_StringConverter::CopyToCharArrayN(key));
659
660         return AddStrArray(b, pKey.get(), pList);
661 }
662
663
664 result
665 _AppArg::AddStrArray(bundle* pb, const char* key, const IList* pList)
666 {
667         SysTryReturnResult(NID_APP, pb != NULL, E_INVALID_ARG, "Empty bundle.");
668
669         if (pList == null || pList->GetCount() == 0)
670         {
671                 SysLog(NID_APP, "No element added for bundle.");
672                 return E_SUCCESS;
673         }
674
675         _AppMessageImpl::AddValueArray(pb, key, pList);
676
677         _AppMessageImpl::AddData(pb, pList);
678
679         return E_SUCCESS;
680 }
681
682
683 result
684 _AppArg::AddStrMap(bundle* b, const IMap* pMap)
685 {
686         bundle* pb = b;
687         SysTryReturnResult(NID_APP, pb != NULL, E_INVALID_ARG, "Empty bundle.");
688
689         if (pMap == null || pMap->GetCount() == 0)
690         {
691                 SysLog(NID_APP, "No element added for bundle.");
692                 return E_SUCCESS;
693         }
694
695         std::unique_ptr<IMapEnumerator> pEnum (pMap->GetMapEnumeratorN());
696         while(pEnum->MoveNext() == E_SUCCESS)
697         {
698                 const String* pKey = static_cast<const String*>(pEnum->GetKey());
699                 const Object* pObj = pEnum->GetValue();
700
701                 if (pKey && pObj)
702                 {
703                         if (typeid(*pObj) == typeid(const String))
704                         {
705                                 const String* pVal = static_cast<const String*>(pEnum->GetValue());
706                                 if (pVal)
707                                 {
708                                         _AppMessageImpl::AddData(pb, *pKey, *pVal);
709                                 }
710                         }
711                         else if (typeid(*pObj) == typeid(const ArrayList))
712                         {
713                                 const ArrayList* pList = static_cast<const ArrayList*>(pEnum->GetValue());
714                                 if (pList)
715                                 {
716                                         SysLog(NID_APP, "ArrayList type");
717
718                                         _AppMessageImpl::AddValueArray(pb, *pKey, pList);
719                                 }
720                         }
721                         else if (typeid(*pObj) == typeid(const ByteBuffer))
722                         {
723                                 SysLog(NID_APP, "ByteBuffer type");
724                                 const ByteBuffer* pBuffer = static_cast<const ByteBuffer*>(pObj);
725
726                                 std::unique_ptr<char[]> pBundleKey(_StringConverter::CopyToCharArrayN(*pKey));
727                                 bundle_add_byte(b, pBundleKey.get(), pBuffer->GetPointer(), pBuffer->GetLimit());
728                         }
729                 }
730         }
731
732         return E_SUCCESS;
733 }
734
735
736 result
737 _AppArg::FillMapFromList(IMap* pMap, const IList* pList)
738 {
739         if (pMap == null || pList == null)
740         {
741                 return E_SUCCESS;
742         }
743
744         std::unique_ptr<IEnumerator> pEnum(pList->GetEnumeratorN());
745         SysTryReturnResult(NID_APP, pEnum != null, E_OUT_OF_MEMORY, "Getting enumerator failed.");
746
747         String key;
748         String value;
749         while (pEnum->MoveNext() == E_SUCCESS)
750         {
751                 String* pStr = dynamic_cast<String*>(pEnum->GetCurrent());
752
753                 int index = -1;
754                 if (pStr == null || pStr->IndexOf(L':', 0, index) != E_SUCCESS)
755                 {
756                         continue;
757                 }
758                 pStr->SubString(0, index, key);
759                 if (key.IsEmpty())
760                 {
761                         continue;
762                 }
763
764                 pStr->SubString(index + 1, value);
765
766                 pMap->Add(new String(key), new String(value));
767
768                 SysLog(NID_APP, "Added (%ls, %ls).", key.GetPointer(), value.GetPointer());
769         }
770
771         return E_SUCCESS;
772 }
773
774
775 result
776 _AppArg::FillLegacyAppControlResult(IList& list, int res, const IMap* pArgs, const Tizen::Base::String& aId)
777 {
778         switch (res)
779         {
780         case APP_CTRL_RESULT_SUCCEEDED:
781                 list.Add(* new (std::nothrow) String(APPCONTROL_RESULT_SUCCEEDED));
782                 break;
783         case APP_CTRL_RESULT_CANCELED:
784                 list.Add(* new (std::nothrow) String(APPCONTROL_RESULT_CANCELED));
785                 return E_SUCCESS;
786         case APP_CTRL_RESULT_TERMINATED:
787                 list.Add(* new (std::nothrow) String(APPCONTROL_RESULT_TERMINATED));
788                 return E_SUCCESS;
789         case APP_CTRL_RESULT_ABORTED:
790                 list.Add(* new (std::nothrow) String("aborted"));
791                 return E_SUCCESS;
792                 //case APP_CTRL_RESULT_FAILED:
793         default:
794                 list.Add(* new (std::nothrow) String(APPCONTROL_RESULT_FAILED));
795                 return E_SUCCESS;
796         }
797
798         if (pArgs == null)
799         {
800                 return E_SUCCESS;
801         }
802
803         bool isPathRegistered = false;
804         // handle APP_CTRL_RESULT_SUCCEEDED only
805         std::unique_ptr<IMapEnumerator> pMapEnum(pArgs->GetMapEnumeratorN());
806
807         while(pMapEnum->MoveNext() == E_SUCCESS)
808         {
809                 String* pKey = static_cast<String*>(pMapEnum->GetKey());
810                 if (pKey == null)
811                 {
812                         SysLog(NID_APP, "Invalid entry.");
813                         continue;
814                 }
815
816                 if (*pKey == L"path" || *pKey == L"http://tizen.org/appcontrol/data/selected")
817                 {
818                         if (!isPathRegistered)
819                         {
820                                 isPathRegistered = true;
821                         }
822                         else
823                         {
824                                 SysLog(NID_APP, "Selected path key is already registered.");
825                                 continue;
826                         }
827                 }
828
829                 String* pVal = dynamic_cast<String*>(pMapEnum->GetValue());
830                 if (pVal)
831                 {
832                         SysLog(NID_APP, "Adding value (%ls).", pVal->GetPointer());
833
834                         StringTokenizer strTok(*pVal, L';');
835                         if (strTok.GetTokenCount() == 0)
836                         {
837                                 list.Add(* new (std::nothrow) String(*pVal));
838                         }
839                         else
840                         {
841                                 String token;
842                                 while(strTok.HasMoreTokens())
843                                 {
844                                         strTok.GetNextToken(token);
845                                         list.Add(* new (std::nothrow) String(token));
846                                         SysLog(NID_APP, "Adding tokenized value (%ls).", token.GetPointer());
847                                 }
848                         }
849                 }
850         }
851
852         return E_SUCCESS;
853 }
854
855
856 ArrayList*
857 _AppArg::GetListN(bundle* b, const char* key)
858 {
859         bundle* pb = b;
860         if (pb == null)
861         {
862                 return null;
863         }
864
865         const char** pValArray = null;
866         int len = 0;
867
868         pValArray = appsvc_get_data_array(b, key, &len);
869         if (len == 0 || pValArray == null)
870         {
871                 return null;
872         }
873
874         ArrayList* pList = new (std::nothrow) ArrayList;
875         SysTryReturn(NID_APP, pList != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
876
877         pList->Construct();
878
879         for (int i = 0; i < len; i++)
880         {
881                 pList->Add(*new (std::nothrow) String(pValArray[i]));
882         }
883
884         return pList;
885 }
886
887
888 result
889 _AppArg::CreateLaunchArg(bundle* b, const String& arg)
890 {
891         SysAssertf(b != null, "Valid bundle should be supplied");
892
893         bundle* pb = b;
894
895         if (!arg.IsEmpty())
896         {
897                 const char** pSa = new (std::nothrow) const char*[1];
898                 SysTryReturnResult(NID_APP, pSa != null, E_OUT_OF_MEMORY, "Insufficient memory.");
899                 pSa[0] = _StringConverter::CopyToCharArrayN(arg);
900                 bundle_add_str_array(pb, OSP_K_ARG, pSa, 1);
901
902                 bundle_add(pb, TIZEN_NOTIFICATION_DATA, pSa[0]);
903
904                 delete[] pSa[0];
905                 delete[] pSa;
906         }
907
908         bundle_add(pb, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_LAUNCH);
909
910         return E_SUCCESS;
911 }
912
913
914 result
915 _AppArg::CreateLaunchArg(bundle* b, const IList* pList)
916 {
917         SysAssertf(b != null, "Valid bundle should be supplied");
918
919         bundle* pb = b;
920
921         AddStrArray(pb, OSP_K_ARG, pList);
922
923         bundle_add(pb, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_LAUNCH);
924
925         return E_SUCCESS;
926 }
927
928
929 result
930 _AppArg::CreateAppLaunchConditionArg(bundle* b, const String& condition, const IList* pList)
931 {
932         SysAssertf(b != null, "Valid bundle should be supplied");
933         SysLog(NID_APP, "");
934
935         bundle* pb = b;
936
937         AddStrArray(pb, OSP_K_ARG, pList);
938
939         std::unique_ptr<char[]> p(_StringConverter::CopyToCharArrayN(condition));
940         if (p)
941         {
942                 bundle_add(pb, OSP_K_COND, p.get());
943         }
944
945         bundle_add(pb, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_CONDTION);
946
947         return E_SUCCESS;
948 }
949
950
951 result
952 _AppArg::CreateAppControlArg(bundle* b, const _AppControlImpl& ac, const IList* pList)
953 {
954         SysAssertf(b != null, "Valid bundle should be supplied");
955
956         bundle* pb = b;
957
958         AddStrArray(pb, OSP_K_ARG, pList);
959
960         std::unique_ptr<char[]> pOperation(_StringConverter::CopyToCharArrayN(ac._opId));
961         if (pOperation)
962         {
963                 appsvc_set_operation(pb, pOperation.get());
964         }
965
966         bundle_add(pb, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_APPCONTROL);
967
968         return E_SUCCESS;
969 }
970
971
972 result
973 _AppArg::CreateAppControlArg(bundle* b, const _AppControlImpl& ac, const String* pUriData, const String* pMimeType, const IMap* pMap)
974 {
975         return CreateAppControlArg(b, ac._opId, pUriData, pMimeType, pMap);
976 }
977
978
979 result
980 _AppArg::CreateAppControlArg(bundle* b, const String& oId, const String* pUriData, const String* pMimeType, const IMap* pMap)
981 {
982         SysAssertf(b != null, "Valid bundle should be supplied");
983
984         bundle* pb = b;
985
986         std::unique_ptr<char[]> pOperation(_StringConverter::CopyToCharArrayN(oId));
987         if (pOperation.get())
988         {
989                 appsvc_set_operation(pb, pOperation.get());
990         }
991
992         if (pUriData)
993         {
994                 std::unique_ptr<char[]> pUri(_StringConverter::CopyToCharArrayN(*pUriData));
995                 if (pUri.get())
996                 {
997                         appsvc_set_uri(pb, pUri.get());
998                 }
999         }
1000
1001         if (pMimeType)
1002         {
1003                 std::unique_ptr<char[]> pMime(_StringConverter::CopyToCharArrayN(*pMimeType));
1004                 if (pMime.get())
1005                 {
1006                         appsvc_set_mime(pb, pMime.get());
1007                 }
1008         }
1009
1010         AddStrMap(pb, pMap);
1011
1012         bundle_add(pb, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_APPCONTROL);
1013
1014         return E_SUCCESS;
1015 }
1016
1017
1018 namespace
1019 {
1020 const int MAX_LEN_DATA_CONTROL_REQ_TYPE = 8;
1021 }
1022 result
1023 _AppArg::CreateSqlDataControlArg(bundle* b, const _SqlDataControlImpl& dc, _DataControlRequestType requestType,
1024                                                                  const IList* pArgList)
1025 {
1026         SysAssertf(b != null, "Valid bundle should be supplied");
1027
1028         bundle_add(b, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_DATACONTROL);
1029
1030         char dataControlRequestType[MAX_LEN_DATA_CONTROL_REQ_TYPE] = {0, };
1031         snprintf(dataControlRequestType, MAX_LEN_DATA_CONTROL_REQ_TYPE, "%d", static_cast<int>(requestType));
1032         bundle_add(b, OSP_K_DATACONTROL_REQUEST_TYPE, dataControlRequestType);
1033         bundle_add(b, OSP_K_DATACONTROL_PROTOCOL_VERSION, OSP_V_VERSION_2_1_0_3);
1034         bundle_add(b, AUL_K_NO_CANCEL, "1");
1035
1036         std::unique_ptr<char[]> pProvider(_StringConverter::CopyToCharArrayN(dc.__providerId));
1037         if (pProvider)
1038         {
1039                 bundle_add(b, OSP_K_DATACONTROL_PROVIDER, pProvider.get());
1040         }
1041
1042         AddStrArray(b, OSP_K_ARG, pArgList);
1043
1044         return E_SUCCESS;
1045 }
1046
1047
1048 result
1049 _AppArg::CreateMapDataControlArg(bundle* b, const _MapDataControlImpl& dc, _DataControlRequestType requestType,
1050                                                                  const IList* pArgList)
1051 {
1052         SysAssertf(b != null, "Valid bundle should be supplied");
1053
1054         bundle_add(b, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_DATACONTROL);
1055
1056         char dataControlRequestType[MAX_LEN_DATA_CONTROL_REQ_TYPE] = {0, };
1057         snprintf(dataControlRequestType, MAX_LEN_DATA_CONTROL_REQ_TYPE, "%d", static_cast < int >(requestType));
1058         bundle_add(b, OSP_K_DATACONTROL_REQUEST_TYPE, dataControlRequestType);
1059         bundle_add(b, OSP_K_DATACONTROL_PROTOCOL_VERSION, OSP_V_VERSION_2_1_0_3);
1060         bundle_add(b, AUL_K_NO_CANCEL, "1");
1061
1062         std::unique_ptr<char[]> pProvider(_StringConverter::CopyToCharArrayN(dc.__providerId));
1063         if (pProvider)
1064         {
1065                 bundle_add(b, OSP_K_DATACONTROL_PROVIDER, pProvider.get());
1066         }
1067
1068         AddStrArray(b, OSP_K_ARG, pArgList);
1069
1070         return E_SUCCESS;
1071 }
1072
1073
1074 result
1075 _AppArg::CreateResultArg(bundle* b, const IList* pList)
1076 {
1077         SysAssertf(b != null, "Valid bundle should be supplied");
1078
1079         bundle* pb = b;
1080
1081         AddStrArray(pb, OSP_K_ARG, pList);
1082
1083         _AppMessageImpl::AddData(pb, pList);
1084
1085         return E_SUCCESS;
1086 }
1087
1088
1089 result
1090 _AppArg::CreateResultArg(bundle* b, const IMap* pMap)
1091 {
1092         SysAssertf(b != null, "Valid bundle should be supplied");
1093
1094         bundle* pb = b;
1095
1096         AddStrMap(pb, pMap);
1097
1098         return E_SUCCESS;
1099 }
1100
1101
1102 bundle*
1103 _AppArg::CreateBundleFromSvc(void* svc)
1104 {
1105         bundle* pBundle = GetBundleFromSvc(svc);
1106         if (pBundle)
1107         {
1108                 return bundle_dup(pBundle);
1109         }
1110
1111         return null;
1112 }
1113
1114
1115 bundle*
1116 _AppArg::GetBundleFromSvc(void* svc)
1117 {
1118         struct DummyS
1119         {
1120                 int dummy1;
1121                 int dummy2;
1122                 bundle* pData;
1123         };
1124
1125         DummyS* pDummy = static_cast<DummyS*>(svc);
1126
1127         if (pDummy && pDummy->pData)
1128         {
1129                 return pDummy->pData;
1130         }
1131
1132         return NULL;
1133 }
1134
1135
1136 String
1137 _AppArg::GetRequestId(int num)
1138 {
1139         String str;
1140         str.Format(10, L"req%05d", num);
1141         return str;
1142 }
1143
1144
1145 int
1146 _AppArg::GetRequestId(const String& str)
1147 {
1148         int i = 0;
1149         String sub;
1150
1151         result r = str.SubString(3, sub);
1152         SysTryReturn(NID_APP, !IsFailed(r), -1, r, "[%s] Propagating.", GetErrorMessage(r));
1153
1154         r = Integer::Parse(sub, i);
1155         SysTryReturn(NID_APP, !IsFailed(r), -1, r, "[%s] Propagating.", GetErrorMessage(r));
1156
1157         return i;
1158 }
1159
1160
1161 void
1162 _AppArg::UpdateAppId(bundle* b, const AppId& appId)
1163 {
1164         SysTryReturnVoidResult(NID_APP, b != null, E_INVALID_STATE, "[E_INVALID_STATE] Improper bundle state.");
1165
1166         std::unique_ptr<char[]> pId(_StringConverter::CopyToCharArrayN(appId));
1167         SysTryReturnVoidResult(NID_APP, pId != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Converting %ls failed.", appId.GetPointer());
1168
1169         int res = bundle_add(b, OSP_K_APPID, pId.get());
1170         if (res < 0 && errno == EPERM) // key exists
1171         {
1172                 bundle_del(b, OSP_K_APPID);
1173                 bundle_add(b, OSP_K_APPID, pId.get());
1174         }
1175
1176         appsvc_set_appid(b, pId.get());
1177 }
1178
1179
1180 void
1181 _AppArg::UpdateRequestId(bundle* pBundle, int reqId)
1182 {
1183         SysTryReturnVoidResult(NID_APP, pBundle != null, E_INVALID_STATE, "[E_INVALID_STATE] Improper bundle state.");
1184
1185         if (reqId < 0)
1186         {
1187                 //SysLog(NID_APP, "Requested ID is %d", reqId);
1188                 return;
1189         }
1190
1191         char buffer[32] = {0, };
1192         snprintf(buffer, 32, "%d", reqId);
1193         int res = bundle_add(pBundle, OSP_K_REQUEST_ID, buffer);
1194         if (res < 0 && errno == EPERM) // key exists
1195         {
1196                 bundle_del(pBundle, OSP_K_REQUEST_ID);
1197                 bundle_add(pBundle, OSP_K_REQUEST_ID, buffer);
1198         }
1199 }
1200
1201 void
1202 _AppArg::UpdateKeyValue(bundle* pBundle, const char* pKey, const String& value)
1203 {
1204         SysTryReturnVoidResult(NID_APP, pBundle != null, E_INVALID_STATE, "[E_INVALID_STATE] Improper bundle state.");
1205
1206         char pBuffer[128] = {0, };
1207         snprintf(pBuffer, 128, "%ls", value.GetPointer());
1208         int res = bundle_add(pBundle, pKey, pBuffer);
1209         if (res < 0 && errno == EPERM) // key exists
1210         {
1211                 bundle_del(pBundle, pKey);
1212                 bundle_add(pBundle, pKey, pBuffer);
1213         }
1214 }
1215
1216 int
1217 _AppArg::GetRequestIdFromBundle(bundle* pBundle)
1218 {
1219         const char* p = appsvc_get_data(pBundle, OSP_K_REQUEST_ID);
1220         if (p == NULL)
1221         {
1222                 return -1;
1223         }
1224
1225         int i = atoi(p);
1226         return (i < 0) ? -1 : i;
1227 }
1228
1229
1230 result
1231 _AppArg::UpdateWindowHandle(bundle* pBundle, long handle)
1232 {
1233         appsvc_allow_transient_app(pBundle, handle);
1234
1235         SysLog(NID_APP, "Window Handle 0x%x added.", handle);
1236
1237         return E_SUCCESS;
1238 }
1239
1240
1241 void
1242 _AppArg::PrintSvcHandle(void* svc)
1243 {
1244         service_h service = static_cast<service_h>(svc);
1245
1246         if (service == null)
1247         {
1248                 return;
1249         }
1250
1251         Print(GetBundleFromSvc(service));
1252 }
1253
1254
1255 static void
1256 BundlePrintIterFnCb(const char* pKey, const int type, const bundle_keyval_t* pVal, void* pData)
1257 {
1258         if (pKey && pVal)
1259         {
1260                 size_t size = 0;
1261                 char* pStr = NULL;
1262                 switch (type)
1263                 {
1264                 case BUNDLE_TYPE_STR:
1265                         bundle_keyval_get_basic_val(const_cast<bundle_keyval_t*>(pVal), reinterpret_cast<void**>(&pStr), &size);
1266                         if (pStr)
1267                         {
1268                                 SysSecureLog(NID_APP, "(%s, %s)", pKey, pStr);
1269                         }
1270                         break;
1271                 default:
1272                         SysLog(NID_APP, "Invalid type for %s : %d", pKey, type);
1273                         break;
1274                 }
1275         }
1276 }
1277
1278 void
1279 _AppArg::Print(bundle* b)
1280 {
1281         if (b == null)
1282         {
1283                 return;
1284         }
1285
1286         const char* p = null;
1287         p = appsvc_get_data(b, AUL_K_CALLER_PID);
1288         if (p)
1289         {
1290                 SysLog(NID_APP, "CallerPId[%s]", p);
1291         }
1292
1293         p = appsvc_get_data(b, AUL_K_WAIT_RESULT);
1294         if (p)
1295         {
1296                 SysLog(NID_APP, "WaitResult[%s]", p);
1297         }
1298
1299         p = appsvc_get_data(b, OSP_K_COND);
1300         if (p)
1301         {
1302                 SysLog(NID_APP, "Condition[%s]", p);
1303         }
1304
1305         p = appsvc_get_operation(b);
1306         if (p)
1307         {
1308                 SysLog(NID_APP, "operation[%s]", p);
1309         }
1310
1311         p = appsvc_get_uri(b);
1312         if (p)
1313         {
1314                 SysLog(NID_APP, "uri[%s]", p);
1315         }
1316
1317         p = appsvc_get_mime(b);
1318         if (p)
1319         {
1320                 SysLog(NID_APP, "mime[%s]", p);
1321         }
1322
1323         p = appsvc_get_category(b);
1324         if (p)
1325         {
1326                 SysLog(NID_APP, "Category[%s]", p);
1327         }
1328
1329         bundle_foreach(b, BundlePrintIterFnCb, NULL);
1330
1331         int len = 0;
1332         const char** pa = appsvc_get_data_array(b, OSP_K_ARG, &len);
1333         if (pa)
1334         {
1335                 for (int i = 0; i < len; i++)
1336                 {
1337                         if (pa[i])
1338                         {
1339                                 SysLog(NID_APP, "%dth arg [%s]", i, pa[i]);
1340                         }
1341                 }
1342         }
1343 }
1344
1345 } } // Tizen::App