add exception handling code for OOM case
[platform/framework/native/appwidget-service.git] / src / FShell_AppWidgetContext.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
25 #include <FBase.h>
26 #include <FBaseSysLog.h>
27 #include <FSysSystemTime.h>
28 #include <FAppApp.h>
29 #include <FBase_StringConverter.h>
30 #include <FApp_AppManagerImpl.h>
31 #include "FShell_AppWidgetManagerImpl.h"
32 #include "FShell_AppWidgetManagerService.h"
33 #include "FShell_AppWidgetPopupContext.h"
34 #include "FShell_AppWidgetContext.h"
35 #include "FShell_AppWidgetContextHelper.h"
36 #include "FShell_AppWidgetRemoteBuffer.h"
37
38 namespace Tizen { namespace Shell  { namespace App
39 {
40
41 using namespace std;
42 using namespace Tizen::App;
43 using namespace Tizen::Base;
44 using namespace Tizen::Base::Collection;
45 using namespace Tizen::System;
46
47 const wchar_t ARG_KEY_INSTANCE_ID[] = L"_InstanceId";
48 const wchar_t ARG_KEY_PROVIDER_NAME[] = L"_ProviderName";
49 const wchar_t ARG_KEY_USER_INFO[] = L"_UserInfo";
50 const wchar_t ARG_KEY_X[] = L"_X";
51 const wchar_t ARG_KEY_Y[] = L"_Y";
52 const wchar_t ARG_KEY_WIDTH[] = L"_Width";
53 const wchar_t ARG_KEY_HEIGHT[] = L"_Height";
54 const wchar_t ARG_KEY_POPUP_WIDTH[] = L"_PopupWidth";
55 const wchar_t ARG_KEY_POPUP_HEIGHT[] = L"_PopupHeight";
56 const wchar_t ARG_KEY_ARGUMENT[] = L"_Argument";
57 const wchar_t ARG_KEY_EVENT_TYPE[] = L"_EventType";
58 const wchar_t ARG_KEY_TIME_STAMP[] = L"_TimeStamp";
59
60 const wchar_t APPWIDGET_ON_ADD[] = L"http://tizen.org/appcontrol/appwidget/add";
61 const wchar_t APPWIDGET_ON_REMOVE[] = L"http://tizen.org/appcontrol/appwidget/remove";
62 const wchar_t APPWIDGET_ON_UPDATE[] = L"http://tizen.org/appcontrol/appwidget/update";
63 const wchar_t APPWIDGET_ON_RESIZE[] = L"http://tizen.org/appcontrol/appwidget/resize";
64 const wchar_t APPWIDGET_ON_TOUCH[] = L"http://tizen.org/appcontrol/appwidget/touch";
65
66 const int UPDATE_PERIOD_MSEC_MIN = 1800000;     // 30min
67
68
69 _AppWidgetContext::_AppWidgetContext(_AppContext* pAppContext, const String& instanceId, const String& providerId, int width, int height, const Tizen::Base::String& userInfo, int period, int priority)
70         :__instanceId(instanceId)
71         ,__providerId(providerId)
72         ,__appId(_AppWidgetHelper::ExtractAppId(providerId))
73         ,__providerName(_AppWidgetHelper::ExtractProviderName(providerId))
74         ,__userInfo(userInfo)
75         ,__width(width)
76         ,__height(height)
77         ,__priority(priority)
78         ,__updateMillis( (period > UPDATE_PERIOD_MSEC_MIN) ? period : UPDATE_PERIOD_MSEC_MIN )
79         ,__ipcClientId(-1)
80         ,__isForeground(true)
81         ,__isRemoteBufferProxyCreated(false)
82         ,__lastUpdatedTime(0)
83         ,__hasPendingRequest(false)
84         ,__pAppContext(pAppContext)
85         ,__pAppWidgetPopup(null)
86         ,__pAppWidgetRemoteBuffer(null)
87         ,__pPendingTouchEventList(null)
88 {
89         SysSecureLog(NID_SHELL, "appId(%ls), providerId(%ls), instanceId(%ls), width(%d), height(%d), priority(%d), period(%d)", __appId.GetPointer(), __providerId.GetPointer(), __instanceId.GetPointer(), __width, __height, __priority, __updateMillis);
90
91         // for updating period
92         if (__updateMillis > 0)
93         {
94                 SystemTime::GetTicks(this->__lastUpdatedTime);
95
96                 result r = __updateTimer.Construct(*this);
97                 SysTryReturnVoidResult(NID_SHELL, !IsFailed(r), E_SYSTEM, "");
98
99                 r = __updateTimer.StartAsRepeatable(__updateMillis);
100                 SysTryReturnVoidResult(NID_SHELL, !IsFailed(r), E_SYSTEM, "");
101         }
102
103         __pPendingTouchEventList = new (nothrow) ArrayListT<PendingTouchEvent*>();
104         SysTryReturnVoidResult(NID_SHELL, __pPendingTouchEventList, E_OUT_OF_MEMORY, "");
105         __pPendingTouchEventList->Construct();
106
107         __pAppWidgetRemoteBuffer = new (nothrow) _AppWidgetRemoteBuffer(providerId, instanceId, TYPE_LB, this);
108         SysTryReturnVoidResult(NID_SHELL, __pAppWidgetRemoteBuffer, E_OUT_OF_MEMORY, "");
109 }
110
111 _AppWidgetContext::~_AppWidgetContext(void)
112 {
113         SysSecureLog(NID_SHELL, "appId(%ls), instanceId(%ls), width(%d), height(%d), priority(%d)", GetProviderId().GetPointer(), GetInstanceId().GetPointer(), GetWidth(), GetHeight(), GetPriority());
114
115         __updateTimer.Cancel();
116
117         if (__pAppWidgetPopup)
118         {
119                 SysLog(NID_SHELL, "Destroying dangling AppWidgetPopup instance..");
120                 delete __pAppWidgetPopup;
121         }
122
123         if (__pPendingTouchEventList)
124         {
125                 for (int i = 0; i < __pPendingTouchEventList->GetCount(); i++)
126                 {
127                         PendingTouchEvent* pTouchEvent = null;
128                         __pPendingTouchEventList->GetAt(i, pTouchEvent);
129                         delete pTouchEvent;
130                 }
131                 __pPendingTouchEventList->RemoveAll();
132                 delete __pPendingTouchEventList;
133         }
134
135         if (__pAppWidgetRemoteBuffer)
136         {
137                 delete __pAppWidgetRemoteBuffer;
138         }
139 }
140
141 _AppContext*
142 _AppWidgetContext::GetAppContext(void) const
143 {
144         return __pAppContext;
145 }
146
147 _AppWidgetPopupContext*
148 _AppWidgetContext::GetAppWidgetPopup(void) const
149 {
150         return __pAppWidgetPopup;
151 }
152
153 void
154 _AppWidgetContext::OnAdded(void)
155 {
156         SendAddRequest(GetWidth(), GetHeight());
157 }
158
159 result
160 _AppWidgetContext::OnRemoved(bool isTriggeredByViewer)
161 {
162         if (isTriggeredByViewer)
163         {
164                 return SendRemoveRequest();
165         }
166         else
167         {
168                 std::unique_ptr<char[]> providerId(_StringConverter::CopyToCharArrayN(GetProviderId()));
169                 std::unique_ptr<char[]> id(_StringConverter::CopyToCharArrayN(GetInstanceId()));
170
171                 int ret = provider_send_deleted(providerId.get(), id.get());
172                 SysTryReturnResult(NID_SHELL, ret >= 0 , E_SYSTEM, "Failed to execute provider_send_deleted.");
173         }
174         return E_SUCCESS;
175 }
176
177 void
178 _AppWidgetContext::OnUpdate(const String& argument)
179 {
180         SysLog(NID_SHELL, "argument(%ls)", argument.GetPointer());
181         ClearLastResult();
182
183         if (this->IsForeground())
184         {
185                 result r = this->SendUpdateRequest(GetWidth(), GetHeight(), argument);
186                 SysTryLog(NID_SHELL, !IsFailed(r), "Failed to execute SendUpdateRequest.");
187
188                 SystemTime::GetTicks(this->__lastUpdatedTime);
189                 SysLog(NID_SHELL, "The last updated time is %lld.", this->__lastUpdatedTime);
190
191                 __hasPendingRequest = false;
192                 __pendingArgument.Clear();
193         }
194         else
195         {
196                 // Queueing the pointer of background context.
197                 if (!argument.IsEmpty())
198                 {
199                         __pendingArgument = argument;
200                 }
201
202                 __hasPendingRequest = true;
203                 SysLog(NID_SHELL, "Update is requested but the %ls is background.", (this->GetProviderId()).GetPointer());
204         }
205 }
206
207 result
208 _AppWidgetContext::OnUpdateAsync(_AppContext* pAppContext, const String& argument)
209 {
210         ArrayList* pArray = new (std::nothrow) ArrayList();
211         SysTryReturnResult(NID_SHELL, pArray, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]");
212
213         pArray->Construct();
214         pArray->Add(pAppContext);
215         pArray->Add(this);
216         pArray->Add(new String(argument));
217
218         result r = Tizen::App::App::GetInstance()->SendUserEvent(LOCAL_EVENT_REQUEST_UPDATE, pArray);
219         SysTryLog(NID_SHELL, !IsFailed(r), "[%s] Propagated.", GetErrorMessage(r));
220         SysLog(NID_SHELL, "UserEvent(%d) is sent for '%ls.%ls'.", LOCAL_EVENT_REQUEST_UPDATE, GetAppId().GetPointer(), GetProviderName().GetPointer() );
221
222         return E_SUCCESS;
223 }
224
225 void
226 _AppWidgetContext::OnResize(int width, int height)
227 {
228         SysSecureLog(NID_SHELL, "appId(%ls), instanceId(%ls), width(%d->%d), height(%d->%d)", GetProviderId().GetPointer(), GetInstanceId().GetPointer(), GetWidth(), width, GetHeight(), height);
229
230         SetWidth(width);
231         SetHeight(height);
232
233         SendResizeRequest(width, height);
234 }
235
236 void
237 _AppWidgetContext::OnForeground(void)
238 {
239         if (IsForeground())
240         {
241                 SysLog(NID_SHELL, "%ls is already foreground.", (this->GetAppId()).GetPointer());
242                 return;
243         }
244
245         __isForeground = true;
246
247         if (__hasPendingRequest == true)
248         {
249                 SysLog(NID_SHELL, "There is pending request.");
250                 OnUpdateAsync(__pAppContext, __pendingArgument);
251         }
252         else
253         {
254                 if (IsUpdatePeriodExpired() == true)
255                 {
256                         SysLog(NID_SHELL, "The period is expired.");
257                         OnUpdateAsync(__pAppContext, L"");
258                 }
259         }
260 }
261
262 bool
263 _AppWidgetContext::IsUpdatePeriodExpired(void) const
264 {
265         if (this->GetPeriod() <= 0)
266         {
267                 return false;
268         }
269
270         long long currentTicks = 0;
271         SystemTime::GetTicks(currentTicks);
272
273         SysLog(NID_SHELL, "current[%lld] - last updated time[%lld] = [%lld], period[%d]",
274                         currentTicks, this->GetLastUpdatedTime(), currentTicks - this->GetLastUpdatedTime(), this->GetPeriod());
275
276         bool isPeriodExpired = (currentTicks - this->GetLastUpdatedTime()) >= (this->GetPeriod());
277         return isPeriodExpired;
278 }
279
280 void
281 _AppWidgetContext::OnBackground(void)
282 {
283         if (!IsForeground())
284         {
285                 SysLog(NID_SHELL, "%ls is already background.", (this->GetAppId()).GetPointer());
286                 return;
287         }
288
289         SysLog(NID_SHELL, "OnBackground");
290         __isForeground = false;
291 }
292
293 void
294 _AppWidgetContext::OnPopupCreated(double x, double y, int width, int height)
295 {
296         __pAppWidgetPopup = new (nothrow) _AppWidgetPopupContext(this);
297         SysTryReturnVoidResult(NID_SHELL, __pAppWidgetPopup, E_OUT_OF_MEMORY, "");
298
299         __pAppWidgetPopup->OnPopupCreated(x, y, width, height);
300 }
301
302 void
303 _AppWidgetContext::OnPopupDestoyed(void)
304 {
305         SysLog(NID_SHELL, "");
306
307         if (__pAppWidgetPopup)
308         {
309                 delete __pAppWidgetPopup;
310                 __pAppWidgetPopup = null;
311         }
312 }
313
314 result
315 _AppWidgetContext::SendAddRequest(int width, int height) const
316 {
317         std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN());
318
319         return __pAppContext->SendRequestToApp(GetAppId(), APPWIDGET_ON_ADD, pArgs.release());
320 }
321
322 result
323 _AppWidgetContext::SendUpdateRequest(int width, int height, const String& argument) const
324 {
325         std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN());
326
327         pArgs->Add(new (nothrow) String(ARG_KEY_ARGUMENT), new (nothrow) String(argument));
328
329         return __pAppContext->SendRequestToApp(GetAppId(), APPWIDGET_ON_UPDATE, pArgs.release());
330 }
331
332 result
333 _AppWidgetContext::SendResizeRequest(int width, int height) const
334 {
335         std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN() );
336
337         return __pAppContext->SendRequestToApp(GetAppId(), APPWIDGET_ON_RESIZE, pArgs.release());
338 }
339
340 result
341 _AppWidgetContext::SendRemoveRequest(void) const
342 {
343         std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN());
344
345         return __pAppContext->SendRequestToApp(GetAppId(), APPWIDGET_ON_REMOVE, pArgs.release());
346 }
347
348 void
349 _AppWidgetContext::SendPendingTouchEvent(void)
350 {
351         for (int i =0; i< __pPendingTouchEventList->GetCount(); i++)
352         {
353                 PendingTouchEvent* pTouchEvent = null;
354                 __pPendingTouchEventList->GetAt(i, pTouchEvent);
355                 AppWidgetManagerService::GetInstance()->SendTouchEvent(GetClientId(), GetInstanceId(), pTouchEvent->eventType, pTouchEvent->timeStamp, pTouchEvent->x, pTouchEvent->y);
356                 delete pTouchEvent;
357         }
358         __pPendingTouchEventList->RemoveAll();
359 }
360
361 void
362 _AppWidgetContext::OnTouchEventReceived(buffer_event event, double timestamp, double x, double y)
363 {
364         if (__pAppContext->GetConnectionState() == CONNECTION_STATE_CONNECTED && __isRemoteBufferProxyCreated)
365         {
366                 SysLog(NID_SHELL, "%d, %f, %f", event, x, y);
367                 AppWidgetManagerService::GetInstance()->SendTouchEvent(GetClientId(), GetInstanceId(), event, timestamp, x, y);
368         }
369         else
370         {
371                 __pPendingTouchEventList->Add(new (nothrow) PendingTouchEvent(event, timestamp, x, y));
372
373                 if( _AppManagerImpl::GetInstance()->IsRunning(this->GetAppId() ) == false ||
374                         ( __pAppContext->GetConnectionState() == CONNECTION_STATE_CONNECTED && __isRemoteBufferProxyCreated == false))
375                 {
376                         SysLog(NID_SHELL, "request to start AppControl");
377                         std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN() );
378
379                         // TODO: consider to remove these unused args.
380                         pArgs->Add(new (nothrow) String(ARG_KEY_EVENT_TYPE), new (nothrow) String(Integer::ToString(event)));
381                         pArgs->Add(new (nothrow) String(ARG_KEY_TIME_STAMP), new (nothrow) String(Double::ToString(timestamp)));
382                         pArgs->Add(new (nothrow) String(ARG_KEY_X), new (nothrow) String(Double::ToString(x)));
383                         pArgs->Add(new (nothrow) String(ARG_KEY_Y), new (nothrow) String(Double::ToString(y)));
384
385                         _AppWidgetRequestHelper::SendAppControlRequest(GetAppId(), APPWIDGET_ON_TOUCH, pArgs.get());
386                 }
387         }
388 }
389
390 result
391 _AppWidgetContext::SyncRemoteBuffer(int width, int height)
392 {
393         std::unique_ptr<char[]> providerId(_StringConverter::CopyToCharArrayN(GetProviderId()));
394         std::unique_ptr<char[]> id(_StringConverter::CopyToCharArrayN(GetInstanceId()));
395         std::unique_ptr<char[]> content_info(_StringConverter::CopyToCharArrayN(GetUserInfo()));
396
397         int ret = provider_send_updated(providerId.get(), id.get(), width, height, GetPriority(), content_info.get(), null);
398         SysTryReturnResult(NID_SHELL, ret >= 0 , E_SYSTEM, "[E_SYSTEM] failed to provider_send_updated");
399
400         SendPendingTouchEvent();
401         SysLog(NID_SHELL, "Done");
402         return E_SUCCESS;
403 }
404
405 result
406 _AppWidgetContext::SyncRemoteBufferForPD(void) const
407 {
408         _AppWidgetPopupContext* pPopupContext = GetAppWidgetPopup();
409         SysSecureTryReturnResult(NID_SHELL, pPopupContext , E_SYSTEM, "pPopupContext is null for (%ls)", GetProviderId().GetPointer());
410
411         return pPopupContext->SyncRemoteBuffer();
412 }
413
414 result
415 _AppWidgetContext::SendAccessStatus(int accessStatus) const
416 {
417         std::unique_ptr<char[]> providerId(_StringConverter::CopyToCharArrayN(GetProviderId()));
418         std::unique_ptr<char[]> id(_StringConverter::CopyToCharArrayN(GetInstanceId()));
419
420         int ret = provider_send_access_status(providerId.get(), id.get(), accessStatus);
421         SysTryReturnResult(NID_SHELL, ret >= 0 , E_SYSTEM, "[E_SYSTEM] failed to provider_send_access_status");
422
423         return E_SUCCESS;
424 }
425
426 Tizen::Base::Collection::HashMap*
427 _AppWidgetContext::CreateRequestArgsN(void) const
428 {
429         HashMap* pArgs = new (nothrow) HashMap(SingleObjectDeleter);
430         pArgs->Construct();
431
432         pArgs->Add(new (nothrow) String(ARG_KEY_INSTANCE_ID), new (nothrow) String(GetInstanceId()));
433         pArgs->Add(new (nothrow) String(ARG_KEY_PROVIDER_NAME), new (nothrow) String(GetProviderName()));
434         pArgs->Add(new (nothrow) String(ARG_KEY_USER_INFO), new (nothrow) String(GetUserInfo()));
435         pArgs->Add(new (nothrow) String(ARG_KEY_WIDTH), new (nothrow) String(Integer::ToString(GetWidth())));
436         pArgs->Add(new (nothrow) String(ARG_KEY_HEIGHT), new (nothrow) String(Integer::ToString(GetHeight())));
437
438         return pArgs;
439 }
440
441 int
442 _AppWidgetContext::GetPeriod(void) const
443 {
444         return __updateMillis;
445 }
446
447 long long
448 _AppWidgetContext::GetLastUpdatedTime(void) const
449 {
450         return __lastUpdatedTime;
451 }
452
453 int
454 _AppWidgetContext::GetClientId(void) const
455 {
456         return GetAppContext()->GetClientId();
457 }
458
459 int
460 _AppWidgetContext::GetWidth(void) const
461 {
462         return __width;
463 }
464
465 void
466 _AppWidgetContext::SetWidth(int width)
467 {
468         __width = width;
469 }
470
471 int
472 _AppWidgetContext::GetHeight(void) const
473 {
474         return __height;
475 }
476
477 void
478 _AppWidgetContext::SetHeight(int height)
479 {
480         __height = height;
481 }
482
483 String
484 _AppWidgetContext::GetProviderId(void) const
485 {
486         return __providerId;
487 }
488
489 /*void
490 _AppWidgetContext::SetProviderId(const String& providerId)
491 {
492         __providerId = providerId;
493 }*/
494
495 String
496 _AppWidgetContext::GetAppId(void) const
497 {
498         return __appId;
499 }
500
501 int
502 _AppWidgetContext::GetPriority(void) const
503 {
504         return __priority;
505 }
506
507 /*void
508 _AppWidgetContext::SetPriority(int priority)
509 {
510         __priority = priority;
511 }*/
512
513 String
514 _AppWidgetContext::GetProviderName(void) const
515 {
516         return __providerName;
517 }
518
519 bool
520 _AppWidgetContext::IsForeground(void) const
521 {
522         return __isForeground;
523 }
524
525 String
526 _AppWidgetContext::GetUserInfo(void) const
527 {
528         return __userInfo;
529 }
530
531 /*void
532 _AppWidgetContext::SetUserInfo(const String& userInfo)
533 {
534         __userInfo = userInfo;
535 }*/
536
537 String
538 _AppWidgetContext::GetInstanceId(void) const
539 {
540         return __instanceId;
541 }
542
543 void
544 _AppWidgetContext::OnTimerExpired(Tizen::Base::Runtime::Timer& timer)
545 {
546         if (&timer == &__updateTimer)
547         {
548                 SysLog(NID_SHELL, "update timer is expired for appWidget app(%ls).", GetProviderId().GetPointer());
549                 OnUpdate(L"");
550         }
551 }
552
553 void
554 _AppWidgetContext::OnDisconnected(void)
555 {
556         SysSecureLog(NID_SHELL, "%ls, %ls", GetInstanceId().GetPointer(), GetProviderId().GetPointer());
557
558         __isRemoteBufferProxyCreated = false;
559         if (GetAppWidgetPopup())
560         {
561                 OnPopupDestoyed();
562         }
563 }
564
565 int
566 _AppWidgetContext::AcquireRemoteBuffer(int w, int h) const
567 {
568         int id = __pAppWidgetRemoteBuffer->Acquire(w, h);
569         if (id != -1)
570         {
571                 __isRemoteBufferProxyCreated = true;
572         }
573         return id;
574 }
575
576 int
577 _AppWidgetContext::AcquireRemoteBufferForPD(int w, int h) const
578 {
579         _AppWidgetPopupContext* pPopupContext = GetAppWidgetPopup();
580         SysSecureTryReturnResult(NID_SHELL, pPopupContext , E_SYSTEM, "pPopupContext is null for (%ls)", GetProviderId().GetPointer());
581
582         int bufferId = pPopupContext->AcquireRemoteBuffer(w, h);
583         SysSecureTryReturnResult(NID_SHELL, bufferId != -1, E_SYSTEM, "Failed to AcquireRemoteBuffer for (%ls)", GetProviderId().GetPointer());
584
585         return bufferId;
586 }
587
588 }}}  // Tizen::Shell::App