fix memory leak
[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::SetWaitingStatus(bool status)
237 {
238         __isWaitingResult = status;
239 }
240
241 bool
242 _AppContext::GetWaitingStatus(void) const
243 {
244         return __isWaitingResult;
245 }
246
247 result
248 _AppContext::SendRequestToApp(const AppId& providerAppId, const String& operation, HashMap* pArgs)
249 {
250         result r = E_SUCCESS;
251
252         if (GetConnectionState() == CONNECTION_STATE_NONE || GetConnectionState() == CONNECTION_STATE_DISCONNECTED)
253         {
254                 SysLog(NID_SHELL, "The application is not running.");
255                 r = _AppWidgetRequestHelper::SendAppControlRequest(providerAppId, operation, pArgs);
256                 pArgs->RemoveAll(true);
257                 delete pArgs;
258
259                 SysTryReturn(NID_SHELL, !IsFailed(r), r, r, "[%s] Failed to SendRequestToApp", GetErrorMessage(r));
260
261                 SetWaitingStatus(true);
262                 SetConnectionState(CONNECTION_STATE_CONNECTING);
263         }
264         else
265         {
266                 if (GetConnectionState() == CONNECTION_STATE_CONNECTING || GetWaitingStatus() == true)
267                 {
268                         SysLog(NID_SHELL, "The application is running but IPC is not connected yet. Queueing the request (%ls).", operation.GetPointer() );
269                         __pPendingEventList->Add(new (nothrow) PendingEvent(operation, pArgs));
270                 }
271                 else
272                 {
273                         SysLog(NID_SHELL, "The application is running and IPC is connected.");
274                         r  = _AppWidgetRequestHelper::SendIpcRequest(GetClientId(), operation, pArgs);
275                         pArgs->RemoveAll(true);
276                         delete pArgs;
277                         SysTryReturn(NID_SHELL, !IsFailed(r), r, r, "[%s] Failed to SendRequestToApp", GetErrorMessage(r));
278
279                         SetWaitingStatus(true);
280                 }
281         }
282
283         return E_SUCCESS;
284 }
285
286 result
287 _AppContext::SendPendingEvent(void)
288 {
289         SetWaitingStatus(false);
290         TryReturn(__pPendingEventList->GetCount() > 0, E_DATA_NOT_FOUND, "No pending event.");
291
292         PendingEvent* pEvent = null;
293         __pPendingEventList->GetAt(0, pEvent);
294         __pPendingEventList->RemoveAt(0);
295         SysLog(NID_SHELL, "(%d) Remains in __pPendingEventList.", __pPendingEventList->GetCount());
296
297         result r = _AppWidgetRequestHelper::SendIpcRequest(GetClientId(), pEvent->operation, pEvent->pArgs);
298         delete pEvent;
299         SysTryReturnResult(NID_SHELL, !IsFailed(r), E_SYSTEM, "SendIpcRequest failed.");
300
301         return E_SUCCESS;
302 }
303
304 result
305 _AppContext::RequestUpdateInstance(const Tizen::Base::String& instanceId, const Tizen::Base::String& argument)
306 {
307         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
308         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
309
310         return pAppWidgetContext->OnUpdateAsync(this, argument);
311 }
312
313 result
314 _AppContext::AcquireRemoteBuffer(const Tizen::Base::String& instanceId, int width, int height, int& bufferId)
315 {
316         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
317         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
318
319         bufferId = pAppWidgetContext->AcquireRemoteBuffer(width, height);
320
321         return E_SUCCESS;
322 }
323
324 result
325 _AppContext::AcquireRemoteBufferForPD(const Tizen::Base::String& instanceId, int width, int height, int& bufferId)
326 {
327         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
328         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
329
330         bufferId = pAppWidgetContext->AcquireRemoteBufferForPD(width, height);
331
332         return E_SUCCESS;
333 }
334
335 result
336 _AppContext::SyncRemoteBuffer(const Tizen::Base::String& instanceId, int width, int height)
337 {
338         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
339         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
340
341         return pAppWidgetContext->SyncRemoteBuffer(width, height);
342 }
343
344 result
345 _AppContext::SyncRemoteBufferForPD(const Tizen::Base::String& instanceId)
346 {
347         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
348         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
349
350         return pAppWidgetContext->SyncRemoteBufferForPD();
351 }
352
353 result
354 _AppContext::SendAccessStatus(const Tizen::Base::String& instanceId, int accessStatus)
355 {
356         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
357         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
358
359         return pAppWidgetContext->SendAccessStatus(accessStatus);
360 }
361
362 _AppWidgetContext*
363 _AppContext::FindAppWidget(const String& instanceId) const
364 {
365         _AppWidgetContext* pAppWidgetContext = null;
366
367         if (instanceId == INVALID_INSTANCE)
368         {
369                 pAppWidgetContext = FindInvalidAppWidget();
370         }
371         else
372         {
373                 result r = __appWidgetContextList.GetValue(instanceId, pAppWidgetContext);
374                 SysTryReturn(NID_SHELL, !IsFailed(r), null, E_OBJ_NOT_FOUND, "instanceId(%ls) is not found", instanceId.GetPointer() );
375         }
376         return pAppWidgetContext;
377 }
378
379 _AppWidgetContext*
380 _AppContext::FindInvalidAppWidget(void) const
381 {
382         SysTryReturn(NID_SHELL, GetConnectionState() == CONNECTION_STATE_NONE, null, E_INVALID_STATE, "[E_INVALID_STATE] connectionState(%d)", GetConnectionState());
383
384         _AppWidgetContext* pAppWidgetContext = null;
385         unique_ptr< IMapEnumeratorT<String, _AppWidgetContext*> > pAppWidgetContextEnum(__appWidgetContextList.GetMapEnumeratorN());
386         SysTryReturn(NID_SHELL, pAppWidgetContextEnum, null, E_SYSTEM, "");
387
388         while (pAppWidgetContextEnum->MoveNext() == E_SUCCESS)
389         {
390                 pAppWidgetContextEnum->GetValue(pAppWidgetContext);
391                 if (pAppWidgetContext)
392                 {
393                         //TODO: check whether this app context has only one instance of _AppWidgetContext
394                         return pAppWidgetContext;
395                 }
396         }
397         return null;
398 }
399
400 int
401 _AppContext::GetProviderCount(void) const
402 {
403         return __appWidgetContextList.GetCount();
404 }
405
406 result
407 _AppContext::RequestUpdate(const Tizen::Base::String& providerName, const Tizen::Base::String& argument)
408 {
409         SysLog(NID_SHELL, "Enter.");
410         bool found = false;
411
412         unique_ptr< IMapEnumeratorT<String, _AppWidgetContext*> > pAppWidgetContextEnum(__appWidgetContextList.GetMapEnumeratorN());
413         SysTryReturnResult(NID_SHELL, pAppWidgetContextEnum, E_SYSTEM, "Failed to invoke __appWidgetContextList.GetMapEnumeratorN()");
414
415         while (pAppWidgetContextEnum->MoveNext() == E_SUCCESS)
416         {
417                 _AppWidgetContext* pAppWidgetContext = null;
418                 pAppWidgetContextEnum->GetValue(pAppWidgetContext);
419
420                 if (pAppWidgetContext->GetProviderName() == providerName)
421                 {
422                         pAppWidgetContext->OnUpdateAsync(this, argument);
423                         found = true;
424                 }
425         }
426
427         SysLog(NID_SHELL, "Exit.");
428         return (found) ? E_SUCCESS : E_OBJ_NOT_FOUND;
429 }
430
431 result
432 _AppContext::RequestUpdateAllInactiveted(void)
433 {
434         SysLog(NID_SHELL, "Exit.");
435         unique_ptr< IMapEnumeratorT<String, _AppWidgetContext*> > pAppWidgetContextEnum(__appWidgetContextList.GetMapEnumeratorN());
436         SysTryReturnResult(NID_SHELL, pAppWidgetContextEnum, E_SYSTEM, "Failed to invoke __appWidgetContextList.GetMapEnumeratorN()");
437
438         while (pAppWidgetContextEnum->MoveNext() == E_SUCCESS)
439         {
440                 _AppWidgetContext* pAppWidgetContext = null;
441                 pAppWidgetContextEnum->GetValue(pAppWidgetContext);
442
443                 if (pAppWidgetContext->IsActive() == false)
444                 {
445                         pAppWidgetContext->OnUpdateAsync(this, L"");
446                 }
447         }
448
449         SysLog(NID_SHELL, "Exit.");
450         return E_SUCCESS;
451 }
452
453 result
454 _AppContext::OnAppWidgetBackground(const Tizen::Base::String& instanceId)
455 {
456         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
457         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
458
459         pAppWidgetContext->OnBackground();
460
461         return E_SUCCESS;
462 }
463
464 result
465 _AppContext::OnAppWidgetBackgroundAll(void)
466 {
467         unique_ptr< IMapEnumeratorT<String, _AppWidgetContext*> > pAppWidgetContextEnum(__appWidgetContextList.GetMapEnumeratorN());
468         SysTryReturnResult(NID_SHELL, pAppWidgetContextEnum, E_SYSTEM, "Failed to invoke GetMapEnumeratorN()");
469
470         while (pAppWidgetContextEnum->MoveNext() == E_SUCCESS)
471         {
472                 _AppWidgetContext* pAppWidgetContext = null;
473                 pAppWidgetContextEnum->GetValue(pAppWidgetContext);
474                 if (pAppWidgetContext)
475                 {
476                         pAppWidgetContext->OnBackground();
477                 }
478         }
479
480         return E_SUCCESS;
481 }
482
483 result
484 _AppContext::OnAppWidgetForeground(const Tizen::Base::String& instanceId)
485 {
486         _AppWidgetContext* pAppWidgetContext = FindAppWidget(instanceId);
487         SysTryReturnResult(NID_SHELL, pAppWidgetContext, E_OBJ_NOT_FOUND, "Failed to find _AppWidgetContext.");
488
489         pAppWidgetContext->OnForeground();
490
491         return E_SUCCESS;
492 }
493
494 result
495 _AppContext::OnAppWidgetForegroundAll(void)
496 {
497         unique_ptr< IMapEnumeratorT<String, _AppWidgetContext*> > pAppWidgetContextEnum(__appWidgetContextList.GetMapEnumeratorN());
498         SysTryReturnResult(NID_SHELL, pAppWidgetContextEnum, E_SYSTEM, "Failed to invoke GetMapEnumeratorN()");
499
500         while (pAppWidgetContextEnum->MoveNext() == E_SUCCESS)
501         {
502                 _AppWidgetContext* pAppWidgetContext = null;
503                 pAppWidgetContextEnum->GetValue(pAppWidgetContext);
504                 if (pAppWidgetContext)
505                 {
506                         pAppWidgetContext->OnForeground();
507                 }
508         }
509
510         return E_SUCCESS;
511 }
512
513 void
514 _AppContext::HandleUserEvent(Tizen::Base::Collection::IList* pArgs)
515 {
516         _AppWidgetContext* pAppWidgetContext = dynamic_cast<_AppWidgetContext*>( pArgs->GetAt(1) );
517         SysTryReturnVoidResult(NID_SHELL, pAppWidgetContext != null, E_INVALID_STATE, "_AppWidget is null!.");
518
519         String* pArgument = dynamic_cast<String*>( pArgs->GetAt(2) );
520         SysTryReturnVoidResult(NID_SHELL, pArgument != null, E_INVALID_STATE, "pArgument is null!.");
521
522         pAppWidgetContext->OnUpdate(*pArgument);
523 }
524
525 }}}  // Tizen::Shell::App