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