X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2FPlugin%2FAppBoxPlugin%2FAppBoxRenderView.cpp;h=f609963874b5fdb4e8f138f04d02580cdb4f7f64;hb=d7ea8d5593d575f1dadfa77a363ca98d5e3787f9;hp=e9a2066a9e21129b0eb6fdfb8a88f7ca77c67aec;hpb=0e2f26b1b437235415c6ac30ebe2907031effed1;p=platform%2Fframework%2Fweb%2Fweb-provider.git diff --git a/src/Plugin/AppBoxPlugin/AppBoxRenderView.cpp b/src/Plugin/AppBoxPlugin/AppBoxRenderView.cpp old mode 100644 new mode 100755 index e9a2066..f609963 --- a/src/Plugin/AppBoxPlugin/AppBoxRenderView.cpp +++ b/src/Plugin/AppBoxPlugin/AppBoxRenderView.cpp @@ -1,11 +1,11 @@ /* * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved * - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Flora License, Version 1.1 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://floralicense.org/license/ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,37 +18,54 @@ * @author Yunchan Cho (yunchan.cho@samsung.com) */ #include +#include +#include #include #include #include +#include +#include +#include +#include #include #include #include #include +#include #include #include #include +#include #include #include "AppBoxObserver.h" #include "AppBoxRenderBuffer.h" +#include "AppBoxPdHelper.h" #include "AppBoxRenderView.h" -#define RENDER_MAX_TIME 10.0 +#define RENDER_MAX_TIME 30.0 +#define SNAPSHOT_REMOVE_TIME 1.0 + +// injection javascript file regarding creating js object used by box and pd +static const std::string injectionFile("/usr/share/web-provider/injection.js"); AppBoxRenderView::AppBoxRenderView( std::string boxId, std::string instanceId, - Evas_Object* boxWin, EwkContextPtr ewkContext) + EwkContextPtr ewkContext) : m_appId() , m_boxId(boxId) , m_instanceId(instanceId) - , m_boxWin(boxWin) - , m_baseWebView() - , m_renderInfo() - , m_view() - , m_startUrl() + , m_ewkContext(ewkContext) + , m_boxRenderInfo() + , m_boxWrt() + , m_pdWrt() + , m_snapshot() , m_fireRenderTimer() + , m_removeSnapShotTimer() , m_pdHelper() - , m_ewkContext(ewkContext) + , m_boxRenderBuffer() + , m_pdFastOpen(false) + , m_boxFinishLoad(false) + , m_boxWrt_isSuspended(false) { LogD("enter"); m_appId = getAppId(m_boxId); @@ -56,103 +73,155 @@ AppBoxRenderView::AppBoxRenderView( throw; //exception throw! } - evas_object_show(m_boxWin); - m_renderBuffer = AppBoxObserver::Instance()->getRenderBuffer(m_instanceId); + m_boxRenderBuffer = AppBoxObserver::Instance()->getRenderBuffer(m_instanceId); + + // use fastopen to default + // m_pdFastOpen = web_provider_livebox_get_pd_fast_open(m_boxId.c_str()) ? true : false; + m_pdFastOpen = true; AppBoxObserver::Instance()->registerRenderView(m_instanceId, this); } AppBoxRenderView::~AppBoxRenderView() { LogD("enter"); - evas_object_hide(m_boxWin); AppBoxObserver::Instance()->unregisterRenderView(m_instanceId); } -void AppBoxRenderView::showBox(RenderInfoPtr renderInfo) +void AppBoxRenderView::showBox(RenderInfoPtr boxRenderInfo) { LogD("enter"); + // stop updating render buffer + m_boxRenderBuffer->stopCanvasUpdate(); + + // clear snapshot if this is not the case of pd open + if (!m_pdHelper) { + clearSnapShot(); + } + // delete already running timer - deleteRenderTimer(); + deleteTimer(&m_fireRenderTimer); - // stop touch timer - if (livebox_service_mouse_event(m_boxId.c_str())) { - m_renderBuffer->deleteTouchTimer(); + // delete touch timer + if (web_provider_livebox_get_mouse_event(m_boxId.c_str())) { + m_boxRenderBuffer->deleteTouchTimer(); } - // copy to url - m_startUrl = getStartUrl(URL_TYPE_BOX, renderInfo->defaultUrlParams); + // set boxFinishLoad to false + m_boxFinishLoad = false; - if (!createView()) { - LogD("can't create view instance"); - return; + // copy to url + std::string boxStartUrl = getStartUrl(URL_TYPE_BOX, boxRenderInfo->defaultUrlParams); + if (m_boxWrt) { + LogD("existing wrt core is removed"); + destroyBoxWrtCore(); } + m_boxWrt = createWrtCore( + URL_TYPE_BOX, boxStartUrl, + boxRenderInfo->window, m_ewkContext); + m_boxWrt_isSuspended = false; + // in case of showing box by request of pd open if (m_pdHelper) { - m_pdHelper->setBaseWebView(m_baseWebView); + m_pdHelper->setBoxWebView(m_boxWrt->GetCurrentWebview()); } // resize webview fitted to width, height of Box evas_object_resize( - m_baseWebView, - renderInfo->width, - renderInfo->height); + m_boxWrt->GetCurrentWebview(), + boxRenderInfo->width, + boxRenderInfo->height); + - m_view->Show(); - m_renderInfo = renderInfo; + evas_object_show(boxRenderInfo->window); + m_boxWrt->Show(); + m_boxRenderInfo = boxRenderInfo; } -bool AppBoxRenderView::createView() +AppBoxRenderView::WrtCorePtr AppBoxRenderView::createWrtCore( + UrlType type, std::string& startUrl, + Evas_Object* win, EwkContextPtr ewkContext) { LogD("enter"); - if (m_view) { - m_view->Hide(); - m_view.reset(); - m_baseWebView = NULL; - } - - m_view = WRT::CoreModuleSingleton:: + WrtCorePtr wrt; + wrt = WRT::CoreModuleSingleton:: Instance().getRunnableWidgetObject(m_appId); - // prepare webview - if (m_startUrl.empty()) { + if (startUrl.empty()) { LogD("no start url"); - return false; + return WrtCorePtr(); } - m_view->PrepareView(m_startUrl, m_boxWin, m_ewkContext.get()); - m_view->CheckBeforeLaunch(); + wrt->PrepareView(startUrl, win, ewkContext.get()); + wrt->CheckBeforeLaunch(); // set callback functions of RunnableWidgetObject WRT::UserDelegatesPtr cbs(new WRT::UserDelegates); cbs->loadStart = DPL::MakeDelegate(this, &AppBoxRenderView::startLoadCallback); - cbs->loadFinish = DPL::MakeDelegate(this, &AppBoxRenderView::finishLoadCallback); + if (type == URL_TYPE_BOX) { + cbs->loadFinish = DPL::MakeDelegate(this, &AppBoxRenderView::finishBoxLoadCallback); + } else { + cbs->loadFinish = DPL::MakeDelegate(this, &AppBoxRenderView::finishPdLoadCallback); + } + cbs->bufferSet = DPL::MakeDelegate(this, &AppBoxRenderView::setBufferCallback); cbs->bufferUnset = DPL::MakeDelegate(this, &AppBoxRenderView::unsetBufferCallback); - cbs->windowCreateBefore = DPL::MakeDelegate(this, &AppBoxRenderView::createWindowBeforeCallback); - cbs->windowCreateAfter = DPL::MakeDelegate(this, &AppBoxRenderView::createWindowAfterCallback); - m_view->SetUserDelegates(cbs); + if (!m_pdFastOpen) { + cbs->windowCreateBefore = + DPL::MakeDelegate(this, &AppBoxRenderView::createWindowBeforeCallback); + cbs->windowCreateAfter = + DPL::MakeDelegate(this, &AppBoxRenderView::createWindowAfterCallback); + } - // set base webview - m_baseWebView = m_view->GetCurrentWebview(); - m_renderBuffer->startCanvasUpdate(); - return true; + cbs->navigationDecide = + DPL::MakeDelegate(this, &AppBoxRenderView::decideNavigationCallback); + cbs->webCrash = DPL::MakeDelegate(this, &AppBoxRenderView::crashWebProcessCallback); + wrt->SetUserDelegates(cbs); + + // set basic webview setting + setWebViewBasicSetting(wrt->GetCurrentWebview()); + return wrt; +} + +void AppBoxRenderView::destroyBoxWrtCore() +{ + LogD("enter"); + + m_boxRenderBuffer->stopCanvasUpdate(); + deleteTimer(&m_fireRenderTimer); + deleteTimer(&m_removeSnapShotTimer); + destroyWrtCore(m_boxWrt); + m_boxWrt.reset(); + + // temp + m_boxWrt_isSuspended = false; } -bool AppBoxRenderView::destroyView() +void AppBoxRenderView::destroyPdWrtCore() { LogD("enter"); - m_renderBuffer->stopCanvasUpdate(); - ecore_idler_add(destroyViewIdlerCallback, this); - return true; + destroyWrtCore(m_pdWrt); + m_pdWrt.reset(); +} + +void AppBoxRenderView::destroyWrtCore(WrtCorePtr wrt) +{ + LogD("enter"); + + if (wrt) { + wrt->Hide(); + } } void AppBoxRenderView::hideBox() { LogD("enter"); - destroyView(); + destroyBoxWrtCore(); + if (m_boxRenderInfo->window) { + evas_object_hide(m_boxRenderInfo->window); + } } void AppBoxRenderView::pauseBox() @@ -165,41 +234,90 @@ void AppBoxRenderView::resumeBox() LogD("enter"); } -void AppBoxRenderView::showPd(Evas_Object* pdWin, RenderInfoPtr renderInfo) +void AppBoxRenderView::showPd(RenderInfoPtr pdRenderInfo, RenderInfoPtr boxRenderInfo) { LogD("enter"); - // create pd helper - std::string pdStartUrl = getStartUrl(URL_TYPE_PD, renderInfo->defaultUrlParams); - m_pdHelper = PdHelper::create(pdWin, pdStartUrl, renderInfo); + std::string pdStartUrl = getStartUrl(URL_TYPE_PD, pdRenderInfo->defaultUrlParams); + if (m_pdFastOpen) { + destroyPdWrtCore(); + // if you want to launch new Web Process for PD, use the following line. + // EwkContextPtr pdContext = AppBoxObserver::Instance()->getPdEwkContext(); + m_pdWrt = createWrtCore(URL_TYPE_PD, pdStartUrl, pdRenderInfo->window, m_ewkContext); + if (!m_pdWrt) { + LogD("no wrt core instance"); + return; + } + m_pdHelper = AppBoxPdHelper::create(pdRenderInfo->window); + + // resize webview fitted to width, height of pd + evas_object_resize( + m_pdWrt->GetCurrentWebview(), + pdRenderInfo->width, + pdRenderInfo->height); + // show pd + m_pdWrt->Show(); + m_pdHelper->finishOpen(m_pdWrt->GetCurrentWebview()); + } else { + m_pdHelper = PdHelper::create(pdRenderInfo, pdStartUrl); + } // show pd window - evas_object_show(pdWin); - showBox(m_renderInfo); + evas_object_show(pdRenderInfo->window); + + // show box + showBox(boxRenderInfo); + + // start timer for clearing existing snapshot in case of only pd open + addTimer(&m_removeSnapShotTimer, SNAPSHOT_REMOVE_TIME, removeSnapShotTimerCallback); + } void AppBoxRenderView::hidePd() { LogD("enter"); + if (m_pdFastOpen) { + destroyPdWrtCore(); + } m_pdHelper->close(); m_pdHelper.reset(); - // destory box webview to stop rendering - destroyView(); + // stop box webview + stopRenderBox(); +} + +Evas_Object* AppBoxRenderView::getBoxWebView() +{ + if (!m_pdHelper) { + return m_boxWrt->GetCurrentWebview(); + } else { + // Here, we can't use GetCurrentWebView() of wrt-core to get Box' webview, + // because in the non fast-open, GetCurrentWebview() returns PD's webview. + return m_pdHelper->getBoxWebView(); + } +} + +Evas_Object* AppBoxRenderView::getPdWebView() +{ + if (!m_pdHelper) { + return NULL; + } + + return m_pdHelper->getPdWebView(); } std::string AppBoxRenderView::getAppId(std::string& boxId) { - // TODO more exact and safe parsing is needed - std::string temp = std::string(boxId); - int found = temp.find_last_of("."); - if (found == std::string::npos) { + LogD("enter"); + + const char* appId = web_provider_livebox_get_app_id(boxId.c_str()); + if (!appId) { + LogD("no appid of %s", boxId.c_str()); return std::string(); } - temp.assign(temp, 0, found); - return temp; + return std::string(appId); } std::string AppBoxRenderView::getStartUrl(UrlType type, std::string& defaultParams) @@ -222,82 +340,205 @@ std::string AppBoxRenderView::getStartUrl(UrlType type, std::string& defaultPara return url; } -void AppBoxRenderView::addRenderTimer() +Evas_Object* AppBoxRenderView::getCurrentSnapShot() +{ + LogD("enter"); + clearSnapShot(); + m_snapshot = m_boxRenderBuffer->getSnapshot(); + + return m_snapshot; +} + +void AppBoxRenderView::clearSnapShot() { LogD("enter"); - if (m_fireRenderTimer) { - deleteRenderTimer(); + if (m_snapshot) { + evas_object_del(m_snapshot); + m_snapshot = NULL; } +} - m_fireRenderTimer = ecore_timer_add( - RENDER_MAX_TIME, - fireRenderTimerCallback, - this); +void AppBoxRenderView::showSnapShot() +{ + LogD("enter"); + if (m_snapshot) { + evas_object_raise(m_snapshot); + evas_object_show(m_snapshot); + } } -void AppBoxRenderView::deleteRenderTimer() +void AppBoxRenderView::hideSnapShot() { LogD("enter"); - if (m_fireRenderTimer) { - ecore_timer_del(m_fireRenderTimer); - m_fireRenderTimer = NULL; + if (m_snapshot) { + evas_object_hide(m_snapshot); + evas_object_lower(m_snapshot); } } -Eina_Bool AppBoxRenderView::fireRenderTimerCallback(void* data) +void AppBoxRenderView::addTimer(Ecore_Timer** timer, double interval, Ecore_Task_Cb callback) { LogD("enter"); + if (*timer) { + deleteTimer(timer); + } - AppBoxRenderView* This = static_cast(data); - This->m_fireRenderTimer = NULL; - - This->m_renderBuffer->stopCanvasUpdate(); - if (livebox_service_mouse_event(This->m_boxId.c_str())) { + *timer = ecore_timer_add(interval, callback, this); +} + +void AppBoxRenderView::deleteTimer(Ecore_Timer** timer) +{ + LogD("enter"); + if (*timer) { + ecore_timer_del(*timer); + *timer = NULL; + } +} + +void AppBoxRenderView::stopRenderBox() +{ + deleteTimer(&m_fireRenderTimer); + m_boxRenderBuffer->stopCanvasUpdate(); + if (web_provider_livebox_get_mouse_event(m_boxId.c_str())) { // stop touch timer - This->m_renderBuffer->deleteTouchTimer(); - This->m_view->Suspend(); + m_boxRenderBuffer->deleteTouchTimer(); + + // temp condition + if (m_boxWrt_isSuspended == false) + { + m_boxWrt_isSuspended = true; + m_boxWrt->Suspend(); + } } else { - // webview should be removed - ecore_idler_add(destroyViewIdlerCallback, This); + // Before webview should be removed, + // new evas object with last render data should be created + // otherwise, after webview is removed, box is white screen. + evas_object_show(getCurrentSnapShot()); + destroyBoxWrtCore(); } +} + +void AppBoxRenderView::setWebViewBasicSetting(Evas_Object* webview) +{ + LogD("enter"); + + if (!webview) { + return; + } + Ewk_Settings* setting = ewk_view_settings_get(webview); + // To support transparent background + evas_object_color_set(webview, 0, 0, 0, 1); + ewk_view_visibility_set(webview, EINA_TRUE); + + // To know starting point for updating buffer + evas_object_smart_callback_add( + webview, + "load,nonemptylayout,finished", + loadNonEmptyLayoutFinishedCallback, + this); + evas_object_smart_callback_add( + webview, + "frame,rendered", + frameRenderedCallback, + this); +} + +Eina_Bool AppBoxRenderView::fireRenderTimerCallback(void* data) +{ + LogD("enter"); + + AppBoxRenderView* This = static_cast(data); + This->m_fireRenderTimer = NULL; + This->stopRenderBox(); return ECORE_CALLBACK_CANCEL; } -Eina_Bool AppBoxRenderView::destroyViewIdlerCallback(void* data) +Eina_Bool AppBoxRenderView::removeSnapShotTimerCallback(void* data) { LogD("enter"); AppBoxRenderView* This = static_cast(data); - if (This->m_view) { - This->m_view->Hide(); - This->m_view.reset(); - This->m_baseWebView = NULL; + if (!(This->m_boxFinishLoad)) { + return ECORE_CALLBACK_RENEW; } + // hide snapshot because valid frame has been prepared generally. + This->clearSnapShot(); + + This->m_removeSnapShotTimer = NULL; + return ECORE_CALLBACK_CANCEL; +} + +Eina_Bool AppBoxRenderView::openPdIdlerCallback(void* data) +{ + LogD("enter"); + AppBoxRenderView* This = static_cast(data); + if (This && This->m_pdHelper) { + This->m_pdHelper->startOpen(); + } return ECORE_CALLBACK_CANCEL; } +void AppBoxRenderView::executeScriptCallback( + Evas_Object* webview, const char* result, void* data) +{ + LogD("enter"); + + std::string resultStr(result ? result : "null"); + LogD("result: %s", resultStr.c_str()); +} + void AppBoxRenderView::startLoadCallback(Evas_Object* webview) { - // start load + LogD("enter"); + if(!webview) { + return; + } + // execute injection for creating js objects + std::ifstream jsFile(injectionFile); + std::string script((std::istreambuf_iterator(jsFile)), + std::istreambuf_iterator()); + + LogD("injected js code: %s", script.c_str()); + ewk_view_script_execute(webview, script.c_str(), executeScriptCallback, this); } -void AppBoxRenderView::finishLoadCallback(Evas_Object* webview) +void AppBoxRenderView::finishBoxLoadCallback(Evas_Object* webview) { LogD("enter"); + if (!webview) { + return; + } + ewk_view_visibility_set(webview, EINA_TRUE); if (!m_pdHelper) { // start render timer - addRenderTimer(); + addTimer(&m_fireRenderTimer, RENDER_MAX_TIME, fireRenderTimerCallback); } else { - if (!(m_pdHelper->isPdOpened()) && - webview == m_pdHelper->getBaseWebView()) - { - m_pdHelper->startOpen(); + if (!m_pdFastOpen) { + if (!(m_pdHelper->isPdOpened()) && + webview == m_pdHelper->getBoxWebView()) + { + // open pd + ecore_idler_add(openPdIdlerCallback, this); + } } } + + // set flag + m_boxFinishLoad = true; +} + +void AppBoxRenderView::finishPdLoadCallback(Evas_Object* webview) +{ + LogD("enter"); + if (!webview) { + return; + } + + ewk_view_visibility_set(webview, EINA_TRUE); } void AppBoxRenderView::createWindowBeforeCallback(Evas** canvas, Evas_Object* parent) @@ -306,13 +547,13 @@ void AppBoxRenderView::createWindowBeforeCallback(Evas** canvas, Evas_Object* pa if (m_pdHelper) { if (!(m_pdHelper->isPdOpened()) && - parent == m_pdHelper->getBaseWebView()) + parent == m_pdHelper->getBoxWebView()) { LogD("pd canvas is used"); *canvas = m_pdHelper->getPdCanvas(); return; } - } + } LogD("canvas of this webview is used"); *canvas = evas_object_evas_get(parent); @@ -321,17 +562,25 @@ void AppBoxRenderView::createWindowBeforeCallback(Evas** canvas, Evas_Object* pa void AppBoxRenderView::createWindowAfterCallback(Evas_Object* parent, Evas_Object* child) { LogD("enter"); + if (!parent) { + return; + } if (m_pdHelper) { Evas* parentCanvas = evas_object_evas_get(parent); Evas* childCanvas = evas_object_evas_get(child); if (parentCanvas != childCanvas) { + // wrt-core change visibility value to false internally + // So plugin should reset this value to true for painting parent webview + ewk_view_visibility_set(parent, EINA_TRUE); evas_object_show(parent); - evas_object_show(child); m_pdHelper->finishOpen(child); } } + + setWebViewBasicSetting(child); + evas_object_show(child); } void AppBoxRenderView::setBufferCallback(Evas_Object* webview) @@ -346,3 +595,37 @@ void AppBoxRenderView::unsetBufferCallback(Evas_Object* webview) LogD("enter"); evas_object_hide(webview); } + +void AppBoxRenderView::decideNavigationCallback(Evas_Object* webview, std::string& uri) +{ + LogD("enter"); + + // navigation of box scheme should be ignored + if(BoxSchemeHandler::Instance()->isBoxScheme(uri)) { + LogD("box scheme"); + BoxSchemeHandler::Instance()->process(m_instanceId, uri); + } +} + +void AppBoxRenderView::crashWebProcessCallback() +{ + LogD("enter"); + ewk_shutdown(); + elm_exit(); +} + +void AppBoxRenderView::loadNonEmptyLayoutFinishedCallback( + void* data, Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); +} + +void AppBoxRenderView::frameRenderedCallback( + void* data, Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + + // start to update render buffer! + AppBoxRenderView* This = static_cast(data); + This->m_boxRenderBuffer->startCanvasUpdate(); +}