2 * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://floralicense.org/license/
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.
17 * @file AppBoxRenderView.cpp
18 * @author Yunchan Cho (yunchan.cho@samsung.com)
28 #include <ewk_context.h>
29 #include <ewk_settings.h>
30 #include <livebox-service.h>
31 #include <i_runnable_widget_object.h>
32 #include <core_module.h>
33 #include <dpl/fast_delegate.h>
34 #include <Core/BoxSchemeHandler.h>
35 #include <Core/View/IRenderView.h>
36 #include <Core/View/IPdHelper.h>
37 #include <Core/View/PdHelper.h>
38 #include <API/web_provider_livebox_info.h>
39 #include <Core/Util/Log.h>
40 #include "AppBoxObserver.h"
41 #include "AppBoxRenderBuffer.h"
42 #include "AppBoxPdHelper.h"
43 #include "AppBoxRenderView.h"
45 #define RENDER_MAX_TIME 30.0
46 #define SNAPSHOT_REMOVE_TIME 1.0
48 // injection javascript file regarding creating js object used by box and pd
49 static const std::string injectionFile("/usr/share/web-provider/injection.js");
51 AppBoxRenderView::AppBoxRenderView(
52 std::string boxId, std::string instanceId,
53 EwkContextPtr ewkContext)
56 , m_instanceId(instanceId)
57 , m_ewkContext(ewkContext)
63 , m_removeSnapShotTimer()
67 , m_boxFinishLoad(false)
68 , m_boxWrt_isSuspended(false)
71 m_appId = getAppId(m_boxId);
72 if (m_appId.empty()) {
73 throw; //exception throw!
76 m_boxRenderBuffer = AppBoxObserver::Instance()->getRenderBuffer(m_instanceId);
78 // use fastopen to default
79 // m_pdFastOpen = web_provider_livebox_get_pd_fast_open(m_boxId.c_str()) ? true : false;
81 AppBoxObserver::Instance()->registerRenderView(m_instanceId, this);
84 AppBoxRenderView::~AppBoxRenderView()
87 AppBoxObserver::Instance()->unregisterRenderView(m_instanceId);
90 void AppBoxRenderView::showBox(RenderInfoPtr boxRenderInfo)
94 // stop updating render buffer
95 m_boxRenderBuffer->stopCanvasUpdate();
97 // clear snapshot if this is not the case of pd open
102 // delete already running timer
103 deleteTimer(&m_fireRenderTimer);
105 // delete touch timer
106 if (web_provider_livebox_get_mouse_event(m_boxId.c_str())) {
107 m_boxRenderBuffer->deleteTouchTimer();
110 // set boxFinishLoad to false
111 m_boxFinishLoad = false;
114 std::string boxStartUrl = getStartUrl(URL_TYPE_BOX, boxRenderInfo->defaultUrlParams);
116 LogD("existing wrt core is removed");
120 m_boxWrt = createWrtCore(
121 URL_TYPE_BOX, boxStartUrl,
122 boxRenderInfo->window, m_ewkContext);
123 m_boxWrt_isSuspended = false;
125 // in case of showing box by request of pd open
127 m_pdHelper->setBoxWebView(m_boxWrt->GetCurrentWebview());
130 // resize webview fitted to width, height of Box
132 m_boxWrt->GetCurrentWebview(),
133 boxRenderInfo->width,
134 boxRenderInfo->height);
137 evas_object_show(boxRenderInfo->window);
139 m_boxRenderInfo = boxRenderInfo;
142 AppBoxRenderView::WrtCorePtr AppBoxRenderView::createWrtCore(
143 UrlType type, std::string& startUrl,
144 Evas_Object* win, EwkContextPtr ewkContext)
149 wrt = WRT::CoreModuleSingleton::
150 Instance().getRunnableWidgetObject(m_appId);
152 if (startUrl.empty()) {
153 LogD("no start url");
156 wrt->PrepareView(startUrl, win, ewkContext.get());
157 wrt->CheckBeforeLaunch();
159 // set callback functions of RunnableWidgetObject
160 WRT::UserDelegatesPtr cbs(new WRT::UserDelegates);
161 cbs->loadStart = DPL::MakeDelegate(this, &AppBoxRenderView::startLoadCallback);
162 if (type == URL_TYPE_BOX) {
163 cbs->loadFinish = DPL::MakeDelegate(this, &AppBoxRenderView::finishBoxLoadCallback);
165 cbs->loadFinish = DPL::MakeDelegate(this, &AppBoxRenderView::finishPdLoadCallback);
168 cbs->bufferSet = DPL::MakeDelegate(this, &AppBoxRenderView::setBufferCallback);
169 cbs->bufferUnset = DPL::MakeDelegate(this, &AppBoxRenderView::unsetBufferCallback);
171 cbs->windowCreateBefore =
172 DPL::MakeDelegate(this, &AppBoxRenderView::createWindowBeforeCallback);
173 cbs->windowCreateAfter =
174 DPL::MakeDelegate(this, &AppBoxRenderView::createWindowAfterCallback);
177 cbs->navigationDecide =
178 DPL::MakeDelegate(this, &AppBoxRenderView::decideNavigationCallback);
179 cbs->webCrash = DPL::MakeDelegate(this, &AppBoxRenderView::crashWebProcessCallback);
180 wrt->SetUserDelegates(cbs);
182 // set basic webview setting
183 setWebViewBasicSetting(wrt->GetCurrentWebview());
187 void AppBoxRenderView::destroyBoxWrtCore()
191 m_boxRenderBuffer->stopCanvasUpdate();
192 deleteTimer(&m_fireRenderTimer);
193 deleteTimer(&m_removeSnapShotTimer);
194 destroyWrtCore(m_boxWrt);
198 m_boxWrt_isSuspended = false;
201 void AppBoxRenderView::destroyPdWrtCore()
205 destroyWrtCore(m_pdWrt);
209 void AppBoxRenderView::destroyWrtCore(WrtCorePtr wrt)
218 void AppBoxRenderView::hideBox()
222 if (m_boxRenderInfo->window) {
223 evas_object_hide(m_boxRenderInfo->window);
227 void AppBoxRenderView::pauseBox()
232 void AppBoxRenderView::resumeBox()
237 void AppBoxRenderView::showPd(RenderInfoPtr pdRenderInfo, RenderInfoPtr boxRenderInfo)
241 std::string pdStartUrl = getStartUrl(URL_TYPE_PD, pdRenderInfo->defaultUrlParams);
244 // if you want to launch new Web Process for PD, use the following line.
245 // EwkContextPtr pdContext = AppBoxObserver::Instance()->getPdEwkContext();
246 m_pdWrt = createWrtCore(URL_TYPE_PD, pdStartUrl, pdRenderInfo->window, m_ewkContext);
248 LogD("no wrt core instance");
251 m_pdHelper = AppBoxPdHelper::create(pdRenderInfo->window);
253 // resize webview fitted to width, height of pd
255 m_pdWrt->GetCurrentWebview(),
257 pdRenderInfo->height);
260 m_pdHelper->finishOpen(m_pdWrt->GetCurrentWebview());
262 m_pdHelper = PdHelper::create(pdRenderInfo, pdStartUrl);
266 evas_object_show(pdRenderInfo->window);
269 showBox(boxRenderInfo);
271 // start timer for clearing existing snapshot in case of only pd open
272 addTimer(&m_removeSnapShotTimer, SNAPSHOT_REMOVE_TIME, removeSnapShotTimerCallback);
276 void AppBoxRenderView::hidePd()
290 Evas_Object* AppBoxRenderView::getBoxWebView()
293 return m_boxWrt->GetCurrentWebview();
295 // Here, we can't use GetCurrentWebView() of wrt-core to get Box' webview,
296 // because in the non fast-open, GetCurrentWebview() returns PD's webview.
297 return m_pdHelper->getBoxWebView();
301 Evas_Object* AppBoxRenderView::getPdWebView()
307 return m_pdHelper->getPdWebView();
310 std::string AppBoxRenderView::getAppId(std::string& boxId)
314 const char* appId = web_provider_livebox_get_app_id(boxId.c_str());
316 LogD("no appid of %s", boxId.c_str());
317 return std::string();
320 return std::string(appId);
323 std::string AppBoxRenderView::getStartUrl(UrlType type, std::string& defaultParams)
328 url = livebox_service_lb_script_path(m_boxId.c_str());
331 url = livebox_service_pd_script_path(m_boxId.c_str());
334 LogD("no available type");
337 // add default parameters to start url
338 url += defaultParams;
343 Evas_Object* AppBoxRenderView::getCurrentSnapShot()
347 m_snapshot = m_boxRenderBuffer->getSnapshot();
352 void AppBoxRenderView::clearSnapShot()
356 evas_object_del(m_snapshot);
361 void AppBoxRenderView::showSnapShot()
365 evas_object_raise(m_snapshot);
366 evas_object_show(m_snapshot);
370 void AppBoxRenderView::hideSnapShot()
374 evas_object_hide(m_snapshot);
375 evas_object_lower(m_snapshot);
379 void AppBoxRenderView::addTimer(Ecore_Timer** timer, double interval, Ecore_Task_Cb callback)
386 *timer = ecore_timer_add(interval, callback, this);
389 void AppBoxRenderView::deleteTimer(Ecore_Timer** timer)
393 ecore_timer_del(*timer);
398 void AppBoxRenderView::stopRenderBox()
400 deleteTimer(&m_fireRenderTimer);
401 m_boxRenderBuffer->stopCanvasUpdate();
402 if (web_provider_livebox_get_mouse_event(m_boxId.c_str())) {
404 m_boxRenderBuffer->deleteTouchTimer();
407 if (m_boxWrt_isSuspended == false)
409 m_boxWrt_isSuspended = true;
413 // Before webview should be removed,
414 // new evas object with last render data should be created
415 // otherwise, after webview is removed, box is white screen.
416 evas_object_show(getCurrentSnapShot());
421 void AppBoxRenderView::setWebViewBasicSetting(Evas_Object* webview)
428 Ewk_Settings* setting = ewk_view_settings_get(webview);
429 // To support transparent background
430 evas_object_color_set(webview, 0, 0, 0, 1);
431 ewk_view_visibility_set(webview, EINA_TRUE);
433 // To know starting point for updating buffer
434 evas_object_smart_callback_add(
436 "load,nonemptylayout,finished",
437 loadNonEmptyLayoutFinishedCallback,
439 evas_object_smart_callback_add(
442 frameRenderedCallback,
446 Eina_Bool AppBoxRenderView::fireRenderTimerCallback(void* data)
450 AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
451 This->m_fireRenderTimer = NULL;
452 This->stopRenderBox();
454 return ECORE_CALLBACK_CANCEL;
457 Eina_Bool AppBoxRenderView::removeSnapShotTimerCallback(void* data)
461 AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
462 if (!(This->m_boxFinishLoad)) {
463 return ECORE_CALLBACK_RENEW;
466 // hide snapshot because valid frame has been prepared generally.
467 This->clearSnapShot();
469 This->m_removeSnapShotTimer = NULL;
470 return ECORE_CALLBACK_CANCEL;
473 Eina_Bool AppBoxRenderView::openPdIdlerCallback(void* data)
476 AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
477 if (This && This->m_pdHelper) {
478 This->m_pdHelper->startOpen();
480 return ECORE_CALLBACK_CANCEL;
483 void AppBoxRenderView::executeScriptCallback(
484 Evas_Object* webview, const char* result, void* data)
488 std::string resultStr(result ? result : "null");
489 LogD("result: %s", resultStr.c_str());
492 void AppBoxRenderView::startLoadCallback(Evas_Object* webview)
498 // execute injection for creating js objects
499 std::ifstream jsFile(injectionFile);
500 std::string script((std::istreambuf_iterator<char>(jsFile)),
501 std::istreambuf_iterator<char>());
503 LogD("injected js code: %s", script.c_str());
504 ewk_view_script_execute(webview, script.c_str(), executeScriptCallback, this);
507 void AppBoxRenderView::finishBoxLoadCallback(Evas_Object* webview)
514 ewk_view_visibility_set(webview, EINA_TRUE);
517 // start render timer
518 addTimer(&m_fireRenderTimer, RENDER_MAX_TIME, fireRenderTimerCallback);
521 if (!(m_pdHelper->isPdOpened()) &&
522 webview == m_pdHelper->getBoxWebView())
525 ecore_idler_add(openPdIdlerCallback, this);
531 m_boxFinishLoad = true;
534 void AppBoxRenderView::finishPdLoadCallback(Evas_Object* webview)
541 ewk_view_visibility_set(webview, EINA_TRUE);
544 void AppBoxRenderView::createWindowBeforeCallback(Evas** canvas, Evas_Object* parent)
549 if (!(m_pdHelper->isPdOpened()) &&
550 parent == m_pdHelper->getBoxWebView())
552 LogD("pd canvas is used");
553 *canvas = m_pdHelper->getPdCanvas();
558 LogD("canvas of this webview is used");
559 *canvas = evas_object_evas_get(parent);
562 void AppBoxRenderView::createWindowAfterCallback(Evas_Object* parent, Evas_Object* child)
570 Evas* parentCanvas = evas_object_evas_get(parent);
571 Evas* childCanvas = evas_object_evas_get(child);
573 if (parentCanvas != childCanvas) {
574 // wrt-core change visibility value to false internally
575 // So plugin should reset this value to true for painting parent webview
576 ewk_view_visibility_set(parent, EINA_TRUE);
577 evas_object_show(parent);
578 m_pdHelper->finishOpen(child);
582 setWebViewBasicSetting(child);
583 evas_object_show(child);
586 void AppBoxRenderView::setBufferCallback(Evas_Object* webview)
589 evas_object_show(webview);
590 evas_object_focus_set(webview, EINA_TRUE);
593 void AppBoxRenderView::unsetBufferCallback(Evas_Object* webview)
596 evas_object_hide(webview);
599 void AppBoxRenderView::decideNavigationCallback(Evas_Object* webview, std::string& uri)
603 // navigation of box scheme should be ignored
604 if(BoxSchemeHandler::Instance()->isBoxScheme(uri)) {
606 BoxSchemeHandler::Instance()->process(m_instanceId, uri);
610 void AppBoxRenderView::crashWebProcessCallback()
617 void AppBoxRenderView::loadNonEmptyLayoutFinishedCallback(
618 void* data, Evas_Object* webview, void* eventInfo)
623 void AppBoxRenderView::frameRenderedCallback(
624 void* data, Evas_Object* webview, void* eventInfo)
628 // start to update render buffer!
629 AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
630 This->m_boxRenderBuffer->startCanvasUpdate();