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
47 // injection javascript file regarding creating js object used by box and pd
48 static const std::string injectionFile("/usr/share/web-provider/injection.js");
50 AppBoxRenderView::AppBoxRenderView(
51 std::string boxId, std::string instanceId,
52 EwkContextPtr ewkContext)
55 , m_instanceId(instanceId)
56 , m_ewkContext(ewkContext)
65 , m_boxWrt_isSuspended(false)
68 m_appId = getAppId(m_boxId);
69 if (m_appId.empty()) {
70 throw; //exception throw!
73 m_boxRenderBuffer = 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()
81 AppBoxObserver::Instance()->unregisterRenderView(m_instanceId);
84 void AppBoxRenderView::showBox(RenderInfoPtr boxRenderInfo)
88 // stop updating render buffer
89 m_boxRenderBuffer->stopCanvasUpdate();
92 // delete already running timer
96 if (web_provider_livebox_get_mouse_event(m_boxId.c_str())) {
97 m_boxRenderBuffer->deleteTouchTimer();
101 std::string boxStartUrl = getStartUrl(URL_TYPE_BOX, boxRenderInfo->defaultUrlParams);
103 LogD("existing wrt core is removed");
107 m_boxWrt = createWrtCore(boxStartUrl, boxRenderInfo->window, m_ewkContext);
108 m_boxWrt_isSuspended = false;
110 // in case of showing box by request of pd open
112 m_pdHelper->setBoxWebView(m_boxWrt->GetCurrentWebview());
115 // resize webview fitted to width, height of Box
117 m_boxWrt->GetCurrentWebview(),
118 boxRenderInfo->width,
119 boxRenderInfo->height);
122 evas_object_show(boxRenderInfo->window);
124 m_boxRenderInfo = boxRenderInfo;
127 AppBoxRenderView::WrtCorePtr AppBoxRenderView::createWrtCore(
128 std::string& startUrl, Evas_Object* win, EwkContextPtr ewkContext)
133 #ifdef MULTIPROCESS_SERVICE_SUPPORT
134 wrt = WRT::CoreModuleSingleton::
135 Instance().getRunnableWidgetObject(m_appId, DPL::Optional<unsigned>());
137 wrt = WRT::CoreModuleSingleton::
138 Instance().getRunnableWidgetObject(m_appId);
141 if (startUrl.empty()) {
142 LogD("no start url");
145 wrt->PrepareView(startUrl, win, ewkContext.get());
146 wrt->CheckBeforeLaunch();
148 // set callback functions of RunnableWidgetObject
149 WRT::UserDelegatesPtr cbs(new WRT::UserDelegates);
150 cbs->loadStart = DPL::MakeDelegate(this, &AppBoxRenderView::startLoadCallback);
151 cbs->loadFinish = DPL::MakeDelegate(this, &AppBoxRenderView::finishLoadCallback);
152 cbs->bufferSet = DPL::MakeDelegate(this, &AppBoxRenderView::setBufferCallback);
153 cbs->bufferUnset = DPL::MakeDelegate(this, &AppBoxRenderView::unsetBufferCallback);
155 cbs->windowCreateBefore =
156 DPL::MakeDelegate(this, &AppBoxRenderView::createWindowBeforeCallback);
157 cbs->windowCreateAfter =
158 DPL::MakeDelegate(this, &AppBoxRenderView::createWindowAfterCallback);
161 cbs->navigationDecide =
162 DPL::MakeDelegate(this, &AppBoxRenderView::decideNavigationCallback);
163 cbs->webCrash = DPL::MakeDelegate(this, &AppBoxRenderView::crashWebProcessCallback);
164 wrt->SetUserDelegates(cbs);
166 // set basic webview setting
167 setWebViewBasicSetting(wrt->GetCurrentWebview());
171 void AppBoxRenderView::destroyBoxWrtCore()
175 m_boxRenderBuffer->stopCanvasUpdate();
177 destroyWrtCore(m_boxWrt);
181 m_boxWrt_isSuspended = false;
184 void AppBoxRenderView::destroyPdWrtCore()
188 destroyWrtCore(m_pdWrt);
192 void AppBoxRenderView::destroyWrtCore(WrtCorePtr wrt)
201 void AppBoxRenderView::hideBox()
205 if (m_boxRenderInfo->window) {
206 evas_object_hide(m_boxRenderInfo->window);
210 void AppBoxRenderView::pauseBox()
215 void AppBoxRenderView::resumeBox()
220 void AppBoxRenderView::showPd(RenderInfoPtr pdRenderInfo, RenderInfoPtr boxRenderInfo)
225 std::string pdStartUrl = getStartUrl(URL_TYPE_PD, pdRenderInfo->defaultUrlParams);
228 // if needed, last param regarding ewk context can be set to new one.
229 m_pdWrt = createWrtCore(pdStartUrl, pdRenderInfo->window, m_ewkContext);
231 LogD("no wrt core instance");
234 m_pdHelper = AppBoxPdHelper::create(pdRenderInfo->window);
236 // resize webview fitted to width, height of pd
238 m_pdWrt->GetCurrentWebview(),
240 pdRenderInfo->height);
243 m_pdHelper->finishOpen(m_pdWrt->GetCurrentWebview());
245 m_pdHelper = PdHelper::create(pdRenderInfo, pdStartUrl);
249 evas_object_show(pdRenderInfo->window);
250 showBox(boxRenderInfo);
253 void AppBoxRenderView::hidePd()
267 Evas_Object* AppBoxRenderView::getBoxWebView()
270 return m_boxWrt->GetCurrentWebview();
272 // Here, we can't use GetCurrentWebView() of wrt-core to get Box' webview,
273 // because in the non fast-open, GetCurrentWebview() returns PD's webview.
274 return m_pdHelper->getBoxWebView();
278 Evas_Object* AppBoxRenderView::getPdWebView()
284 return m_pdHelper->getPdWebView();
287 std::string AppBoxRenderView::getAppId(std::string& boxId)
291 const char* appId = web_provider_livebox_get_app_id(boxId.c_str());
293 LogD("no appid of %s", boxId.c_str());
294 return std::string();
297 return std::string(appId);
300 std::string AppBoxRenderView::getStartUrl(UrlType type, std::string& defaultParams)
305 url = livebox_service_lb_script_path(m_boxId.c_str());
308 url = livebox_service_pd_script_path(m_boxId.c_str());
311 LogD("no available type");
314 // add default parameters to start url
315 url += defaultParams;
320 Evas_Object* AppBoxRenderView::getCurrentSnapShot()
324 m_snapshot = m_boxRenderBuffer->getSnapshot();
329 void AppBoxRenderView::clearSnapShot()
333 evas_object_del(m_snapshot);
338 void AppBoxRenderView::addRenderTimer()
341 if (m_fireRenderTimer) {
345 m_fireRenderTimer = ecore_timer_add(
347 fireRenderTimerCallback,
351 void AppBoxRenderView::deleteRenderTimer()
354 if (m_fireRenderTimer) {
355 ecore_timer_del(m_fireRenderTimer);
356 m_fireRenderTimer = NULL;
360 void AppBoxRenderView::stopRenderBox()
363 m_boxRenderBuffer->stopCanvasUpdate();
364 if (web_provider_livebox_get_mouse_event(m_boxId.c_str())) {
366 m_boxRenderBuffer->deleteTouchTimer();
369 if (m_boxWrt_isSuspended == false)
371 m_boxWrt_isSuspended = true;
375 // Before webview should be removed,
376 // new evas object with last render data should be created
377 // otherwise, after webview is removed, box is white screen.
378 evas_object_show(getCurrentSnapShot());
383 void AppBoxRenderView::setWebViewBasicSetting(Evas_Object* webview)
390 Ewk_Settings* setting = ewk_view_settings_get(webview);
391 // To support transparent background
392 evas_object_color_set(webview, 0, 0, 0, 1);
393 ewk_view_visibility_set(webview, EINA_TRUE);
395 // To know starting point for updating buffer
396 evas_object_smart_callback_add(
398 "load,nonemptylayout,finished",
399 loadNonEmptyLayoutFinishedCallback,
401 evas_object_smart_callback_add(
404 frameRenderedCallback,
408 Eina_Bool AppBoxRenderView::fireRenderTimerCallback(void* data)
412 AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
413 This->m_fireRenderTimer = NULL;
414 This->stopRenderBox();
416 return ECORE_CALLBACK_CANCEL;
419 Eina_Bool AppBoxRenderView::openPdIdlerCallback(void* data)
422 AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
423 if (This && This->m_pdHelper) {
424 This->m_pdHelper->startOpen();
426 return ECORE_CALLBACK_CANCEL;
429 void AppBoxRenderView::executeScriptCallback(
430 Evas_Object* webview, const char* result, void* data)
434 std::string resultStr(result ? result : "null");
435 LogD("result: %s", resultStr.c_str());
438 void AppBoxRenderView::startLoadCallback(Evas_Object* webview)
444 // execute injection for creating js objects
445 std::ifstream jsFile(injectionFile);
446 std::string script((std::istreambuf_iterator<char>(jsFile)),
447 std::istreambuf_iterator<char>());
449 LogD("injected js code: %s", script.c_str());
450 ewk_view_script_execute(webview, script.c_str(), executeScriptCallback, this);
453 void AppBoxRenderView::finishLoadCallback(Evas_Object* webview)
460 ewk_view_visibility_set(webview, EINA_TRUE);
463 // start render timer
467 if (!(m_pdHelper->isPdOpened()) &&
468 webview == m_pdHelper->getBoxWebView())
471 ecore_idler_add(openPdIdlerCallback, this);
477 void AppBoxRenderView::createWindowBeforeCallback(Evas** canvas, Evas_Object* parent)
482 if (!(m_pdHelper->isPdOpened()) &&
483 parent == m_pdHelper->getBoxWebView())
485 LogD("pd canvas is used");
486 *canvas = m_pdHelper->getPdCanvas();
491 LogD("canvas of this webview is used");
492 *canvas = evas_object_evas_get(parent);
495 void AppBoxRenderView::createWindowAfterCallback(Evas_Object* parent, Evas_Object* child)
503 Evas* parentCanvas = evas_object_evas_get(parent);
504 Evas* childCanvas = evas_object_evas_get(child);
506 if (parentCanvas != childCanvas) {
507 // wrt-core change visibility value to false internally
508 // So plugin should reset this value to true for painting parent webview
509 ewk_view_visibility_set(parent, EINA_TRUE);
510 evas_object_show(parent);
511 m_pdHelper->finishOpen(child);
515 setWebViewBasicSetting(child);
516 evas_object_show(child);
519 void AppBoxRenderView::setBufferCallback(Evas_Object* webview)
522 evas_object_show(webview);
523 evas_object_focus_set(webview, EINA_TRUE);
526 void AppBoxRenderView::unsetBufferCallback(Evas_Object* webview)
529 evas_object_hide(webview);
532 void AppBoxRenderView::decideNavigationCallback(Evas_Object* webview, std::string& uri)
536 // navigation of box scheme should be ignored
537 if(BoxSchemeHandler::Instance()->isBoxScheme(uri)) {
539 BoxSchemeHandler::Instance()->process(m_instanceId, uri);
543 void AppBoxRenderView::crashWebProcessCallback()
550 void AppBoxRenderView::loadNonEmptyLayoutFinishedCallback(
551 void* data, Evas_Object* webview, void* eventInfo)
556 void AppBoxRenderView::frameRenderedCallback(
557 void* data, Evas_Object* webview, void* eventInfo)
561 // start to update render buffer!
562 AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
563 This->m_boxRenderBuffer->startCanvasUpdate();