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