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)
27 #include <ewk_context.h>
28 #include <livebox-service.h>
29 #include <i_runnable_widget_object.h>
30 #include <core_module.h>
31 #include <dpl/fast_delegate.h>
32 #include <Core/BoxSchemeHandler.h>
33 #include <Core/View/IRenderView.h>
34 #include <Core/View/IPdHelper.h>
35 #include <Core/View/PdHelper.h>
36 #include <API/web_provider_livebox_info.h>
37 #include <Core/Util/Log.h>
38 #include "AppBoxObserver.h"
39 #include "AppBoxRenderBuffer.h"
40 #include "AppBoxPdHelper.h"
41 #include "AppBoxRenderView.h"
43 #define RENDER_MAX_TIME 10.0
45 // injection javascript file regarding creating js object used by box and pd
46 static const std::string injectionFile("/usr/share/web-provider/injection.js");
48 AppBoxRenderView::AppBoxRenderView(
49 std::string boxId, std::string instanceId,
50 Evas_Object* boxWin, EwkContextPtr ewkContext)
53 , m_instanceId(instanceId)
58 , m_boxWrt_isSuspended(false)
63 , m_ewkContext(ewkContext)
67 m_appId = getAppId(m_boxId);
68 if (m_appId.empty()) {
69 throw; //exception throw!
72 evas_object_show(m_boxWin);
73 m_renderBuffer = AppBoxObserver::Instance()->getRenderBuffer(m_instanceId);
74 m_pdFastOpen = web_provider_livebox_get_pd_fast_open(m_boxId.c_str()) ? true : false;
75 AppBoxObserver::Instance()->registerRenderView(m_instanceId, this);
78 AppBoxRenderView::~AppBoxRenderView()
82 evas_object_hide(m_boxWin);
84 AppBoxObserver::Instance()->unregisterRenderView(m_instanceId);
87 void AppBoxRenderView::showBox(RenderInfoPtr renderInfo)
91 // stop updating render buffer
92 m_renderBuffer->stopCanvasUpdate();
95 // delete already running timer
99 if (web_provider_livebox_get_mouse_event(m_boxId.c_str())) {
100 m_renderBuffer->deleteTouchTimer();
104 std::string boxStartUrl = getStartUrl(URL_TYPE_BOX, renderInfo->defaultUrlParams);
106 LogD("existing wrt core is removed");
110 m_boxWrt = createWrtCore(boxStartUrl, m_boxWin, m_ewkContext);
111 m_boxWrt_isSuspended = false;
113 // in case of showing box by request of pd open
115 m_pdHelper->setBoxWebView(m_boxWrt->GetCurrentWebview());
118 // resize webview fitted to width, height of Box
120 m_boxWrt->GetCurrentWebview(),
125 m_renderInfo = renderInfo;
128 AppBoxRenderView::WrtCorePtr AppBoxRenderView::createWrtCore(
129 std::string& startUrl, Evas_Object* win, EwkContextPtr ewkContext)
134 #ifdef MULTIPROCESS_SERVICE_SUPPORT
135 wrt = WRT::CoreModuleSingleton::
136 Instance().getRunnableWidgetObject(m_appId, DPL::Optional<unsigned>());
138 wrt = WRT::CoreModuleSingleton::
139 Instance().getRunnableWidgetObject(m_appId);
142 if (startUrl.empty()) {
143 LogD("no start url");
146 wrt->PrepareView(startUrl, win, ewkContext.get());
147 wrt->CheckBeforeLaunch();
149 // set callback functions of RunnableWidgetObject
150 WRT::UserDelegatesPtr cbs(new WRT::UserDelegates);
151 cbs->loadStart = DPL::MakeDelegate(this, &AppBoxRenderView::startLoadCallback);
152 cbs->loadFinish = DPL::MakeDelegate(this, &AppBoxRenderView::finishLoadCallback);
153 cbs->bufferSet = DPL::MakeDelegate(this, &AppBoxRenderView::setBufferCallback);
154 cbs->bufferUnset = DPL::MakeDelegate(this, &AppBoxRenderView::unsetBufferCallback);
156 cbs->windowCreateBefore =
157 DPL::MakeDelegate(this, &AppBoxRenderView::createWindowBeforeCallback);
158 cbs->windowCreateAfter =
159 DPL::MakeDelegate(this, &AppBoxRenderView::createWindowAfterCallback);
162 cbs->navigationDecide =
163 DPL::MakeDelegate(this, &AppBoxRenderView::decideNavigationCallback);
164 cbs->webCrash = DPL::MakeDelegate(this, &AppBoxRenderView::crashWebProcessCallback);
165 wrt->SetUserDelegates(cbs);
167 // To support transparent background
168 evas_object_color_set(wrt->GetCurrentWebview(), 0, 0, 0, 0);
169 //evas_object_layer_set(wrt->GetCurrentWebview(), EVAS_LAYER_MAX);
171 // To know starting point for updating buffer
172 evas_object_smart_callback_add(
173 wrt->GetCurrentWebview(),
174 "load,nonemptylayout,finished",
176 loadNonEmptyLayoutFinishedCallback,
182 void AppBoxRenderView::destroyBoxWrtCore()
186 m_renderBuffer->stopCanvasUpdate();
188 destroyWrtCore(m_boxWrt);
191 m_boxWrt_isSuspended = false;
194 void AppBoxRenderView::destroyPdWrtCore()
198 destroyWrtCore(m_pdWrt);
202 void AppBoxRenderView::destroyWrtCore(WrtCorePtr wrt)
211 void AppBoxRenderView::hideBox()
217 void AppBoxRenderView::pauseBox()
222 void AppBoxRenderView::resumeBox()
227 void AppBoxRenderView::showPd(Evas_Object* pdWin, RenderInfoPtr renderInfo)
232 std::string pdStartUrl = getStartUrl(URL_TYPE_PD, renderInfo->defaultUrlParams);
235 // if needed, last param regarding ewk context can be set to new one.
236 m_pdWrt = createWrtCore(pdStartUrl, pdWin, m_ewkContext);
238 LogD("no wrt core instance");
241 m_pdHelper = AppBoxPdHelper::create(pdWin);
243 // resize webview fitted to width, height of pd
245 m_pdWrt->GetCurrentWebview(),
250 m_pdHelper->finishOpen(m_pdWrt->GetCurrentWebview());
252 m_pdHelper = PdHelper::create(pdWin, pdStartUrl, renderInfo);
256 evas_object_show(pdWin);
257 showBox(m_renderInfo);
260 void AppBoxRenderView::hidePd()
270 // stop box webview after render timer
274 Evas_Object* AppBoxRenderView::getBoxWebView()
277 return m_boxWrt->GetCurrentWebview();
279 // Here, we can't use GetCurrentWebView() of wrt-core to get Box' webview,
280 // because in the non fast-open, GetCurrentWebview() returns PD's webview.
281 return m_pdHelper->getBoxWebView();
285 Evas_Object* AppBoxRenderView::getPdWebView()
291 return m_pdHelper->getPdWebView();
294 std::string AppBoxRenderView::getAppId(std::string& boxId)
298 const char* appId = web_provider_livebox_get_app_id(boxId.c_str());
300 LogD("no appid of %s", boxId.c_str());
301 return std::string();
304 return std::string(appId);
307 std::string AppBoxRenderView::getStartUrl(UrlType type, std::string& defaultParams)
312 url = livebox_service_lb_script_path(m_boxId.c_str());
315 url = livebox_service_pd_script_path(m_boxId.c_str());
318 LogD("no available type");
321 // add default parameters to start url
322 url += defaultParams;
327 Evas_Object* AppBoxRenderView::getCurrentSnapShot()
331 m_snapshot = m_renderBuffer->getSnapshot();
332 //evas_object_layer_set(m_snapshot, EVAS_LAYER_MAX);
337 void AppBoxRenderView::clearSnapShot()
341 //evas_object_layer_set(m_snapshot, EVAS_LAYER_MIN);
342 evas_object_del(m_snapshot);
347 void AppBoxRenderView::addRenderTimer()
350 if (m_fireRenderTimer) {
354 m_fireRenderTimer = ecore_timer_add(
356 fireRenderTimerCallback,
360 void AppBoxRenderView::deleteRenderTimer()
363 if (m_fireRenderTimer) {
364 ecore_timer_del(m_fireRenderTimer);
365 m_fireRenderTimer = NULL;
369 Eina_Bool AppBoxRenderView::fireRenderTimerCallback(void* data)
373 AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
374 This->m_fireRenderTimer = NULL;
376 This->m_renderBuffer->stopCanvasUpdate();
377 if (web_provider_livebox_get_mouse_event(This->m_boxId.c_str())) {
379 This->m_renderBuffer->deleteTouchTimer();
382 if (This->m_boxWrt_isSuspended == false)
384 This->m_boxWrt_isSuspended = true;
385 This->m_boxWrt->Suspend();
388 // Before webview should be removed,
389 // new evas object with last render data should be created
390 // otherwise, after webview is removed, box is white screen.
391 evas_object_show(This->getCurrentSnapShot());
392 This->destroyBoxWrtCore();
395 return ECORE_CALLBACK_CANCEL;
398 Eina_Bool AppBoxRenderView::openPdIdlerCallback(void* data)
401 AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
402 if (This && This->m_pdHelper) {
403 This->m_pdHelper->startOpen();
405 return ECORE_CALLBACK_CANCEL;
408 void AppBoxRenderView::executeScriptCallback(
409 Evas_Object* webview, const char* result, void* data)
412 std::string resultStr(result ? result : "null");
413 LogD("result: %s", resultStr.c_str());
416 void AppBoxRenderView::startLoadCallback(Evas_Object* webview)
419 // execute injection for creating js objects
420 std::ifstream jsFile(injectionFile);
421 std::string script((std::istreambuf_iterator<char>(jsFile)),
422 std::istreambuf_iterator<char>());
424 LogD("injected js code: %s", script.c_str());
425 ewk_view_script_execute(webview, script.c_str(), executeScriptCallback, this);
428 void AppBoxRenderView::finishLoadCallback(Evas_Object* webview)
431 ewk_view_visibility_set(webview, EINA_TRUE);
434 // start render timer
438 if (!(m_pdHelper->isPdOpened()) &&
439 webview == m_pdHelper->getBoxWebView())
442 ecore_idler_add(openPdIdlerCallback, this);
448 void AppBoxRenderView::createWindowBeforeCallback(Evas** canvas, Evas_Object* parent)
453 if (!(m_pdHelper->isPdOpened()) &&
454 parent == m_pdHelper->getBoxWebView())
456 LogD("pd canvas is used");
457 *canvas = m_pdHelper->getPdCanvas();
462 LogD("canvas of this webview is used");
463 *canvas = evas_object_evas_get(parent);
466 void AppBoxRenderView::createWindowAfterCallback(Evas_Object* parent, Evas_Object* child)
470 // To support transparent background
471 evas_object_color_set(child, 0, 0, 0, 0);
474 Evas* parentCanvas = evas_object_evas_get(parent);
475 Evas* childCanvas = evas_object_evas_get(child);
477 if (parentCanvas != childCanvas) {
478 // wrt-core change visibility value to false internally
479 // So plugin should reset this value to true for painting parent webview
480 ewk_view_visibility_set(parent, EINA_TRUE);
481 evas_object_show(parent);
482 m_pdHelper->finishOpen(child);
486 ewk_view_visibility_set(child, EINA_TRUE);
487 evas_object_show(child);
490 void AppBoxRenderView::setBufferCallback(Evas_Object* webview)
493 evas_object_show(webview);
494 evas_object_focus_set(webview, EINA_TRUE);
497 void AppBoxRenderView::unsetBufferCallback(Evas_Object* webview)
500 evas_object_hide(webview);
503 void AppBoxRenderView::decideNavigationCallback(Evas_Object* webview, std::string& uri)
507 // navigation of box scheme should be ignored
508 if(BoxSchemeHandler::Instance()->isBoxScheme(uri)) {
510 BoxSchemeHandler::Instance()->process(m_instanceId, uri);
514 void AppBoxRenderView::crashWebProcessCallback()
521 void AppBoxRenderView::loadNonEmptyLayoutFinishedCallback(
522 void* data, Evas_Object* webview, void* eventInfo)
526 // start to update render buffer!
527 AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
528 This->m_renderBuffer->startCanvasUpdate();