AppControl 2.0/2.1 argument handling
[platform/framework/native/appfw.git] / src / app / FApp_AppArg.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_AppArg.cpp
20 * @brief        This is the implementation for the _AppArg.cpp class.
21 */
22
23 #include <cstdio>
24 #include <cstdlib>
25 #include <vector>
26 #include <new>
27 #include <typeinfo>
28 #include <unique_ptr.h>
29
30 #include <aul.h>
31 #include <app.h>
32 #include <appsvc/appsvc.h>
33 #include <Ecore_X.h>
34
35 #include <FBaseInteger.h>
36 #include <FBaseColArrayList.h>
37 #include <FBaseColHashMap.h>
38 #include <FBaseUtilStringTokenizer.h>
39
40 #include <FBaseSysLog.h>
41 #include <FBase_StringConverter.h>
42
43 #include "FApp_MapDataControlImpl.h"
44 #include "FApp_AppControlImpl.h"
45 #include "FApp_SqlDataControlImpl.h"
46 #include "FApp_AppControlEventArg.h"
47 #include "FApp_AppArg.h"
48 #include "FApp_AppMessageImpl.h"
49 #include "FAppPkg_PackageManagerImpl.h"
50
51 using namespace Tizen::Base;
52 using namespace Tizen::Base::Collection;
53 using namespace Tizen::Base::Utility;
54 using namespace Tizen::App::Package;
55
56
57 extern "C" int appsvc_allow_transient_app(bundle*, Ecore_X_Window);
58
59 namespace Tizen { namespace App
60 {
61
62 static const char OSP_V_LAUNCH_TYPE_LAUNCH[] = "launch";
63 static const char OSP_V_LAUNCH_TYPE_APPCONTROL[] = "appcontrol";
64 static const char OSP_V_LAUNCH_TYPE_DATACONTROL[] = "datacontrol";
65 static const char OSP_V_LAUNCH_TYPE_CONDTION[] = "condition";
66 static const char OSP_V_REQUEST_TYPE_SQL_QUERY[] = "sql_query";
67 static const char OSP_V_REQUEST_TYPE_SQL_INSERT[] = "sql_insert";
68 static const char OSP_V_REQUEST_TYPE_SQL_UPDATE[] = "sql_update";
69 static const char OSP_V_REQUEST_TYPE_SQL_DELETE[] = "sql_delete";
70 static const char OSP_V_REQUEST_TYPE_MAP_QEURY[] = "map_query";
71 static const char OSP_V_REQUEST_TYPE_MAP_INSERT[] = "map_insert";
72 static const char OSP_V_REQUEST_TYPE_MAP_UPDATE[] = "map_update";
73 static const char OSP_V_REQUEST_TYPE_MAP_DELETE[] = "map_delete";
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                 default:
434                         SysLog(NID_APP, "Invalid type for %s : %d", pKey, type);
435                         break;
436                 }
437         }
438 }
439
440 result
441 _AppArg::SetArgMap(bundle* pBundle, HashMap* pMap)
442 {
443         bundle_foreach(pBundle, BundleIterFnCb, reinterpret_cast<void*>(pMap));
444
445         return E_SUCCESS;
446 }
447
448 result
449 _AppArg::SetArgList(bundle* pBundle, ArrayList* pList)
450 {
451         // actual argument below
452         int len = 0;
453         const char** pa = appsvc_get_data_array(pBundle, OSP_K_ARG, &len);
454         if (pa)
455         {
456                 for (int i = 0; i < len; i++)
457                 {
458                         if (pa[i])
459                         {
460                                 //SysLog(NID_APP, "%d/%dth arg [%s]", i, len, pa[i]);
461                                 pList->Add(*new (std::nothrow) String(pa[i]));
462                         }
463                 }
464         }
465
466         const char* p = appsvc_get_uri(pBundle);
467         if (p)
468         {
469                 pList->Add(*new (std::nothrow) String(p));
470                 SysLog(NID_APP, "argument is %s", p);
471         }
472
473         String tmp;
474         p = appsvc_get_data(pBundle, SMS_KEY_SERVICE_CALLER);
475         if (p)
476         {
477                 tmp.Format(60, L"%s:%s", SMS_KEY_SERVICE_CALLER, p);
478                 pList->Add(*new (std::nothrow) String(tmp));
479                 SysLog(NID_APP, "service_caller is %s", p);
480         }
481         
482         p = appsvc_get_data(pBundle, SMS_KEY_SERVICE_DATA);
483         if (p)
484         {
485                 tmp.Format(60, L"%s:%s", SMS_KEY_SERVICE_DATA, p);
486                 pList->Add(*new (std::nothrow) String(tmp));
487                 SysLog(NID_APP, "service_data is set");
488         }
489         
490         p = appsvc_get_data(pBundle, SAMSUNG_ACCOUNT_KEY_CLIENT_ID);
491         if (p)
492         {
493                 tmp.Format(60, L"%s:%s", SAMSUNG_ACCOUNT_KEY_CLIENT_ID, p);
494                 pList->Add(*new (std::nothrow) String(tmp));
495                 SysLog(NID_APP, "client_id is %s", p);
496         }
497         
498         p = appsvc_get_data(pBundle, SAMSUNG_ACCOUNT_KEY_CLIENT_SECRET);
499         if (p)
500         {
501                 tmp.Format(60, L"%s:%s", SAMSUNG_ACCOUNT_KEY_CLIENT_SECRET, p);
502                 pList->Add(*new (std::nothrow) String(tmp));
503                 SysLog(NID_APP, "client_secret is %s", p);
504         }
505
506         p = appsvc_get_data(pBundle, SAMSUNG_ACCOUNT_KEY_SERVICE_CATEGORY);
507         if (p)
508         {
509                 tmp.Format(60, L"%s:%s", SAMSUNG_ACCOUNT_KEY_SERVICE_CATEGORY, p);
510                 pList->Add(*new (std::nothrow) String(tmp));
511                 SysLog(NID_APP, "service_category is %s", p);
512         }
513
514         return E_SUCCESS;
515 }
516
517
518 String
519 _AppArg::GetValue(const char* key) const
520 {
521         const char* p = appsvc_get_data(__pBundle, key);
522         return String(p);
523 }
524
525
526 _AppHandler
527 _AppArg::GetHandler(bundle* b)
528 {
529         SysTryReturn(NID_APP, b != null, _APP_HANDLER_NONE, E_INVALID_STATE, "[E_INVALID_STATE] Improper bundle state.");
530
531         const char* p = null;
532
533         p = appsvc_get_data(b, OSP_K_LAUNCH_TYPE);
534
535         if (p)
536         {
537                 if (strcmp(p, OSP_V_LAUNCH_TYPE_DATACONTROL) == 0)
538                 {
539                         return _APP_HANDLER_DATACONTROL;
540                 }
541
542                 if (strcmp(p, OSP_V_LAUNCH_TYPE_APPCONTROL) == 0)
543                 {
544                         SysLog(NID_APP, "Building AppControl arguments.");
545
546                         return _APP_HANDLER_APPCONTROL;
547                 }
548                 else
549                 {
550                         // not appcontrol nor datacontrol => normal launch or condlaunch
551                         p = appsvc_get_data(b, OSP_K_COND);
552                         if (p)
553                         {
554                                 SysLog(NID_APP, "Building Conditional AppLaunch arguments.");
555                                 return _APP_HANDLER_LAUNCH_COND;
556                         }
557                         else
558                         {
559                                 SysLog(NID_APP, "Building Normal AppLaunch arguments.");
560                                 return _APP_HANDLER_LAUNCH_NORMAL;
561                         }
562                 }
563         }
564
565         // fallback
566         return _APP_HANDLER_APPCONTROL;
567 }
568
569
570 int
571 _AppArg::GetCallerPid(bundle* pBundle)
572 {
573         const char* pBundleValue = bundle_get_val(pBundle, AUL_K_ORG_CALLER_PID);
574         if (pBundleValue == NULL)
575         {
576                 pBundleValue = bundle_get_val(pBundle, AUL_K_CALLER_PID);
577         }
578
579         SysTryReturn(NID_APP, pBundleValue != null, -1, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] Object not found.");
580
581         return atoi(pBundleValue);
582 }
583
584
585 AppId
586 _AppArg::GetCallerAppId(void) const
587 {
588         const char* pBundleValue = bundle_get_val(__pBundle, AUL_K_CALLER_APPID);
589
590         return String(pBundleValue);
591 }
592
593
594 AppId
595 _AppArg::GetCalleeAppId(void) const
596 {
597         const char* pBundleValue = bundle_get_val(__pBundle, AUL_K_CALLEE_APPID);
598
599         String retVal = pBundleValue;
600
601         String temp;
602         // [INFO] ugly code for submode callee
603         retVal.SubString(11, temp);
604         if (temp == L"_AppControl")
605         {
606                 String id;
607                 retVal.SubString(0, 10, id);
608                 const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(id);
609
610                 retVal = id + L'.' + name;
611                 SysLog(NID_APP, "Converted caller Id is %ls", retVal.GetPointer());
612         }
613
614         return retVal;
615 }
616
617
618 void
619 _AppArg::AddListFromBundle(ArrayList* pList, bundle* bk, const char* key)
620 {
621         bundle* pBundle = bk;
622
623         const char* p = appsvc_get_data(pBundle, key);
624         if (p)
625         {
626                 pList->Add(*new (std::nothrow) String(p));
627         }
628         else
629         {
630                 pList->Add(*new (std::nothrow) String(L""));
631         }
632 }
633
634
635 result
636 _AppArg::AddStrArray(bundle* b, const String& key, const IList* pList)
637 {
638         std::unique_ptr<char[]> pKey(_StringConverter::CopyToCharArrayN(key));
639
640         return AddStrArray(b, pKey.get(), pList);
641 }
642
643
644 result
645 _AppArg::AddStrArray(bundle* pb, const char* key, const IList* pList)
646 {
647         SysTryReturnResult(NID_APP, pb != NULL, E_INVALID_ARG, "Empty bundle.");
648
649         if (pList == null || pList->GetCount() == 0)
650         {
651                 SysLog(NID_APP, "No element added for bundle.");
652                 return E_SUCCESS;
653         }
654
655         _AppMessageImpl::AddValueArray(pb, key, pList);
656
657         _AppMessageImpl::AddData(pb, pList);
658
659         return E_SUCCESS;
660 }
661
662
663 result
664 _AppArg::AddStrMap(bundle* b, const IMap* pMap)
665 {
666         bundle* pb = b;
667         SysTryReturnResult(NID_APP, pb != NULL, E_INVALID_ARG, "Empty bundle.");
668
669         if (pMap == null || pMap->GetCount() == 0)
670         {
671                 SysLog(NID_APP, "No element added for bundle.");
672                 return E_SUCCESS;
673         }
674
675         std::unique_ptr<IMapEnumerator> pEnum (pMap->GetMapEnumeratorN());
676         while(pEnum->MoveNext() == E_SUCCESS)
677         {
678                 const String* pKey = static_cast<const String*>(pEnum->GetKey());
679                 const Object* pObj = pEnum->GetValue();
680
681                 if (pKey && pObj)
682                 {
683                         if (typeid(*pObj) == typeid(const String))
684                         {
685                                 const String* pVal = static_cast<const String*>(pEnum->GetValue());
686                                 if (pVal)
687                                 {
688                                         _AppMessageImpl::AddData(pb, *pKey, *pVal);
689                                 }
690                         }
691                         else if (typeid(*pObj) == typeid(const ArrayList))
692                         {
693                                 const ArrayList* pList = static_cast<const ArrayList*>(pEnum->GetValue());
694                                 if (pList)
695                                 {
696                                         SysLog(NID_APP, "ArrayList type");
697
698                                         _AppMessageImpl::AddValueArray(pb, *pKey, pList);
699                                 }
700                         }
701                         else if (typeid(*pObj) == typeid(const ByteBuffer))
702                         {
703                                 SysLog(NID_APP, "ByteBuffer type");
704                         }
705                 }
706         }
707
708         return E_SUCCESS;
709 }
710
711
712 result
713 _AppArg::FillMapFromList(IMap* pMap, const IList* pList)
714 {
715         if (pMap == null || pList == null)
716         {
717                 return E_SUCCESS;
718         }
719
720         std::unique_ptr<IEnumerator> pEnum(pList->GetEnumeratorN());
721         SysTryReturnResult(NID_APP, pEnum != null, E_OUT_OF_MEMORY, "Getting enumerator failed.");
722
723         String key;
724         String value;
725         while (pEnum->MoveNext() == E_SUCCESS)
726         {
727                 String* pStr = dynamic_cast<String*>(pEnum->GetCurrent());
728
729                 int index = -1;
730                 if (pStr == null || pStr->IndexOf(L':', 0, index) != E_SUCCESS)
731                 {
732                         continue;
733                 }
734                 pStr->SubString(0, index, key);
735                 if (key.IsEmpty())
736                 {
737                         continue;
738                 }
739
740                 pStr->SubString(index + 1, value);
741
742                 pMap->Add(new String(key), new String(value));
743
744                 SysLog(NID_APP, "Added (%ls, %ls).", key.GetPointer(), value.GetPointer());
745         }
746
747         return E_SUCCESS;
748 }
749
750
751 result
752 _AppArg::FillLegacyAppControlResult(IList& list, int res, const IMap* pArgs, const Tizen::Base::String& aId)
753 {
754         switch (res)
755         {
756         case APP_CTRL_RESULT_SUCCEEDED:
757                 list.Add(* new (std::nothrow) String(APPCONTROL_RESULT_SUCCEEDED));
758                 break;
759         case APP_CTRL_RESULT_CANCELED:
760                 list.Add(* new (std::nothrow) String(APPCONTROL_RESULT_CANCELED));
761                 return E_SUCCESS;
762         case APP_CTRL_RESULT_TERMINATED:
763                 list.Add(* new (std::nothrow) String(APPCONTROL_RESULT_TERMINATED));
764                 return E_SUCCESS;
765         case APP_CTRL_RESULT_ABORTED:
766                 list.Add(* new (std::nothrow) String("aborted"));
767                 return E_SUCCESS;
768                 //case APP_CTRL_RESULT_FAILED:
769         default:
770                 list.Add(* new (std::nothrow) String(APPCONTROL_RESULT_FAILED));
771                 return E_SUCCESS;
772         }
773
774         if (pArgs == null)
775         {
776                 return E_SUCCESS;
777         }
778
779         bool isPathRegistered = false;
780         // handle APP_CTRL_RESULT_SUCCEEDED only
781         std::unique_ptr<IMapEnumerator> pMapEnum(pArgs->GetMapEnumeratorN());
782
783         while(pMapEnum->MoveNext() == E_SUCCESS)
784         {
785                 String* pKey = static_cast<String*>(pMapEnum->GetKey());
786                 if (pKey == null)
787                 {
788                         SysLog(NID_APP, "Invalid entry.");
789                         continue;
790                 }
791
792                 if (*pKey == L"path" || *pKey == L"http://tizen.org/appcontrol/data/selected")
793                 {
794                         if (!isPathRegistered)
795                         {
796                                 isPathRegistered = true;
797                         }
798                         else
799                         {
800                                 SysLog(NID_APP, "Selected path key is already registered.");
801                                 continue;
802                         }
803                 }
804
805                 String* pVal = dynamic_cast<String*>(pMapEnum->GetValue());
806                 if (pVal)
807                 {
808                         SysLog(NID_APP, "Adding value (%ls).", pVal->GetPointer());
809
810                         StringTokenizer strTok(*pVal, L';');
811                         if (strTok.GetTokenCount() == 0)
812                         {
813                                 list.Add(* new (std::nothrow) String(*pVal));
814                         }
815                         else
816                         {
817                                 String token;
818                                 while(strTok.HasMoreTokens())
819                                 {
820                                         strTok.GetNextToken(token);
821                                         list.Add(* new (std::nothrow) String(token));
822                                         SysLog(NID_APP, "Adding tokenized value (%ls).", token.GetPointer());
823                                 }
824                         }
825                 }
826         }
827
828         return E_SUCCESS;
829 }
830
831
832 ArrayList*
833 _AppArg::GetListN(bundle* b, const char* key)
834 {
835         bundle* pb = b;
836         if (pb == null)
837         {
838                 return null;
839         }
840
841         const char** pValArray = null;
842         int len = 0;
843
844         pValArray = appsvc_get_data_array(b, key, &len);
845         if (len == 0 || pValArray == null)
846         {
847                 return null;
848         }
849
850         ArrayList* pList = new (std::nothrow) ArrayList;
851         SysTryReturn(NID_APP, pList != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
852
853         pList->Construct();
854
855         for (int i = 0; i < len; i++)
856         {
857                 pList->Add(*new (std::nothrow) String(pValArray[i]));
858         }
859
860         return pList;
861 }
862
863
864 result
865 _AppArg::CreateLaunchArg(bundle* b, const String& arg)
866 {
867         SysAssertf(b != null, "Valid bundle should be supplied");
868
869         bundle* pb = b;
870
871         if (!arg.IsEmpty())
872         {
873                 const char** pSa = new (std::nothrow) const char*[1];
874                 SysTryReturnResult(NID_APP, pSa != null, E_OUT_OF_MEMORY, "Insufficient memory.");
875                 pSa[0] = _StringConverter::CopyToCharArrayN(arg);
876                 bundle_add_str_array(pb, OSP_K_ARG, pSa, 1);
877
878                 bundle_add(pb, TIZEN_NOTIFICATION_DATA, pSa[0]);
879
880                 delete[] pSa[0];
881                 delete[] pSa;
882         }
883
884         bundle_add(pb, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_LAUNCH);
885
886         return E_SUCCESS;
887 }
888
889
890 result
891 _AppArg::CreateLaunchArg(bundle* b, const IList* pList)
892 {
893         SysAssertf(b != null, "Valid bundle should be supplied");
894
895         bundle* pb = b;
896
897         AddStrArray(pb, OSP_K_ARG, pList);
898
899         bundle_add(pb, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_LAUNCH);
900
901         return E_SUCCESS;
902 }
903
904
905 result
906 _AppArg::CreateAppLaunchConditionArg(bundle* b, const String& condition, const IList* pList)
907 {
908         SysAssertf(b != null, "Valid bundle should be supplied");
909         SysLog(NID_APP, "");
910
911         bundle* pb = b;
912
913         AddStrArray(pb, OSP_K_ARG, pList);
914
915         std::unique_ptr<char[]> p(_StringConverter::CopyToCharArrayN(condition));
916         if (p)
917         {
918                 bundle_add(pb, OSP_K_COND, p.get());
919         }
920
921         bundle_add(pb, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_CONDTION);
922
923         return E_SUCCESS;
924 }
925
926
927 result
928 _AppArg::CreateAppControlArg(bundle* b, const _AppControlImpl& ac, const IList* pList)
929 {
930         SysAssertf(b != null, "Valid bundle should be supplied");
931
932         bundle* pb = b;
933
934         AddStrArray(pb, OSP_K_ARG, pList);
935
936         std::unique_ptr<char[]> pOperation(_StringConverter::CopyToCharArrayN(ac._opId));
937         if (pOperation)
938         {
939                 appsvc_set_operation(pb, pOperation.get());
940         }
941
942         bundle_add(pb, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_APPCONTROL);
943
944         return E_SUCCESS;
945 }
946
947
948 result
949 _AppArg::CreateAppControlArg(bundle* b, const _AppControlImpl& ac, const String* pUriData, const String* pMimeType, const IMap* pMap)
950 {
951         return CreateAppControlArg(b, ac._opId, pUriData, pMimeType, pMap);
952 }
953
954
955 result
956 _AppArg::CreateAppControlArg(bundle* b, const String& oId, const String* pUriData, const String* pMimeType, const IMap* pMap)
957 {
958         SysAssertf(b != null, "Valid bundle should be supplied");
959
960         bundle* pb = b;
961
962         std::unique_ptr<char[]> pOperation(_StringConverter::CopyToCharArrayN(oId));
963         if (pOperation.get())
964         {
965                 appsvc_set_operation(pb, pOperation.get());
966         }
967
968         if (pUriData)
969         {
970                 std::unique_ptr<char[]> pUri(_StringConverter::CopyToCharArrayN(*pUriData));
971                 if (pUri.get())
972                 {
973                         appsvc_set_uri(pb, pUri.get());
974                 }
975         }
976
977         if (pMimeType)
978         {
979                 std::unique_ptr<char[]> pMime(_StringConverter::CopyToCharArrayN(*pMimeType));
980                 if (pMime.get())
981                 {
982                         appsvc_set_mime(pb, pMime.get());
983                 }
984         }
985
986         AddStrMap(pb, pMap);
987
988         bundle_add(pb, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_APPCONTROL);
989
990         return E_SUCCESS;
991 }
992
993
994 namespace
995 {
996 const int MAX_LEN_DATA_CONTROL_REQ_TYPE = 8;
997 }
998 result
999 _AppArg::CreateSqlDataControlArg(bundle* b, const _SqlDataControlImpl& dc, _DataControlRequestType requestType,
1000                                                                  const IList* pArgList)
1001 {
1002         SysAssertf(b != null, "Valid bundle should be supplied");
1003
1004         bundle_add(b, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_DATACONTROL);
1005
1006         char dataControlRequestType[MAX_LEN_DATA_CONTROL_REQ_TYPE] = {0, };
1007         snprintf(dataControlRequestType, MAX_LEN_DATA_CONTROL_REQ_TYPE, "%d", static_cast<int>(requestType));
1008         bundle_add(b, OSP_K_DATACONTROL_REQUEST_TYPE, dataControlRequestType);
1009
1010         std::unique_ptr<char[]> pProvider(_StringConverter::CopyToCharArrayN(dc.__providerId));
1011         if (pProvider)
1012         {
1013                 bundle_add(b, OSP_K_DATACONTROL_PROVIDER, pProvider.get());
1014         }
1015
1016         AddStrArray(b, OSP_K_ARG, pArgList);
1017
1018         return E_SUCCESS;
1019 }
1020
1021
1022 result
1023 _AppArg::CreateMapDataControlArg(bundle* b, const _MapDataControlImpl& 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
1034         std::unique_ptr<char[]> pProvider(_StringConverter::CopyToCharArrayN(dc.__providerId));
1035         if (pProvider)
1036         {
1037                 bundle_add(b, OSP_K_DATACONTROL_PROVIDER, pProvider.get());
1038         }
1039
1040         AddStrArray(b, OSP_K_ARG, pArgList);
1041
1042         return E_SUCCESS;
1043 }
1044
1045
1046 result
1047 _AppArg::CreateResultArg(bundle* b, const IList* pList)
1048 {
1049         SysAssertf(b != null, "Valid bundle should be supplied");
1050
1051         bundle* pb = b;
1052
1053         AddStrArray(pb, OSP_K_ARG, pList);
1054
1055         _AppMessageImpl::AddData(pb, pList);
1056
1057         return E_SUCCESS;
1058 }
1059
1060
1061 result
1062 _AppArg::CreateResultArg(bundle* b, const IMap* pMap)
1063 {
1064         SysAssertf(b != null, "Valid bundle should be supplied");
1065
1066         bundle* pb = b;
1067
1068         AddStrMap(pb, pMap);
1069
1070         return E_SUCCESS;
1071 }
1072
1073
1074 bundle*
1075 _AppArg::CreateBundleFromSvc(void* svc)
1076 {
1077         bundle* pBundle = GetBundleFromSvc(svc);
1078         if (pBundle)
1079         {
1080                 return bundle_dup(pBundle);
1081         }
1082
1083         return null;
1084 }
1085
1086
1087 bundle*
1088 _AppArg::GetBundleFromSvc(void* svc)
1089 {
1090         struct DummyS
1091         {
1092                 int dummy1;
1093                 int dummy2;
1094                 bundle* pData;
1095         };
1096
1097         DummyS* pDummy = static_cast<DummyS*>(svc);
1098
1099         if (pDummy && pDummy->pData)
1100         {
1101                 return pDummy->pData;
1102         }
1103
1104         return NULL;
1105 }
1106
1107
1108 String
1109 _AppArg::GetRequestId(int num)
1110 {
1111         String str;
1112         str.Format(10, L"req%05d", num);
1113         return str;
1114 }
1115
1116
1117 int
1118 _AppArg::GetRequestId(const String& str)
1119 {
1120         int i = 0;
1121         String sub;
1122
1123         result r = str.SubString(3, sub);
1124         SysTryReturn(NID_APP, !IsFailed(r), -1, r, "[%s] Propagating.", GetErrorMessage(r));
1125
1126         r = Integer::Parse(sub, i);
1127         SysTryReturn(NID_APP, !IsFailed(r), -1, r, "[%s] Propagating.", GetErrorMessage(r));
1128
1129         return i;
1130 }
1131
1132
1133 void
1134 _AppArg::UpdateAppId(bundle* b, const AppId& appId)
1135 {
1136         SysTryReturnVoidResult(NID_APP, b != null, E_INVALID_STATE, "[E_INVALID_STATE] Improper bundle state.");
1137
1138         std::unique_ptr<char[]> pId(_StringConverter::CopyToCharArrayN(appId));
1139         SysTryReturnVoidResult(NID_APP, pId != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Converting %ls failed.", appId.GetPointer());
1140
1141         int res = bundle_add(b, OSP_K_APPID, pId.get());
1142         if (res < 0 && errno == EPERM) // key exists
1143         {
1144                 bundle_del(b, OSP_K_APPID);
1145                 bundle_add(b, OSP_K_APPID, pId.get());
1146         }
1147
1148         appsvc_set_appid(b, pId.get());
1149 }
1150
1151
1152 void
1153 _AppArg::UpdateRequestId(bundle* pBundle, int reqId)
1154 {
1155         SysTryReturnVoidResult(NID_APP, pBundle != null, E_INVALID_STATE, "[E_INVALID_STATE] Improper bundle state.");
1156
1157         if (reqId < 0)
1158         {
1159                 //SysLog(NID_APP, "Requested ID is %d", reqId);
1160                 return;
1161         }
1162
1163         char buffer[32] = {0, };
1164         snprintf(buffer, 32, "%d", reqId);
1165         int res = bundle_add(pBundle, OSP_K_REQUEST_ID, buffer);
1166         if (res < 0 && errno == EPERM) // key exists
1167         {
1168                 bundle_del(pBundle, OSP_K_REQUEST_ID);
1169                 bundle_add(pBundle, OSP_K_REQUEST_ID, buffer);
1170         }
1171 }
1172
1173 void
1174 _AppArg::UpdateKeyValue(bundle* pBundle, const char* pKey, const String& value)
1175 {
1176         SysTryReturnVoidResult(NID_APP, pBundle != null, E_INVALID_STATE, "[E_INVALID_STATE] Improper bundle state.");
1177
1178         char pBuffer[128] = {0, };
1179         snprintf(pBuffer, 128, "%ls", value.GetPointer());
1180         int res = bundle_add(pBundle, pKey, pBuffer);
1181         if (res < 0 && errno == EPERM) // key exists
1182         {
1183                 bundle_del(pBundle, pKey);
1184                 bundle_add(pBundle, pKey, pBuffer);
1185         }
1186 }
1187
1188 int
1189 _AppArg::GetRequestIdFromBundle(bundle* pBundle)
1190 {
1191         const char* p = appsvc_get_data(pBundle, OSP_K_REQUEST_ID);
1192         if (p == NULL)
1193         {
1194                 return -1;
1195         }
1196
1197         int i = atoi(p);
1198         return (i < 0) ? -1 : i;
1199 }
1200
1201
1202 result
1203 _AppArg::UpdateWindowHandle(bundle* pBundle, long handle)
1204 {
1205         appsvc_allow_transient_app(pBundle, handle);
1206
1207         SysLog(NID_APP, "Window Handle 0x%x added.", handle);
1208
1209         return E_SUCCESS;
1210 }
1211
1212
1213 void
1214 _AppArg::PrintSvcHandle(void* svc)
1215 {
1216         service_h service = static_cast<service_h>(svc);
1217
1218         if (service == null)
1219         {
1220                 return;
1221         }
1222
1223         Print(GetBundleFromSvc(service));
1224 }
1225
1226
1227 static void
1228 BundlePrintIterFnCb(const char* pKey, const int type, const bundle_keyval_t* pVal, void* pData)
1229 {
1230         if (pKey && pVal)
1231         {
1232                 size_t size = 0;
1233                 char* pStr = NULL;
1234                 switch (type)
1235                 {
1236                 case BUNDLE_TYPE_STR:
1237                         bundle_keyval_get_basic_val(const_cast<bundle_keyval_t*>(pVal), reinterpret_cast<void**>(&pStr), &size);
1238                         if (pStr)
1239                         {
1240                                 SysLog(NID_APP, "(%s, %s)", pKey, pStr);
1241                         }
1242                         break;
1243                 default:
1244                         SysLog(NID_APP, "Invalid type for %s : %d", pKey, type);
1245                         break;
1246                 }
1247         }
1248 }
1249
1250 void
1251 _AppArg::Print(bundle* b)
1252 {
1253         if (b == null)
1254         {
1255                 return;
1256         }
1257
1258         const char* p = null;
1259         p = appsvc_get_data(b, AUL_K_CALLER_PID);
1260         if (p)
1261         {
1262                 SysLog(NID_APP, "CallerPId[%s]", p);
1263         }
1264
1265         p = appsvc_get_data(b, AUL_K_WAIT_RESULT);
1266         if (p)
1267         {
1268                 SysLog(NID_APP, "WaitResult[%s]", p);
1269         }
1270
1271         p = appsvc_get_data(b, OSP_K_COND);
1272         if (p)
1273         {
1274                 SysLog(NID_APP, "Condition[%s]", p);
1275         }
1276
1277         p = appsvc_get_operation(b);
1278         if (p)
1279         {
1280                 SysLog(NID_APP, "operation[%s]", p);
1281         }
1282
1283         p = appsvc_get_uri(b);
1284         if (p)
1285         {
1286                 SysLog(NID_APP, "uri[%s]", p);
1287         }
1288
1289         p = appsvc_get_mime(b);
1290         if (p)
1291         {
1292                 SysLog(NID_APP, "mime[%s]", p);
1293         }
1294
1295         p = appsvc_get_category(b);
1296         if (p)
1297         {
1298                 SysLog(NID_APP, "Category[%s]", p);
1299         }
1300
1301         bundle_foreach(b, BundlePrintIterFnCb, NULL);
1302
1303         int len = 0;
1304         const char** pa = appsvc_get_data_array(b, OSP_K_ARG, &len);
1305         if (pa)
1306         {
1307                 for (int i = 0; i < len; i++)
1308                 {
1309                         if (pa[i])
1310                         {
1311                                 SysLog(NID_APP, "%dth arg [%s]", i, pa[i]);
1312                         }
1313                 }
1314         }
1315 }
1316
1317 } } // Tizen::App