The license change version 1.0 to version 1.1
[platform/framework/web/web-provider.git] / src / Plugin / AppBoxPlugin / AppBoxRenderView.cpp
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
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  * @file    AppBoxRenderView.cpp
18  * @author  Yunchan Cho (yunchan.cho@samsung.com)
19  */
20 #include <string>
21 #include <Eina.h>
22 #include <Evas.h>
23 #include <Ecore.h>
24 #include <livebox-service.h>
25 #include <i_runnable_widget_object.h>
26 #include <core_module.h>
27 #include <dpl/fast_delegate.h>
28 #include <Core/View/IRenderView.h>
29 #include <Core/View/IPdHelper.h>
30 #include <Core/View/PdHelper.h>
31 #include <API/web_provider_livebox_info.h>
32 #include <Core/Util/Log.h>
33 #include "AppBoxObserver.h"
34 #include "AppBoxRenderBuffer.h"
35 #include "AppBoxRenderView.h"
36
37 #define RENDER_MAX_TIME 10.0
38
39 AppBoxRenderView::AppBoxRenderView(
40         std::string boxId, std::string instanceId,
41         Evas_Object* boxWin, EwkContextPtr ewkContext)
42     : m_appId()
43     , m_boxId(boxId)
44     , m_instanceId(instanceId)
45     , m_boxWin(boxWin)
46     , m_baseWebView()
47     , m_snapshot()
48     , m_renderInfo()
49     , m_view()
50     , m_startUrl()
51     , m_fireRenderTimer()
52     , m_pdHelper()
53     , m_ewkContext(ewkContext)
54 {
55     LogD("enter");
56     m_appId = getAppId(m_boxId);
57     if (m_appId.empty()) {
58         throw; //exception throw!
59     }
60
61     evas_object_show(m_boxWin);
62     m_renderBuffer = AppBoxObserver::Instance()->getRenderBuffer(m_instanceId);
63     AppBoxObserver::Instance()->registerRenderView(m_instanceId, this);
64 }
65
66 AppBoxRenderView::~AppBoxRenderView()
67 {
68     LogD("enter");
69     evas_object_hide(m_boxWin);
70     AppBoxObserver::Instance()->unregisterRenderView(m_instanceId);
71 }
72
73 void AppBoxRenderView::showBox(RenderInfoPtr renderInfo)
74 {
75     LogD("enter");
76
77     // delete already running timer
78     deleteRenderTimer();
79
80     // stop touch timer
81     if (web_provider_livebox_get_mouse_event(m_boxId.c_str())) {
82         m_renderBuffer->deleteTouchTimer();
83     }
84
85     // copy to url
86     m_startUrl = getStartUrl(URL_TYPE_BOX, renderInfo->defaultUrlParams);
87
88     if (!createView()) {
89         LogD("can't create view instance");
90         return;
91     }
92
93     // in case of showing box by request of pd open
94     if (m_pdHelper) {
95         m_pdHelper->setBaseWebView(m_baseWebView);
96     }
97
98     // resize webview fitted to width, height of Box
99     evas_object_resize(
100             m_baseWebView, 
101             renderInfo->width,
102             renderInfo->height);
103
104     clearSnapShot();
105     m_renderBuffer->startCanvasUpdate();
106     m_view->Show();
107     m_renderInfo = renderInfo;
108 }
109
110 bool AppBoxRenderView::createView()
111 {
112     LogD("enter");
113     
114     if (m_view) {
115         m_view->Hide();
116         m_view.reset();
117         m_baseWebView = NULL;
118     }
119 #ifdef MULTIPROCESS_SERVICE_SUPPORT
120     m_view = WRT::CoreModuleSingleton::
121                 Instance().getRunnableWidgetObject(m_appId, DPL::Optional<unsigned>());
122 #else
123     m_view = WRT::CoreModuleSingleton::
124                 Instance().getRunnableWidgetObject(m_appId);
125 #endif
126     // prepare webview
127     if (m_startUrl.empty()) {
128         LogD("no start url");
129         return false;
130     }
131     m_view->PrepareView(m_startUrl, m_boxWin, m_ewkContext.get());
132     m_view->CheckBeforeLaunch();
133
134     // set callback functions of RunnableWidgetObject
135     WRT::UserDelegatesPtr cbs(new WRT::UserDelegates);
136     cbs->loadStart = DPL::MakeDelegate(this, &AppBoxRenderView::startLoadCallback);
137     cbs->loadFinish = DPL::MakeDelegate(this, &AppBoxRenderView::finishLoadCallback);
138     cbs->bufferSet = DPL::MakeDelegate(this, &AppBoxRenderView::setBufferCallback);
139     cbs->bufferUnset = DPL::MakeDelegate(this, &AppBoxRenderView::unsetBufferCallback);
140     cbs->windowCreateBefore = DPL::MakeDelegate(this, &AppBoxRenderView::createWindowBeforeCallback);
141     cbs->windowCreateAfter = DPL::MakeDelegate(this, &AppBoxRenderView::createWindowAfterCallback);
142     m_view->SetUserDelegates(cbs);
143
144     // set base webview
145     m_baseWebView = m_view->GetCurrentWebview();
146
147     // To support transparent background
148     evas_object_color_set(m_baseWebView, 0, 0, 0, 0);
149     evas_object_layer_set(m_baseWebView, EVAS_LAYER_MAX);
150     return true;
151 }
152
153 bool AppBoxRenderView::destroyView()
154 {
155     LogD("enter");
156
157     m_renderBuffer->stopCanvasUpdate();
158     deleteRenderTimer();
159     if (m_view) {
160         m_view->Hide();
161         m_view.reset();
162         m_baseWebView = NULL;
163     }
164
165     return true;
166 }
167
168 void AppBoxRenderView::hideBox()
169 {
170     LogD("enter");
171     destroyView();
172 }
173
174 void AppBoxRenderView::pauseBox()
175 {
176     LogD("enter");
177 }
178
179 void AppBoxRenderView::resumeBox()
180 {
181     LogD("enter");
182 }
183
184 void AppBoxRenderView::showPd(Evas_Object* pdWin, RenderInfoPtr renderInfo)
185 {
186     LogD("enter");
187
188     // create pd helper
189     std::string pdStartUrl = getStartUrl(URL_TYPE_PD, renderInfo->defaultUrlParams);
190     m_pdHelper = PdHelper::create(pdWin, pdStartUrl, renderInfo);
191
192     // show pd window
193     evas_object_show(pdWin);
194     showBox(m_renderInfo);
195 }
196
197 void AppBoxRenderView::hidePd()
198 {
199     LogD("enter");
200
201     m_pdHelper->close();
202     m_pdHelper.reset();
203
204     // stop box webview after render timer
205     addRenderTimer();
206 }
207
208 std::string AppBoxRenderView::getAppId(std::string& boxId)
209 {
210     LogD("enter");
211
212     const char* appId = web_provider_livebox_get_app_id(boxId.c_str());
213     if (!appId) {
214         LogD("no appid of %s", boxId.c_str());
215         return std::string();
216     }
217
218     return std::string(appId);
219 }
220
221 std::string AppBoxRenderView::getStartUrl(UrlType type, std::string& defaultParams)
222 {
223     std::string url;
224     switch (type) {
225     case URL_TYPE_BOX:
226         url = livebox_service_lb_script_path(m_boxId.c_str());
227         break;
228     case URL_TYPE_PD:
229         url = livebox_service_pd_script_path(m_boxId.c_str());
230         break;
231     default:
232         LogD("no available type");
233     }
234
235     // add default parameters to start url
236     url += defaultParams;
237
238     return url;
239 }
240
241 Evas_Object* AppBoxRenderView::getCurrentSnapShot() 
242 {
243     LogD("enter");
244     clearSnapShot();
245     m_snapshot = m_renderBuffer->getSnapshot();
246     //evas_object_layer_set(m_snapshot, EVAS_LAYER_MAX);
247
248     return m_snapshot;
249 }
250
251 void AppBoxRenderView::clearSnapShot() 
252 {
253     LogD("enter");
254     if (m_snapshot) {
255         evas_object_layer_set(m_snapshot, EVAS_LAYER_MIN);
256         //evas_object_hide(m_snapshot);
257         evas_object_del(m_snapshot);
258         m_snapshot = NULL;
259     }
260 }
261
262 void AppBoxRenderView::addRenderTimer()
263 {
264     LogD("enter");
265     if (m_fireRenderTimer) {
266         deleteRenderTimer();
267     }
268
269     m_fireRenderTimer = ecore_timer_add(
270                             RENDER_MAX_TIME, 
271                             fireRenderTimerCallback,
272                             this);
273 }
274
275 void AppBoxRenderView::deleteRenderTimer()
276 {
277     LogD("enter");
278     if (m_fireRenderTimer) {
279         ecore_timer_del(m_fireRenderTimer);
280         m_fireRenderTimer = NULL;
281     }
282 }
283
284 Eina_Bool AppBoxRenderView::fireRenderTimerCallback(void* data)
285 {
286     LogD("enter");
287
288     AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
289     This->m_fireRenderTimer = NULL;
290
291     This->m_renderBuffer->stopCanvasUpdate();
292     if (web_provider_livebox_get_mouse_event(This->m_boxId.c_str())) {
293         // stop touch timer
294         This->m_renderBuffer->deleteTouchTimer();
295         This->m_view->Suspend();
296     } else {
297         // Before webview should be removed,
298         // new evas object with last render data should be created
299         // otherwise, after webview is removed, box is white screen.
300         evas_object_show(This->getCurrentSnapShot());
301         This->destroyView();
302     }
303
304     return ECORE_CALLBACK_CANCEL;
305 }
306
307 Eina_Bool AppBoxRenderView::openPdIdlerCallback(void* data)
308 {
309     LogD("enter");
310     AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
311     if (This && This->m_pdHelper) {
312         This->m_pdHelper->startOpen();
313     }
314     return ECORE_CALLBACK_CANCEL;
315 }
316
317
318 void AppBoxRenderView::startLoadCallback(Evas_Object* webview)
319 {
320     // start load
321 }
322
323 void AppBoxRenderView::finishLoadCallback(Evas_Object* webview)
324 {
325     LogD("enter");
326     ewk_view_visibility_set(webview, EINA_TRUE);
327
328     if (!m_pdHelper) {
329         // start render timer
330         addRenderTimer();
331     } else {
332         if (!(m_pdHelper->isPdOpened()) && 
333                 webview == m_pdHelper->getBaseWebView())
334         {
335             // open pd
336             ecore_idler_add(openPdIdlerCallback, this);
337         }
338     }
339 }
340
341 void AppBoxRenderView::createWindowBeforeCallback(Evas** canvas, Evas_Object* parent)
342 {
343     LogD("enter");
344
345     if (m_pdHelper) {
346         if (!(m_pdHelper->isPdOpened()) && 
347                 parent == m_pdHelper->getBaseWebView())
348         {
349             LogD("pd canvas is used");
350             *canvas = m_pdHelper->getPdCanvas();
351             return;
352         }
353     } 
354     
355     LogD("canvas of this webview is used");
356     *canvas = evas_object_evas_get(parent);
357 }
358
359 void AppBoxRenderView::createWindowAfterCallback(Evas_Object* parent, Evas_Object* child)
360 {
361     LogD("enter");
362
363     // To support transparent background
364     evas_object_color_set(child, 0, 0, 0, 0);
365
366     if (m_pdHelper) {
367         Evas* parentCanvas = evas_object_evas_get(parent);
368         Evas* childCanvas = evas_object_evas_get(child);
369
370         if (parentCanvas != childCanvas) {
371            // wrt-core change visibility value to false internally
372            // So plugin should reset this value to true for painting parent webview
373            ewk_view_visibility_set(parent, EINA_TRUE);
374            evas_object_show(parent);
375            m_pdHelper->finishOpen(child); 
376         }
377     }
378
379     ewk_view_visibility_set(child, EINA_TRUE);
380     evas_object_show(child);
381 }
382
383 void AppBoxRenderView::setBufferCallback(Evas_Object* webview)
384 {
385     LogD("enter");
386     evas_object_show(webview);
387     evas_object_focus_set(webview, EINA_TRUE);
388 }
389
390 void AppBoxRenderView::unsetBufferCallback(Evas_Object* webview)
391 {
392     LogD("enter");
393     evas_object_hide(webview);
394 }