add exception handling code for abnormal app termination
[platform/framework/native/appwidget-service.git] / src / FShell_AppContext.cpp
1 //
2 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
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        FShell_AppWidgetContext.cpp
19  * @brief       This is the implementation for the _AppWidgetContext class.
20  */
21
22 #include <provider.h>
23 #include <unique_ptr.h>
24 #include <FBase.h>
25 #include <FBaseSysLog.h>
26 #include <FAppApp.h>
27 #include <FApp_AppManagerImpl.h>
28 #include "FShell_AppWidgetContext.h"
29 #include "FShell_AppWidgetContextHelper.h"
30 #include "FShell_TemplateUtil.h"
31
32 namespace Tizen { namespace Shell  { namespace App
33 {
34
35 using namespace std;
36 using namespace Tizen::App;
37 using namespace Tizen::Base;
38 using namespace Tizen::Base::Collection;
39 using namespace Tizen::System;
40
41 static const wchar_t INVALID_INSTANCE[] = L"file://invalid instance id";
42
43 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
44 // _AppContext class
45 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
46 _AppContext::_AppContext(const AppId& appId)
47         :__appId(appId)
48         ,__isWaitingResult(false)
49         ,__ipcClientId(0)
50         ,__connectionState(CONNECTION_STATE_NONE)
51         ,__pPendingEventList(null)
52 {
53
54         __pPendingEventList = new (nothrow) ArrayListT<PendingEvent*>();
55         SysTryReturnVoidResult(NID_SHELL, __pPendingEventList, E_OUT_OF_MEMORY, "");
56
57         result r = __pPendingEventList->Construct();
58         SysTryReturnVoidResult(NID_SHELL, !IsFailed(r), E_SYSTEM, "Failed to execute Construct.");
59
60         r = __appWidgetContextList.Construct();
61         SysTryReturnVoidResult(NID_SHELL, !IsFailed(r), E_SYSTEM, "Failed to execute Construct.");
62 }
63
64 _AppContext::~_AppContext(void)
65 {
66         SysLog(NID_SHELL, "Enter");
67
68         if (__pPendingEventList)
69         {
70                 for (int i = 0; i < __pPendingEventList->GetCount(); i++)
71                 {
72                         PendingEvent* pEvent = null;
73                         __pPendingEventList->GetAt(i, pEvent);
74                         delete pEvent;
75                 }
76                 __pPendingEventList->RemoveAll();
77                 delete __pPendingEventList;
78         }
79
80         IMapEnumeratorT<String, _AppWidgetContext*>* pMapEnum = __appWidgetContextList.GetMapEnumeratorN();
81         if (pMapEnum != null)
82         {
83                 while (pMapEnum->MoveNext() == E_SUCCESS)
84                 {
85                         _AppWidgetContext* pAppWidgetContext = null;
86                         pMapEnum->GetValue(pAppWidgetContext);
87                         delete pAppWidgetContext;
88                 }
89
90                 delete pMapEnum;
91         }
92
93         SysLog(NID_SHELL, "Exit");
94 }
95
96 result
97 _AppContext::AddAppWidget(const Tizen::Base::String& userInfo, const Tizen::Base::String& providerId, const Tizen::Base::String& instanceId, int width, int height, int period, int priority)
98 {
99         _AppWidgetContext* pAppWidgetContext = null;
100         bool containsKey = false;
101
102         __appWidgetContextList.ContainsKey(instanceId, containsKey);
103         if (containsKey == true)
104         {
105                 SysSecureLog(NID_SHELL, "The appwidget(%ls) is already exist, so requesting to update.", instanceId.GetPointer() );
106
107                 __appWidgetContextList.GetValue(instanceId, pAppWidgetContext);
108                 pAppWidgetContext->OnUpdate(L"");
109         }
110         else
111         {
112                 pAppWidgetContext = new (std::nothrow)_AppWidgetContext(this, instanceId, providerId, width, height, userInfo, period, priority);
113                 SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OUT_OF_MEMORY, "");
114
115                 __appWidgetContextList.Add(instanceId, pAppWidgetContext);
116                 pAppWidgetContext->OnAdded();
117
118                 SysSecureLog(NID_SHELL, "%ls, %ls, count(%d)", pAppWidgetContext->GetProviderId().GetPointer(), pAppWidgetContext->GetInstanceId().GetPointer(), __appWidgetContextList.GetCount());
119         }
120         return E_SUCCESS;
121 }
122
123 result
124 _AppContext::UpdateAppWidget(const Tizen::Base::String& instanceId)
125 {
126         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
127         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
128
129         pAppWidgetContext->OnUpdate(L"");
130
131         return E_SUCCESS;
132 }
133
134 result
135 _AppContext::ResizeAppWidget(const Tizen::Base::String& instanceId, int width, int height)
136 {
137         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
138         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
139
140         pAppWidgetContext->OnResize(width, height);
141
142         return E_SUCCESS;
143 }
144
145 result
146 _AppContext::CreateAppWidgetPopup(const Tizen::Base::String& instanceId, double x, double y, int width, int height)
147 {
148         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
149         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
150
151         pAppWidgetContext->OnPopupCreated(x, y, width, height);
152
153         return E_SUCCESS;
154 }
155
156 result
157 _AppContext::DestroyAppWidget(const Tizen::Base::String& instanceId, bool isTriggeredByViewer)
158 {
159         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
160         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
161
162         __appWidgetContextList.Remove(instanceId);
163
164         result r = pAppWidgetContext->OnRemoved(isTriggeredByViewer);
165         SysTryLog(NID_SHELL, !IsFailed(r), "Failed to execute OnRemoved.");
166
167         delete pAppWidgetContext;
168
169     SysLog(NID_SHELL, "AppWidget(%ls) is removed. remain count(%d)", instanceId.GetPointer(), __appWidgetContextList.GetCount());
170         return E_SUCCESS;
171 }
172
173 result
174 _AppContext::DestroyAppWidgetPopup(const Tizen::Base::String& instanceId)
175 {
176         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
177         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
178
179         pAppWidgetContext->OnPopupDestoyed();
180
181         return E_SUCCESS;
182 }
183
184 _ConnectionState
185 _AppContext::GetConnectionState(void) const
186 {
187         return __connectionState;
188 }
189
190 void
191 _AppContext::SetConnectionState(_ConnectionState state)
192 {
193         __connectionState = state;
194 }
195
196 Tizen::App::AppId
197 _AppContext::GetAppId(void) const
198 {
199         return __appId;
200 }
201
202 int
203 _AppContext::GetClientId(void) const
204 {
205         return __ipcClientId;
206 }
207
208 void
209 _AppContext::OnIpcConnected(int clientId)
210 {
211         __ipcClientId = clientId;
212         SetConnectionState(CONNECTION_STATE_CONNECTED);
213 }
214
215 void
216 _AppContext::OnIpcDisconnected(void)
217 {
218         __ipcClientId = -1;
219         SetConnectionState(CONNECTION_STATE_DISCONNECTED);
220
221         unique_ptr< IMapEnumeratorT<String, _AppWidgetContext*> > pAppWidgetContextEnum(__appWidgetContextList.GetMapEnumeratorN());
222         SysTryReturnVoidResult(NID_SHELL, pAppWidgetContextEnum, E_SYSTEM, "");
223
224         _AppWidgetContext* pAppWidgetContext = null;
225         while (pAppWidgetContextEnum->MoveNext() == E_SUCCESS)
226         {
227                 pAppWidgetContextEnum->GetValue(pAppWidgetContext);
228                 if (pAppWidgetContext)
229                 {
230                         pAppWidgetContext->OnDisconnected();
231                 }
232         }
233 }
234
235 void
236 _AppContext::OnApplicationTerminated(void)
237 {
238         if (GetWaitingStatus() == true )
239         {
240                 SysLog(NID_SHELL, "The application (%ls) is terminated without response.", __appId.GetPointer() );
241                 SetWaitingStatus(false);
242
243                 if (GetConnectionState() == CONNECTION_STATE_CONNECTING)
244                 {
245                         SysLog(NID_SHELL, "The application (%ls) is terminated before IPC connected, resetting connection state.", __appId.GetPointer() );
246                         SetConnectionState(CONNECTION_STATE_DISCONNECTED);
247                 }
248         }
249 }
250
251 void
252 _AppContext::SetWaitingStatus(bool status)
253 {
254         __isWaitingResult = status;
255 }
256
257 bool
258 _AppContext::GetWaitingStatus(void) const
259 {
260         return __isWaitingResult;
261 }
262
263 result
264 _AppContext::SendRequestToApp(const AppId& providerAppId, const String& operation, HashMap* pArgs)
265 {
266         result r = E_SUCCESS;
267
268         if (GetConnectionState() == CONNECTION_STATE_NONE || GetConnectionState() == CONNECTION_STATE_DISCONNECTED)
269         {
270                 SysLog(NID_SHELL, "The application is not running.");
271                 r = _AppWidgetRequestHelper::SendAppControlRequest(providerAppId, operation, pArgs);
272                 pArgs->RemoveAll(true);
273                 delete pArgs;
274
275                 SysTryReturn(NID_SHELL, !IsFailed(r), r, r, "[%s] Failed to SendRequestToApp", GetErrorMessage(r));
276
277                 SetWaitingStatus(true);
278                 SetConnectionState(CONNECTION_STATE_CONNECTING);
279         }
280         else
281         {
282                 if (GetConnectionState() == CONNECTION_STATE_CONNECTING || GetWaitingStatus() == true)
283                 {
284                         SysLog(NID_SHELL, "The application is running but IPC is not connected yet. Queueing the request (%ls).", operation.GetPointer() );
285                         __pPendingEventList->Add(new (nothrow) PendingEvent(operation, pArgs));
286                 }
287                 else
288                 {
289                         SysLog(NID_SHELL, "The application is running and IPC is connected.");
290                         r  = _AppWidgetRequestHelper::SendIpcRequest(GetClientId(), operation, pArgs);
291                         pArgs->RemoveAll(true);
292                         delete pArgs;
293                         SysTryReturn(NID_SHELL, !IsFailed(r), r, r, "[%s] Failed to SendRequestToApp", GetErrorMessage(r));
294
295                         SetWaitingStatus(true);
296                 }
297         }
298
299         return E_SUCCESS;
300 }
301
302 result
303 _AppContext::SendPendingEvent(void)
304 {
305         SetWaitingStatus(false);
306         TryReturn(__pPendingEventList->GetCount() > 0, E_DATA_NOT_FOUND, "No pending event.");
307
308         PendingEvent* pEvent = null;
309         __pPendingEventList->GetAt(0, pEvent);
310         __pPendingEventList->RemoveAt(0);
311         SysLog(NID_SHELL, "(%d) Remains in __pPendingEventList.", __pPendingEventList->GetCount());
312
313         result r = _AppWidgetRequestHelper::SendIpcRequest(GetClientId(), pEvent->operation, pEvent->pArgs);
314         delete pEvent;
315         SysTryReturnResult(NID_SHELL, !IsFailed(r), E_SYSTEM, "SendIpcRequest failed.");
316
317         return E_SUCCESS;
318 }
319
320 result
321 _AppContext::RequestUpdateInstance(const Tizen::Base::String& instanceId, const Tizen::Base::String& argument)
322 {
323         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
324         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
325
326         return pAppWidgetContext->OnUpdateAsync(this, argument);
327 }
328
329 result
330 _AppContext::AcquireRemoteBuffer(const Tizen::Base::String& instanceId, int width, int height, int& bufferId)
331 {
332         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
333         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
334
335         bufferId = pAppWidgetContext->AcquireRemoteBuffer(width, height);
336
337         return E_SUCCESS;
338 }
339
340 result
341 _AppContext::AcquireRemoteBufferForPD(const Tizen::Base::String& instanceId, int width, int height, int& bufferId)
342 {
343         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
344         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
345
346         bufferId = pAppWidgetContext->AcquireRemoteBufferForPD(width, height);
347
348         return E_SUCCESS;
349 }
350
351 result
352 _AppContext::SyncRemoteBuffer(const Tizen::Base::String& instanceId, int width, int height)
353 {
354         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
355         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
356
357         return pAppWidgetContext->SyncRemoteBuffer(width, height);
358 }
359
360 result
361 _AppContext::SyncRemoteBufferForPD(const Tizen::Base::String& instanceId)
362 {
363         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
364         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
365
366         return pAppWidgetContext->SyncRemoteBufferForPD();
367 }
368
369 result
370 _AppContext::SendAccessStatus(const Tizen::Base::String& instanceId, int accessStatus)
371 {
372         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
373         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
374
375         return pAppWidgetContext->SendAccessStatus(accessStatus);
376 }
377
378 _AppWidgetContext*
379 _AppContext::FindAppWidget(const String& instanceId) const
380 {
381         _AppWidgetContext* pAppWidgetContext = null;
382
383         if (instanceId == INVALID_INSTANCE)
384         {
385                 pAppWidgetContext = FindInvalidAppWidget();
386         }
387         else
388         {
389                 result r = __appWidgetContextList.GetValue(instanceId, pAppWidgetContext);
390                 SysTryReturn(NID_SHELL, !IsFailed(r), null, E_OBJ_NOT_FOUND, "instanceId(%ls) is not found", instanceId.GetPointer() );
391         }
392         return pAppWidgetContext;
393 }
394
395 _AppWidgetContext*
396 _AppContext::FindInvalidAppWidget(void) const
397 {
398         SysTryReturn(NID_SHELL, GetConnectionState() == CONNECTION_STATE_NONE, null, E_INVALID_STATE, "[E_INVALID_STATE] connectionState(%d)", GetConnectionState());
399
400         _AppWidgetContext* pAppWidgetContext = null;
401         unique_ptr< IMapEnumeratorT<String, _AppWidgetContext*> > pAppWidgetContextEnum(__appWidgetContextList.GetMapEnumeratorN());
402         SysTryReturn(NID_SHELL, pAppWidgetContextEnum, null, E_SYSTEM, "");
403
404         while (pAppWidgetContextEnum->MoveNext() == E_SUCCESS)
405         {
406                 pAppWidgetContextEnum->GetValue(pAppWidgetContext);
407                 if (pAppWidgetContext)
408                 {
409                         //TODO: check whether this app context has only one instance of _AppWidgetContext
410                         return pAppWidgetContext;
411                 }
412         }
413         return null;
414 }
415
416 int
417 _AppContext::GetProviderCount(void) const
418 {
419         return __appWidgetContextList.GetCount();
420 }
421
422 result
423 _AppContext::RequestUpdate(const Tizen::Base::String& providerName, const Tizen::Base::String& argument)
424 {
425         SysLog(NID_SHELL, "Enter.");
426         bool found = false;
427
428         unique_ptr< IMapEnumeratorT<String, _AppWidgetContext*> > pAppWidgetContextEnum(__appWidgetContextList.GetMapEnumeratorN());
429         SysTryReturnResult(NID_SHELL, pAppWidgetContextEnum, E_SYSTEM, "Failed to invoke __appWidgetContextList.GetMapEnumeratorN()");
430
431         while (pAppWidgetContextEnum->MoveNext() == E_SUCCESS)
432         {
433                 _AppWidgetContext* pAppWidgetContext = null;
434                 pAppWidgetContextEnum->GetValue(pAppWidgetContext);
435
436                 if (pAppWidgetContext->GetProviderName() == providerName)
437                 {
438                         pAppWidgetContext->OnUpdateAsync(this, argument);
439                         found = true;
440                 }
441         }
442
443         SysLog(NID_SHELL, "Exit.");
444         return (found) ? E_SUCCESS : E_OBJ_NOT_FOUND;
445 }
446
447 result
448 _AppContext::RequestUpdateAllInactiveted(void)
449 {
450         SysLog(NID_SHELL, "Exit.");
451         unique_ptr< IMapEnumeratorT<String, _AppWidgetContext*> > pAppWidgetContextEnum(__appWidgetContextList.GetMapEnumeratorN());
452         SysTryReturnResult(NID_SHELL, pAppWidgetContextEnum, E_SYSTEM, "Failed to invoke __appWidgetContextList.GetMapEnumeratorN()");
453
454         while (pAppWidgetContextEnum->MoveNext() == E_SUCCESS)
455         {
456                 _AppWidgetContext* pAppWidgetContext = null;
457                 pAppWidgetContextEnum->GetValue(pAppWidgetContext);
458
459                 if (pAppWidgetContext->IsActive() == false)
460                 {
461                         pAppWidgetContext->OnUpdateAsync(this, L"");
462                 }
463         }
464
465         SysLog(NID_SHELL, "Exit.");
466         return E_SUCCESS;
467 }
468
469 result
470 _AppContext::OnAppWidgetBackground(const Tizen::Base::String& instanceId)
471 {
472         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
473         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
474
475         pAppWidgetContext->OnBackground();
476
477         return E_SUCCESS;
478 }
479
480 result
481 _AppContext::OnAppWidgetBackgroundAll(void)
482 {
483         unique_ptr< IMapEnumeratorT<String, _AppWidgetContext*> > pAppWidgetContextEnum(__appWidgetContextList.GetMapEnumeratorN());
484         SysTryReturnResult(NID_SHELL, pAppWidgetContextEnum, E_SYSTEM, "Failed to invoke GetMapEnumeratorN()");
485
486         while (pAppWidgetContextEnum->MoveNext() == E_SUCCESS)
487         {
488                 _AppWidgetContext* pAppWidgetContext = null;
489                 pAppWidgetContextEnum->GetValue(pAppWidgetContext);
490                 if (pAppWidgetContext)
491                 {
492                         pAppWidgetContext->OnBackground();
493                 }
494         }
495
496         return E_SUCCESS;
497 }
498
499 result
500 _AppContext::OnAppWidgetForeground(const Tizen::Base::String& instanceId)
501 {
502         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
503         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
504
505         pAppWidgetContext->OnForeground();
506
507         return E_SUCCESS;
508 }
509
510 result
511 _AppContext::OnAppWidgetForegroundAll(void)
512 {
513         unique_ptr< IMapEnumeratorT<String, _AppWidgetContext*> > pAppWidgetContextEnum(__appWidgetContextList.GetMapEnumeratorN());
514         SysTryReturnResult(NID_SHELL, pAppWidgetContextEnum, E_SYSTEM, "Failed to invoke GetMapEnumeratorN()");
515
516         while (pAppWidgetContextEnum->MoveNext() == E_SUCCESS)
517         {
518                 _AppWidgetContext* pAppWidgetContext = null;
519                 pAppWidgetContextEnum->GetValue(pAppWidgetContext);
520                 if (pAppWidgetContext)
521                 {
522                         pAppWidgetContext->OnForeground();
523                 }
524         }
525
526         return E_SUCCESS;
527 }
528
529 void
530 _AppContext::HandleUserEvent(Tizen::Base::Collection::IList* pArgs)
531 {
532         _AppWidgetContext* pAppWidgetContext = dynamic_cast<_AppWidgetContext*>( pArgs->GetAt(1) );
533         SysTryReturnVoidResult(NID_SHELL, pAppWidgetContext != null, E_INVALID_STATE, "_AppWidget is null!.");
534
535         String* pArgument = dynamic_cast<String*>( pArgs->GetAt(2) );
536         SysTryReturnVoidResult(NID_SHELL, pArgument != null, E_INVALID_STATE, "pArgument is null!.");
537
538         pAppWidgetContext->OnUpdate(*pArgument);
539 }
540
541 }}}  // Tizen::Shell::App