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);
75 // use fastopen to default
76 // m_pdFastOpen = web_provider_livebox_get_pd_fast_open(m_boxId.c_str()) ? true : false;
78 AppBoxObserver::Instance()->registerRenderView(m_instanceId, this);
81 AppBoxRenderView::~AppBoxRenderView()
84 AppBoxObserver::Instance()->unregisterRenderView(m_instanceId);
87 void AppBoxRenderView::showBox(RenderInfoPtr boxRenderInfo)
91 // stop updating render buffer
92 m_boxRenderBuffer->stopCanvasUpdate();
95 // delete already running timer
99 if (web_provider_livebox_get_mouse_event(m_boxId.c_str())) {
100 m_boxRenderBuffer->deleteTouchTimer();
104 std::string boxStartUrl = getStartUrl(URL_TYPE_BOX, boxRenderInfo->defaultUrlParams);
106 LogD("existing wrt core is removed");
110 m_boxWrt = createWrtCore(boxStartUrl, boxRenderInfo->window, 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(),
121 boxRenderInfo->width,
122 boxRenderInfo->height);
125 evas_object_show(boxRenderInfo->window);
127 m_boxRenderInfo = boxRenderInfo;
130 AppBoxRenderView::WrtCorePtr AppBoxRenderView::createWrtCore(
131 std::string& startUrl, Evas_Object* win, EwkContextPtr ewkContext)
136 #ifdef MULTIPROCESS_SERVICE_SUPPORT
137 wrt = WRT::CoreModuleSingleton::
138 Instance().getRunnableWidgetObject(m_appId, DPL::Optional<unsigned>());
140 wrt = WRT::CoreModuleSingleton::
141 Instance().getRunnableWidgetObject(m_appId);
144 if (startUrl.empty()) {
145 LogD("no start url");
148 wrt->PrepareView(startUrl, win, ewkContext.get());
149 wrt->CheckBeforeLaunch();
151 // set callback functions of RunnableWidgetObject
152 WRT::UserDelegatesPtr cbs(new WRT::UserDelegates);
153 cbs->loadStart = DPL::MakeDelegate(this, &AppBoxRenderView::startLoadCallback);
154 cbs->loadFinish = DPL::MakeDelegate(this, &AppBoxRenderView::finishLoadCallback);
155 cbs->bufferSet = DPL::MakeDelegate(this, &AppBoxRenderView::setBufferCallback);
156 cbs->bufferUnset = DPL::MakeDelegate(this, &AppBoxRenderView::unsetBufferCallback);
158 cbs->windowCreateBefore =
159 DPL::MakeDelegate(this, &AppBoxRenderView::createWindowBeforeCallback);
160 cbs->windowCreateAfter =
161 DPL::MakeDelegate(this, &AppBoxRenderView::createWindowAfterCallback);
164 cbs->navigationDecide =
165 DPL::MakeDelegate(this, &AppBoxRenderView::decideNavigationCallback);
166 cbs->webCrash = DPL::MakeDelegate(this, &AppBoxRenderView::crashWebProcessCallback);
167 wrt->SetUserDelegates(cbs);
169 // set basic webview setting
170 setWebViewBasicSetting(wrt->GetCurrentWebview());
174 void AppBoxRenderView::destroyBoxWrtCore()
178 m_boxRenderBuffer->stopCanvasUpdate();
180 destroyWrtCore(m_boxWrt);
184 m_boxWrt_isSuspended = false;
187 void AppBoxRenderView::destroyPdWrtCore()
191 destroyWrtCore(m_pdWrt);
195 void AppBoxRenderView::destroyWrtCore(WrtCorePtr wrt)
204 void AppBoxRenderView::hideBox()
208 if (m_boxRenderInfo->window) {
209 evas_object_hide(m_boxRenderInfo->window);
213 void AppBoxRenderView::pauseBox()
218 void AppBoxRenderView::resumeBox()
223 void AppBoxRenderView::showPd(RenderInfoPtr pdRenderInfo, RenderInfoPtr boxRenderInfo)
228 std::string pdStartUrl = getStartUrl(URL_TYPE_PD, pdRenderInfo->defaultUrlParams);
231 // if needed, last param regarding ewk context can be set to new one.
232 m_pdWrt = createWrtCore(pdStartUrl, pdRenderInfo->window, m_ewkContext);
234 LogD("no wrt core instance");
237 m_pdHelper = AppBoxPdHelper::create(pdRenderInfo->window);
239 // resize webview fitted to width, height of pd
241 m_pdWrt->GetCurrentWebview(),
243 pdRenderInfo->height);
246 m_pdHelper->finishOpen(m_pdWrt->GetCurrentWebview());
248 m_pdHelper = PdHelper::create(pdRenderInfo, pdStartUrl);
252 evas_object_show(pdRenderInfo->window);
253 showBox(boxRenderInfo);
256 void AppBoxRenderView::hidePd()
270 Evas_Object* AppBoxRenderView::getBoxWebView()
273 return m_boxWrt->GetCurrentWebview();
275 // Here, we can't use GetCurrentWebView() of wrt-core to get Box' webview,
276 // because in the non fast-open, GetCurrentWebview() returns PD's webview.
277 return m_pdHelper->getBoxWebView();
281 Evas_Object* AppBoxRenderView::getPdWebView()
287 return m_pdHelper->getPdWebView();
290 std::string AppBoxRenderView::getAppId(std::string& boxId)
294 const char* appId = web_provider_livebox_get_app_id(boxId.c_str());
296 LogD("no appid of %s", boxId.c_str());
297 return std::string();
300 return std::string(appId);
303 std::string AppBoxRenderView::getStartUrl(UrlType type, std::string& defaultParams)
308 url = livebox_service_lb_script_path(m_boxId.c_str());
311 url = livebox_service_pd_script_path(m_boxId.c_str());
314 LogD("no available type");
317 // add default parameters to start url
318 url += defaultParams;
323 Evas_Object* AppBoxRenderView::getCurrentSnapShot()
327 m_snapshot = m_boxRenderBuffer->getSnapshot();
332 void AppBoxRenderView::clearSnapShot()
336 evas_object_del(m_snapshot);
341 void AppBoxRenderView::addRenderTimer()
344 if (m_fireRenderTimer) {
348 m_fireRenderTimer = ecore_timer_add(
350 fireRenderTimerCallback,
354 void AppBoxRenderView::deleteRenderTimer()
357 if (m_fireRenderTimer) {
358 ecore_timer_del(m_fireRenderTimer);
359 m_fireRenderTimer = NULL;
363 void AppBoxRenderView::stopRenderBox()
366 m_boxRenderBuffer->stopCanvasUpdate();
367 if (web_provider_livebox_get_mouse_event(m_boxId.c_str())) {
369 m_boxRenderBuffer->deleteTouchTimer();
372 if (m_boxWrt_isSuspended == false)
374 m_boxWrt_isSuspended = true;
378 // Before webview should be removed,
379 // new evas object with last render data should be created
380 // otherwise, after webview is removed, box is white screen.
381 evas_object_show(getCurrentSnapShot());
386 void AppBoxRenderView::setWebViewBasicSetting(Evas_Object* webview)
393 Ewk_Settings* setting = ewk_view_settings_get(webview);
394 // To support transparent background
395 evas_object_color_set(webview, 0, 0, 0, 1);
396 ewk_view_visibility_set(webview, EINA_TRUE);
398 // To know starting point for updating buffer
399 evas_object_smart_callback_add(
401 "load,nonemptylayout,finished",
402 loadNonEmptyLayoutFinishedCallback,
404 evas_object_smart_callback_add(
407 frameRenderedCallback,
411 Eina_Bool AppBoxRenderView::fireRenderTimerCallback(void* data)
415 AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
416 This->m_fireRenderTimer = NULL;
417 This->stopRenderBox();
419 return ECORE_CALLBACK_CANCEL;
422 Eina_Bool AppBoxRenderView::openPdIdlerCallback(void* data)
425 AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
426 if (This && This->m_pdHelper) {
427 This->m_pdHelper->startOpen();
429 return ECORE_CALLBACK_CANCEL;
432 void AppBoxRenderView::executeScriptCallback(
433 Evas_Object* webview, const char* result, void* data)
437 std::string resultStr(result ? result : "null");
438 LogD("result: %s", resultStr.c_str());
441 void AppBoxRenderView::startLoadCallback(Evas_Object* webview)
447 // execute injection for creating js objects
448 std::ifstream jsFile(injectionFile);
449 std::string script((std::istreambuf_iterator<char>(jsFile)),
450 std::istreambuf_iterator<char>());
452 LogD("injected js code: %s", script.c_str());
453 ewk_view_script_execute(webview, script.c_str(), executeScriptCallback, this);
456 void AppBoxRenderView::finishLoadCallback(Evas_Object* webview)
463 ewk_view_visibility_set(webview, EINA_TRUE);
466 // start render timer
470 if (!(m_pdHelper->isPdOpened()) &&
471 webview == m_pdHelper->getBoxWebView())
474 ecore_idler_add(openPdIdlerCallback, this);
480 void AppBoxRenderView::createWindowBeforeCallback(Evas** canvas, Evas_Object* parent)
485 if (!(m_pdHelper->isPdOpened()) &&
486 parent == m_pdHelper->getBoxWebView())
488 LogD("pd canvas is used");
489 *canvas = m_pdHelper->getPdCanvas();
494 LogD("canvas of this webview is used");
495 *canvas = evas_object_evas_get(parent);
498 void AppBoxRenderView::createWindowAfterCallback(Evas_Object* parent, Evas_Object* child)
506 Evas* parentCanvas = evas_object_evas_get(parent);
507 Evas* childCanvas = evas_object_evas_get(child);
509 if (parentCanvas != childCanvas) {
510 // wrt-core change visibility value to false internally
511 // So plugin should reset this value to true for painting parent webview
512 ewk_view_visibility_set(parent, EINA_TRUE);
513 evas_object_show(parent);
514 m_pdHelper->finishOpen(child);
518 setWebViewBasicSetting(child);
519 evas_object_show(child);
522 void AppBoxRenderView::setBufferCallback(Evas_Object* webview)
525 evas_object_show(webview);
526 evas_object_focus_set(webview, EINA_TRUE);
529 void AppBoxRenderView::unsetBufferCallback(Evas_Object* webview)
532 evas_object_hide(webview);
535 void AppBoxRenderView::decideNavigationCallback(Evas_Object* webview, std::string& uri)
539 // navigation of box scheme should be ignored
540 if(BoxSchemeHandler::Instance()->isBoxScheme(uri)) {
542 BoxSchemeHandler::Instance()->process(m_instanceId, uri);
546 void AppBoxRenderView::crashWebProcessCallback()
553 void AppBoxRenderView::loadNonEmptyLayoutFinishedCallback(
554 void* data, Evas_Object* webview, void* eventInfo)
559 void AppBoxRenderView::frameRenderedCallback(
560 void* data, Evas_Object* webview, void* eventInfo)
564 // start to update render buffer!
565 AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data);
566 This->m_boxRenderBuffer->startCanvasUpdate();