e9a2066a9e21129b0eb6fdfb8a88f7ca77c67aec
[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 Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0
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 <Core/Util/Log.h>
32 #include "AppBoxObserver.h"
33 #include "AppBoxRenderBuffer.h"
34 #include "AppBoxRenderView.h"
35
36 #define RENDER_MAX_TIME 10.0
37
38 AppBoxRenderView::AppBoxRenderView(
39         std::string boxId, std::string instanceId,
40         Evas_Object* boxWin, EwkContextPtr ewkContext)
41     : m_appId()
42     , m_boxId(boxId)
43     , m_instanceId(instanceId)
44     , m_boxWin(boxWin)
45     , m_baseWebView()
46     , m_renderInfo()
47     , m_view()
48     , m_startUrl()
49     , m_fireRenderTimer()
50     , m_pdHelper()
51     , m_ewkContext(ewkContext)
52 {
53     LogD("enter");
54     m_appId = getAppId(m_boxId);
55     if (m_appId.empty()) {
56         throw; //exception throw!
57     }
58
59     evas_object_show(m_boxWin);
60     m_renderBuffer = AppBoxObserver::Instance()->getRenderBuffer(m_instanceId);
61     AppBoxObserver::Instance()->registerRenderView(m_instanceId, this);
62 }
63
64 AppBoxRenderView::~AppBoxRenderView()
65 {
66     LogD("enter");
67     evas_object_hide(m_boxWin);
68     AppBoxObserver::Instance()->unregisterRenderView(m_instanceId);
69 }
70
71 void AppBoxRenderView::showBox(RenderInfoPtr renderInfo)
72 {
73     LogD("enter");
74
75     // delete already running timer
76     deleteRenderTimer();
77
78     // stop touch timer
79     if (livebox_service_mouse_event(m_boxId.c_str())) {
80         m_renderBuffer->deleteTouchTimer();
81     }
82
83     // copy to url
84     m_startUrl = getStartUrl(URL_TYPE_BOX, renderInfo->defaultUrlParams);
85
86     if (!createView()) {
87         LogD("can't create view instance");
88         return;
89     }
90
91     // in case of showing box by request of pd open
92     if (m_pdHelper) {
93         m_pdHelper->setBaseWebView(m_baseWebView);
94     }
95
96     // resize webview fitted to width, height of Box
97     evas_object_resize(
98             m_baseWebView, 
99             renderInfo->width,
100             renderInfo->height);
101
102     m_view->Show();
103     m_renderInfo = renderInfo;
104 }
105
106 bool AppBoxRenderView::createView()
107 {
108     LogD("enter");
109     
110     if (m_view) {
111         m_view->Hide();
112         m_view.reset();
113         m_baseWebView = NULL;
114     }
115
116     m_view = WRT::CoreModuleSingleton::
117                 Instance().getRunnableWidgetObject(m_appId);
118
119     // prepare webview
120     if (m_startUrl.empty()) {
121         LogD("no start url");
122         return false;
123     }
124     m_view->PrepareView(m_startUrl, m_boxWin, m_ewkContext.get());
125     m_view->CheckBeforeLaunch();
126
127     // set callback functions of RunnableWidgetObject
128     WRT::UserDelegatesPtr cbs(new WRT::UserDelegates);
129     cbs->loadStart = DPL::MakeDelegate(this, &AppBoxRenderView::startLoadCallback);
130     cbs->loadFinish = DPL::MakeDelegate(this, &AppBoxRenderView::finishLoadCallback);
131     cbs->bufferSet = DPL::MakeDelegate(this, &AppBoxRenderView::setBufferCallback);
132     cbs->bufferUnset = DPL::MakeDelegate(this, &AppBoxRenderView::unsetBufferCallback);
133     cbs->windowCreateBefore = DPL::MakeDelegate(this, &AppBoxRenderView::createWindowBeforeCallback);
134     cbs->windowCreateAfter = DPL::MakeDelegate(this, &AppBoxRenderView::createWindowAfterCallback);
135     m_view->SetUserDelegates(cbs);
136
137     // set base webview
138     m_baseWebView = m_view->GetCurrentWebview();
139     m_renderBuffer->startCanvasUpdate();
140     return true;
141 }
142
143 bool AppBoxRenderView::destroyView()
144 {
145     LogD("enter");
146
147     m_renderBuffer->stopCanvasUpdate();
148     ecore_idler_add(destroyViewIdlerCallback, this);
149     return true;
150 }
151
152 void AppBoxRenderView::hideBox()
153 {
154     LogD("enter");
155     destroyView();
156 }
157
158 void AppBoxRenderView::pauseBox()
159 {
160     LogD("enter");
161 }
162
163 void AppBoxRenderView::resumeBox()
164 {
165     LogD("enter");
166 }
167
168 void AppBoxRenderView::showPd(Evas_Object* pdWin, RenderInfoPtr renderInfo)
169 {
170     LogD("enter");
171
172     // create pd helper
173     std::string pdStartUrl = getStartUrl(URL_TYPE_PD, renderInfo->defaultUrlParams);
174     m_pdHelper = PdHelper::create(pdWin, pdStartUrl, renderInfo);
175
176     // show pd window
177     evas_object_show(pdWin);
178     showBox(m_renderInfo);
179 }
180
181 void AppBoxRenderView::hidePd()
182 {
183     LogD("enter");
184
185     m_pdHelper->close();
186     m_pdHelper.reset();
187
188     // destory box webview to stop rendering
189     destroyView();
190 }
191
192 std::string AppBoxRenderView::getAppId(std::string& boxId)
193 {
194     // TODO more exact and safe parsing is needed
195     std::string temp = std::string(boxId);
196     int found = temp.find_last_of(".");
197     if (found == std::string::npos) {
198         return std::string();
199     }
200
201     temp.assign(temp, 0, found);
202     return temp;
203 }
204
205 std::string AppBoxRenderView::getStartUrl(UrlType type, std::string& defaultParams)
206 {
207     std::string url;
208     switch (type) {
209     case URL_TYPE_BOX:
210         url = livebox_service_lb_script_path(m_boxId.c_str());
211         break;
212     case URL_TYPE_PD:
213         url = livebox_service_pd_script_path(m_boxId.c_str());
214         break;
215     default:
216         LogD("no available type");
217     }
218
219     // add default parameters to start url
220     url += defaultParams;
221
222     return url;
223 }
224
225 void AppBoxRenderView::addRenderTimer()
226 {
227     LogD("enter");
228     if (m_fireRenderTimer) {
229         deleteRenderTimer();
230     }
231
232     m_fireRenderTimer = ecore_timer_add(
233                             RENDER_MAX_TIME, 
234                             fireRenderTimerCallback,
235                             this);
236 }
237
238 void AppBoxRenderView::deleteRenderTimer()
239 {
240     LogD("enter");
241     if (m_fireRenderTimer) {
242         ecore_timer_del(m_fireRenderTimer);
243         m_fireRenderTimer = NULL;
244     }
245 }
246
247 Eina_Bool AppBoxRenderView::fireRenderTimerCallback(void* data)
248 {
249     LogD("enter");
250
251     AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
252     This->m_fireRenderTimer = NULL;
253     
254     This->m_renderBuffer->stopCanvasUpdate();
255     if (livebox_service_mouse_event(This->m_boxId.c_str())) {
256         // stop touch timer
257         This->m_renderBuffer->deleteTouchTimer();
258         This->m_view->Suspend();
259     } else {
260         // webview should be removed
261         ecore_idler_add(destroyViewIdlerCallback, This);
262     }
263
264     return ECORE_CALLBACK_CANCEL;
265 }
266
267 Eina_Bool AppBoxRenderView::destroyViewIdlerCallback(void* data)
268 {
269     LogD("enter");
270
271     AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
272     if (This->m_view) {
273         This->m_view->Hide();
274         This->m_view.reset();
275         This->m_baseWebView = NULL;
276     }
277
278     return ECORE_CALLBACK_CANCEL;
279 }
280
281 void AppBoxRenderView::startLoadCallback(Evas_Object* webview)
282 {
283     // start load
284 }
285
286 void AppBoxRenderView::finishLoadCallback(Evas_Object* webview)
287 {
288     LogD("enter");
289     ewk_view_visibility_set(webview, EINA_TRUE);
290
291     if (!m_pdHelper) {
292         // start render timer
293         addRenderTimer();
294     } else {
295         if (!(m_pdHelper->isPdOpened()) && 
296                 webview == m_pdHelper->getBaseWebView())
297         {
298             m_pdHelper->startOpen();
299         }
300     }
301 }
302
303 void AppBoxRenderView::createWindowBeforeCallback(Evas** canvas, Evas_Object* parent)
304 {
305     LogD("enter");
306
307     if (m_pdHelper) {
308         if (!(m_pdHelper->isPdOpened()) && 
309                 parent == m_pdHelper->getBaseWebView())
310         {
311             LogD("pd canvas is used");
312             *canvas = m_pdHelper->getPdCanvas();
313             return;
314         }
315     } 
316     
317     LogD("canvas of this webview is used");
318     *canvas = evas_object_evas_get(parent);
319 }
320
321 void AppBoxRenderView::createWindowAfterCallback(Evas_Object* parent, Evas_Object* child)
322 {
323     LogD("enter");
324
325     if (m_pdHelper) {
326         Evas* parentCanvas = evas_object_evas_get(parent);
327         Evas* childCanvas = evas_object_evas_get(child);
328
329         if (parentCanvas != childCanvas) {
330            evas_object_show(parent);
331            evas_object_show(child);
332            m_pdHelper->finishOpen(child); 
333         }
334     }
335 }
336
337 void AppBoxRenderView::setBufferCallback(Evas_Object* webview)
338 {
339     LogD("enter");
340     evas_object_show(webview);
341     evas_object_focus_set(webview, EINA_TRUE);
342 }
343
344 void AppBoxRenderView::unsetBufferCallback(Evas_Object* webview)
345 {
346     LogD("enter");
347     evas_object_hide(webview);
348 }