diff options
Diffstat (limited to 'src_wearable/Plugin')
17 files changed, 2127 insertions, 0 deletions
diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxManager.cpp b/src_wearable/Plugin/AppBoxPlugin/AppBoxManager.cpp new file mode 100755 index 0000000..ae41127 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxManager.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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://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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxManager.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <map> +#include <ail.h> +#include <ewk_context.h> +#include <core_module.h> +#include <Plugin/IBoxPluginFactory.h> +#include <Core/BoxData.h> +#include <Core/BoxManager.h> +#include <Core/IBox.h> +#include <Core/Util/Log.h> +#include <API/web_provider_livebox_info.h> +#include "AppBoxManager.h" + +static const std::string bundlePath("/usr/lib/libwrt-injected-bundle.so"); + +AppBoxManager::AppBoxManager(IBoxPluginFactoryPtr factory) + : BoxManager(factory) +{ + bool ret = WRT::CoreModuleSingleton::Instance().Init(); + if (!ret) { + throw; // throw exeception + } +} + +AppBoxManager::~AppBoxManager() +{ +} + +bool AppBoxManager::requestAddBox(BoxInfoPtr boxInfo, EwkContextPtr ewkContext) +{ + const char* appId = + web_provider_livebox_get_app_id(boxInfo->boxId.c_str()); + + if (!appId) { + LogD("no appid of %s", boxInfo->boxId.c_str()); + return false; + } + + std::string appIdStr(appId); + delete appId; + + auto it = m_ewkContextMap.find(appIdStr); + if (it == m_ewkContextMap.end()) { + ewkContext = getAvailableEwkContext(appIdStr); + insertContextMap(appIdStr, ewkContext); + } else { + ewkContext = it->second; + } + + if (!BoxManager::requestAddBox(boxInfo, ewkContext)) { + return false; + } + + return true; +} + +void AppBoxManager::updateEwkContext(std::string& boxId) +{ + 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 appIdStr(appId); + delete appId; + + int count = BoxManager::getBoxCount(appIdStr); + LogD("count: %d", count); + if (!count) { + LogD("%s's ewk context removed", appIdStr.c_str()); + // remove ewk context + eraseContextMap(appIdStr); + } +} + +EwkContextPtr AppBoxManager::getAvailableEwkContext(const std::string& appId) +{ + + // get the base executable path + std::string baseExecutablePath = getBaseExecutablePath(appId); + if (baseExecutablePath.empty()) { + return EwkContextPtr(); + } + + // get web process path for this box + std::string webProcessPath = baseExecutablePath + ".d-box"; + + // get plugin process path for this box + std::string pluginProcessPath = baseExecutablePath + ".npruntime"; + + // box manager should set webprocess path as value of 'WEB_PROCESS_PATH' + // before calling ewk_context_new_with_injected_bundle_path(). + setenv("WEB_PROCESS_EXECUTABLE_PATH", webProcessPath.c_str(), 1); + setenv("PLUGIN_PROCESS_EXECUTABLE_PATH", pluginProcessPath.c_str(), 1); + + EwkContextPtr newEwkContext( + ewk_context_new_with_injected_bundle_path(bundlePath.c_str()), + BoxManager::EwkContextDeleter()); + + // unset the following env variables not to affect other ewk context creation + unsetenv("WEB_PROCESS_EXECUTABLE_PATH"); + unsetenv("PLUGIN_PROCESS_EXECUTABLE_PATH"); + + return newEwkContext; +} + +void AppBoxManager::insertContextMap(std::string& appId, EwkContextPtr ewkContext) +{ + m_ewkContextMap.insert(EwkContextMapPair(appId, ewkContext)); +} + +void AppBoxManager::eraseContextMap(std::string& appId) +{ + m_ewkContextMap.erase(appId); +} + +std::string AppBoxManager::getBaseExecutablePath(const std::string& appId) +{ + ail_error_e ret; + ail_appinfo_h handle = NULL; + + char* retStr = NULL; + ret = ail_get_appinfo(appId.c_str(), &handle); + if (ret != AIL_ERROR_OK) { + return std::string(); + } + + ret = ail_appinfo_get_str(handle, AIL_PROP_X_SLP_EXE_PATH, &retStr); + if (ret != AIL_ERROR_OK || !retStr) { + return std::string(); + } + + std::string basePath(retStr); + + ret = ail_destroy_appinfo(handle); + if (ret != AIL_ERROR_OK) { + return std::string(); + } + + return basePath; +} diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxManager.h b/src_wearable/Plugin/AppBoxPlugin/AppBoxManager.h new file mode 100644 index 0000000..7ef82a6 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxManager.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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://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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxManager.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef APP_BOX_MANAGER_H +#define APP_BOX_MANAGER_H + +#include <Core/IBox.h> +#include <Core/IBoxManager.h> +#include <Core/BoxManager.h> +#include <Core/BoxData.h> +#include <Plugin/IBoxPluginFactory.h> + +class AppBoxManager: public BoxManager { + public: + static IBoxManagerPtr create(IBoxPluginFactoryPtr factory) + { + return IBoxManagerPtr(new AppBoxManager(factory)); + }; + ~AppBoxManager(); + + private: + // BoxManager implementation + bool requestAddBox(BoxInfoPtr boxInfo, EwkContextPtr ewkContext); + void updateEwkContext(std::string& boxId); + + EwkContextPtr getAvailableEwkContext(const std::string& appId); + void insertContextMap(std::string& appId, EwkContextPtr ewkContext); + void eraseContextMap(std::string& appId); + std::string getBaseExecutablePath(const std::string& appId); + explicit AppBoxManager(IBoxPluginFactoryPtr factory); + + // members + typedef std::map<std::string, EwkContextPtr> EwkContextMap; + typedef std::pair<std::string, EwkContextPtr> EwkContextMapPair; + EwkContextMap m_ewkContextMap; +}; + + +#endif // APP_BOX_MANAGER_H diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxPdHelper.cpp b/src_wearable/Plugin/AppBoxPlugin/AppBoxPdHelper.cpp new file mode 100644 index 0000000..46e0fb9 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxPdHelper.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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://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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxPdHelper.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <Evas.h> +#include <ewk_view.h> +#include <Core/Util/Log.h> +#include "AppBoxPdHelper.h" + +AppBoxPdHelper::AppBoxPdHelper(Evas_Object* pdWin) + : m_win(pdWin) + , m_boxWebView() + , m_pdWebView() + , m_opened(false) +{ +} + +AppBoxPdHelper::~AppBoxPdHelper() +{ +} + +void AppBoxPdHelper::startOpen() +{ + LogD("enter"); +} + +void AppBoxPdHelper::finishOpen(Evas_Object* child) +{ + LogD("enter"); + m_opened = true; + setPdWebView(child); +} + +void AppBoxPdHelper::close() +{ + LogD("enter"); +} + +void AppBoxPdHelper::setBoxWebView(Evas_Object* webview) +{ + LogD("enter"); + m_boxWebView = webview; +} + +void AppBoxPdHelper::setPdWebView(Evas_Object* webview) +{ + LogD("enter"); + m_pdWebView = webview; +} + +Evas_Object* AppBoxPdHelper::getBoxWebView() const +{ + LogD("enter"); + return m_boxWebView; +} + +Evas_Object* AppBoxPdHelper::getPdWebView() const +{ + LogD("enter"); + return m_pdWebView; +} + +Evas* AppBoxPdHelper::getPdCanvas() const +{ + LogD("enter"); + return evas_object_evas_get(m_win); +} + +bool AppBoxPdHelper::isPdOpened() const +{ + LogD("enter"); + return m_opened; +} diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxPdHelper.h b/src_wearable/Plugin/AppBoxPlugin/AppBoxPdHelper.h new file mode 100644 index 0000000..ae49863 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxPdHelper.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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://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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxPdHelper.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#ifndef APP_BOX_PD_HELPER_H +#define APP_BOX_PD_HELPER_H + +#include <string> +#include <Evas.h> +#include <Core/View/IPdHelper.h> + +class AppBoxPdHelper: public IPdHelper { + public: + static IPdHelperPtr create(Evas_Object* pdWin) + { + return IPdHelperPtr(new AppBoxPdHelper(pdWin)); + } + virtual void startOpen(); + virtual void finishOpen(Evas_Object* child); + virtual void close(); + virtual void setBoxWebView(Evas_Object* webview); + virtual void setPdWebView(Evas_Object* webview); + virtual Evas_Object* getBoxWebView() const; + virtual Evas_Object* getPdWebView() const; + virtual Evas* getPdCanvas() const; + virtual bool isPdOpened() const; + virtual ~AppBoxPdHelper(); + + private: + AppBoxPdHelper(Evas_Object* pdWin); + + //members + Evas_Object* m_win; + Evas_Object* m_boxWebView; + Evas_Object* m_pdWebView; + bool m_opened; +}; + +#endif // APP_BOX_PD_HELPER_H diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxPluginFactory.cpp b/src_wearable/Plugin/AppBoxPlugin/AppBoxPluginFactory.cpp new file mode 100644 index 0000000..58f149c --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxPluginFactory.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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://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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxPluginFactory.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <memory> +#include <Core/View/IRenderView.h> +#include <Core/BoxData.h> +#include "AppBoxRenderView.h" +#include "AppBoxPluginFactory.h" + +IRenderViewPtr AppBoxPluginFactory::createRenderView( + std::shared_ptr<BoxInfo> boxInfo, + std::shared_ptr<Ewk_Context> ewkContext) +{ + return AppBoxRenderView::create(boxInfo, ewkContext); +} diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxPluginFactory.h b/src_wearable/Plugin/AppBoxPlugin/AppBoxPluginFactory.h new file mode 100644 index 0000000..e54d409 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxPluginFactory.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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://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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxPluginFactory.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef APP_BOX_PLUGIN_FACTORY_H +#define APP_BOX_PLUGIN_FACTORY_H + +#include <string> +#include <memory> +#include <Plugin/IBoxPluginFactory.h> +#include <Core/View/IRenderView.h> +#include <Core/Buffer/IRenderBuffer.h> +#include <ewk_context.h> +#include <Evas.h> + +// forward declaration +struct BoxInfo; + +class AppBoxPluginFactory: public IBoxPluginFactory { + public: + IRenderViewPtr createRenderView( + std::shared_ptr<BoxInfo> boxInfo, + std::shared_ptr<Ewk_Context> ewkContext); + + AppBoxPluginFactory() {}; + ~AppBoxPluginFactory() {}; +}; + +#endif //APP_BOX_PLUGIN_FACTORY_H diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxRenderView.cpp b/src_wearable/Plugin/AppBoxPlugin/AppBoxRenderView.cpp new file mode 100755 index 0000000..6513973 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxRenderView.cpp @@ -0,0 +1,950 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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://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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxRenderView.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include "config.h" +#include "AppBoxRenderView.h" + +#include <sys/types.h> +#include <unistd.h> +#include <string> +#include <fstream> +#include <functional> +#include <streambuf> +#include <ail.h> +#include <aul.h> +#include <Eina.h> +#include <Evas.h> +#include <Ecore.h> +#include <Elementary.h> +#include <EWebKit2.h> +#include <ewk_view.h> +#include <ewk_context.h> +#include <ewk_settings.h> +#include <livebox-service.h> +#include <i_runnable_widget_object.h> +#include <core_module.h> +#include <provider.h> +#include <API/web_provider_livebox_info.h> +#include <Core/BoxData.h> +#include <Core/View/IPdHelper.h> +#include <Core/View/PdHelper.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> + +#include "AppBoxPdHelper.h" + + +#define RENDER_MAX_TIME 30.0 +#define RENDER_MAX_TIME_FOR_INSPECTOR 1200.0 +#define SNAPSHOT_REMOVE_TIME 0.5 +#define TOUCH_MAX_WAIT_TIME 10.0 +#define WEB_DBOX_OBJ_MOVE_TO_OUTSIDE_POINT_VALUE -10000 + +// injection javascript file regarding creating js object used by box and pd +static const std::string injectionFile("/usr/share/web-provider/injection.js"); +static const std::string consoleMessageLogTag("ConsoleMessage"); +static const std::string jsRegisterBoxInfoFunction( + "webprovider.registerAppWidgetContextInfo"); + +AppBoxRenderView::AppBoxRenderView( + BoxInfoPtr boxInfo, + EwkContextPtr ewkContext) + : RenderView(boxInfo, false) + , m_appId() + , m_boxId() + , m_instanceId() + , m_contentInfo() + , m_ewkContext(ewkContext) + , m_boxRenderInfo() + , m_boxWrt() + , m_pdWrt() + , m_boxRenderBuffer() + , m_pdRenderBuffer() + , m_boxSnapshot() + , m_boxRenderTimer() + , m_boxTouchTimer() + , m_boxRemoveSnapShotTimer() + , m_pdHelper() + , m_boxIcon() + , m_pdFastOpen(false) + , m_boxFinishLoad(false) + , m_boxFrameRendered(false) + , m_boxWaitFrameRender(false) + , m_isTouchableBox(false) + , m_boxWrt_isSuspended(false) + , m_showed(false) + , m_showIcon(false) +{ + LogD("enter"); + + // member initialization + m_boxId = boxInfo->boxId; + m_instanceId = boxInfo->instanceId; + m_contentInfo = boxInfo->contentInfo; + m_appId = getAppId(m_boxId); + if (m_appId.empty()) { + throw; //exception throw! + } + + + // get box render buffer + m_boxRenderBuffer = getBoxBuffer(); + + if (!m_showIcon) { + ail_appinfo_h handle; + ail_error_e ret; + char *icon; + ret = ail_get_appinfo(m_appId.c_str(), &handle); + if (ret != AIL_ERROR_OK) { + LogE("[%s] DB_FAILED(0x) : failed to get the app-info", __FUNCTION__); + } else { + ail_appinfo_get_str(handle, AIL_PROP_ICON_STR, &icon); + } +#if ENABLE(SHOW_PRE_ICON) + showIcon(icon, boxInfo->boxWidth, boxInfo->boxHeight); +#endif + ail_destroy_appinfo(handle); + } + // use fastopen to default + // m_pdFastOpen = web_provider_livebox_get_pd_fast_open(m_boxId.c_str()) ? true : false; + m_pdFastOpen = true; + m_isTouchableBox = + web_provider_livebox_get_mouse_event(m_boxId.c_str()) ? true : false; +} + +AppBoxRenderView::~AppBoxRenderView() +{ + LogD("enter"); + + destroyWrtCore(m_boxWrt); + destroyWrtCore(m_pdWrt); +} + +void AppBoxRenderView::showBox(RenderInfoPtr boxRenderInfo) +{ + LogD("enter"); + + // stop updating render buffer + m_boxRenderBuffer->stopCanvasUpdate(); + + if (m_boxRenderTimer) { + // delete already running timer + stopRenderBox(); + } + + // delete touch timer + if (m_isTouchableBox) { + deleteTimer(&m_boxTouchTimer); + } + + // set boxFinishLoad and m_boxFrameRendered to false + m_boxFinishLoad = false; + m_boxFrameRendered = false; + m_boxWaitFrameRender = false; + + // 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->setBoxWebView(m_boxWrt->GetCurrentWebview()); + } + + // resize webview fitted to width, height of Box + evas_object_resize( + m_boxWrt->GetCurrentWebview(), + boxRenderInfo->width, + boxRenderInfo->height); + + showSnapShot(); + evas_object_show(m_boxWrt->GetCurrentWebview()); + // webview window move to outside of viewport because of overlap issue with snapshot image + evas_object_move(m_boxWrt->GetCurrentWebview(), WEB_DBOX_OBJ_MOVE_TO_OUTSIDE_POINT_VALUE, WEB_DBOX_OBJ_MOVE_TO_OUTSIDE_POINT_VALUE); + + m_boxWrt->Show(); + m_boxRenderInfo = boxRenderInfo; + + // start timer for clearing existing snapshot in case of only pd open + addTimer(&m_boxRemoveSnapShotTimer, + SNAPSHOT_REMOVE_TIME, removeBoxSnapShotTimerCallback); + m_showed = true; +} + +AppBoxRenderView::WrtCorePtr AppBoxRenderView::createWrtCore( + UrlType type, std::string& startUrl, + Evas_Object* win, EwkContextPtr ewkContext) +{ + LogD("enter"); + + WrtCorePtr wrt; + wrt = WRT::CoreModuleSingleton:: + Instance().getRunnableWidgetObject(m_appId); + + // prepare webview + if (startUrl.empty()) { + LogD("no start url"); + return WrtCorePtr(); + } + wrt->PrepareView(startUrl, win, ewkContext.get()); + wrt->CheckBeforeLaunch(); + + // set callback functions of RunnableWidgetObject + WRT::UserDelegatesPtr cbs(new WRT::UserDelegates); + using namespace std::placeholders; + cbs->loadStartedCallback = std::bind(&AppBoxRenderView::startLoadCallback, this, _1, _2); + if (type == URL_TYPE_BOX) { + cbs->loadFinishedCallback = std::bind(&AppBoxRenderView::finishBoxLoadCallback, this, _1, _2); + } else { + cbs->loadFinishedCallback = std::bind(&AppBoxRenderView::finishPdLoadCallback, this, _1, _2); + } + + cbs->setWebviewCallback = std::bind(&AppBoxRenderView::setBufferCallback, this, _1); + cbs->unsetWebviewCallback = std::bind(&AppBoxRenderView::unsetBufferCallback, this, _1); + + cbs->policyNavigationDecideCallback = std::bind(&AppBoxRenderView::decideNavigationCallback, this, _1, _2); + cbs->processCrashedCallback = std::bind(&AppBoxRenderView::crashWebProcessCallback, this, _1, _2); + cbs->consoleMessageCallback = std::bind(&AppBoxRenderView::consoleMessageCallback, this, _1, _2); + wrt->SetUserDelegates(cbs); + + // set basic webview setting + setWebViewBasicSetting(wrt->GetCurrentWebview()); + + // only box type needed + if (type == URL_TYPE_BOX) { + Ewk_Settings* setting = ewk_view_settings_get(wrt->GetCurrentWebview()); + ewk_settings_link_effect_enabled_set(setting, EINA_FALSE); + } + + return wrt; +} + +void AppBoxRenderView::destroyBoxWrtCore() +{ + LogD("enter"); + + // stop updating render buffer + m_boxRenderBuffer->stopCanvasUpdate(); + deleteTimer(&m_boxRenderTimer); + deleteTimer(&m_boxRemoveSnapShotTimer); + destroyWrtCore(m_boxWrt); + m_boxWrt.reset(); + + // temp + m_boxWrt_isSuspended = false; +} + +void AppBoxRenderView::destroyPdWrtCore() +{ + LogD("enter"); + + destroyWrtCore(m_pdWrt); + m_pdWrt.reset(); +} + +void AppBoxRenderView::destroyWrtCore(WrtCorePtr wrt) +{ + LogD("enter"); + + if (wrt) { + wrt->Hide(); + } +} + +void AppBoxRenderView::hideBox() +{ + LogD("enter"); + if (m_isTouchableBox) { + deleteTimer(&m_boxTouchTimer); + } + + if (m_boxRenderInfo) { + destroyBoxWrtCore(); + if (m_boxRenderInfo->window) { + evas_object_hide(m_boxRenderInfo->window); + } + } +} + +void AppBoxRenderView::pauseBox() +{ + LogD("enter"); +} + +void AppBoxRenderView::resumeBox() +{ + LogD("enter"); + if (!m_showed) { + RenderView::show(); + } +} + +void AppBoxRenderView::showPd(RenderInfoPtr pdRenderInfo, RenderInfoPtr boxRenderInfo) +{ + LogD("enter"); + + std::string pdStartUrl = getStartUrl(URL_TYPE_PD, pdRenderInfo->defaultUrlParams); + if (m_pdFastOpen) { + destroyPdWrtCore(); + 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(pdRenderInfo->window); + + // need to create new snapshot when m_napshot is empty + if (!m_boxSnapshot) { + evas_object_show(getCurrentSnapShot()); + } + getPdBuffer()->setWebView(m_pdWrt->GetCurrentWebview()); + // show box + showBox(boxRenderInfo); + + // start timer for clearing existing snapshot in case of only pd open + addTimer(&m_boxRemoveSnapShotTimer, SNAPSHOT_REMOVE_TIME, removeBoxSnapShotTimerCallback); +} + +void AppBoxRenderView::hidePd() +{ + LogD("enter"); + + if (m_pdFastOpen) { + destroyPdWrtCore(); + } + m_pdHelper->close(); + m_pdHelper.reset(); + + // start timer for clearing existing snapshot in case of only pd open + struct stat tmp; + if (stat(WEB_PROVIDER_INSPECTOR_FILE_PATH, &tmp) == 0) { + addTimer(&m_boxRenderTimer, RENDER_MAX_TIME_FOR_INSPECTOR, fireBoxRenderTimerCallback); + } else { + addTimer(&m_boxRenderTimer, RENDER_MAX_TIME, fireBoxRenderTimerCallback); + } + +} + +void AppBoxRenderView::didBoxTouched(int x, int y) +{ + LogD("x : %d, y: %d", x, y); + if (!m_isTouchableBox) { + return; + } + + if (!m_boxWrt) { + LogD("no webview"); + return; + } + + // if needed, resume render view + if (m_boxRenderTimer) { + deleteTimer(&m_boxRenderTimer); + } else { + if (!m_boxTouchTimer) { + m_boxRenderBuffer->startCanvasUpdate(); + + // temp condition + if (m_boxWrt_isSuspended == true) + { + m_boxWrt_isSuspended = false; + m_boxWrt->Resume(); + } + } else { + deleteTimer(&m_boxTouchTimer); + } + } + addTimer(&m_boxTouchTimer, TOUCH_MAX_WAIT_TIME, fireBoxTouchTimerCallback); +} + +void AppBoxRenderView::didPdTouched(int x, int y) +{ + LogD("x : %d, y: %d", x, y); +} + +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) +{ + 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(); + } + + return std::string(appId); +} + +std::string AppBoxRenderView::getStartUrl(UrlType type, std::string& defaultParams) +{ + const char* path = NULL; + switch (type) { + case URL_TYPE_BOX: + path = livebox_service_lb_script_path(m_boxId.c_str()); + break; + case URL_TYPE_PD: + path = livebox_service_pd_script_path(m_boxId.c_str()); + break; + default: + LogD("no available type"); + } + + std::string startUrl; + if (path) { + LogD("path : %s", path); + startUrl = path; + } else { + // TODO In this case, fallback page will be loaded. + LogE("Fail to get service lib script path"); + } + + // add default parameters to start url + startUrl += defaultParams; + + return startUrl; +} + +Evas_Object* AppBoxRenderView::getCurrentSnapShot() +{ + LogD("enter"); + + clearSnapShot(); + m_boxSnapshot = m_boxRenderBuffer->getSnapshot(); + + return m_boxSnapshot; +} + +void AppBoxRenderView::clearSnapShot() +{ + LogD("enter"); + if (m_boxSnapshot) { + evas_object_del(m_boxSnapshot); + m_boxSnapshot = NULL; + } +} + +void AppBoxRenderView::showSnapShot() +{ + LogD("enter"); + if (m_boxSnapshot) { + evas_object_raise(m_boxSnapshot); + evas_object_show(m_boxSnapshot); + } +} + +void AppBoxRenderView::hideSnapShot() +{ + LogD("enter"); + if (m_boxSnapshot) { + evas_object_hide(m_boxSnapshot); + evas_object_lower(m_boxSnapshot); + } +} + +void AppBoxRenderView::addTimer(Ecore_Timer** timer, double interval, Ecore_Task_Cb callback) +{ + LogD("enter"); + if (*timer) { + deleteTimer(timer); + } + + *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_boxRenderTimer); + m_boxRenderBuffer->stopCanvasUpdate(); + if (m_isTouchableBox) { + // stop touch timer + deleteTimer(&m_boxTouchTimer); + + // temp condition + if (m_boxWrt_isSuspended == false) + { + m_boxWrt_isSuspended = true; + m_boxWrt->Suspend(); + } + } else { + // 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); + // disable shadow effect on scrolling +#if !ENABLE(WEBKIT_UPVERSION) + ewk_settings_edge_effect_enabled_set(setting, EINA_FALSE); + // Disable ime features + ewk_settings_default_keypad_enabled_set(setting, EINA_FALSE); +#endif + // To support transparent background + ewk_view_bg_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); + // To set font type whenever font changed + ewk_view_use_settings_font(webview); +} + +void AppBoxRenderView::consoleMessage(int level, const char* format, ...) +{ + va_list args; + va_start(args, format); + switch (level) { + case DLOG_DEBUG: + ALOG_VA(LOG_DEBUG, consoleMessageLogTag.c_str(), format, args); + break; + case DLOG_WARN: + ALOG_VA(LOG_WARN, consoleMessageLogTag.c_str(), format, args); + break; + case DLOG_ERROR: + ALOG_VA(LOG_ERROR, consoleMessageLogTag.c_str(), format, args); + break; + default: + ALOG_VA(LOG_DEBUG, consoleMessageLogTag.c_str(), format, args); + break; + } + va_end(args); +} + +Eina_Bool AppBoxRenderView::fireBoxRenderTimerCallback(void* data) +{ + LogD("enter"); + + AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data); + This->m_boxRenderTimer = NULL; + This->stopRenderBox(); + + return ECORE_CALLBACK_CANCEL; +} + +Eina_Bool AppBoxRenderView::fireBoxTouchTimerCallback(void* data) +{ + + LogD("enter"); + AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data); + This->m_boxRenderBuffer->stopCanvasUpdate(); + + // temp condition + if (This->m_boxWrt_isSuspended == false) + { + This->m_boxWrt_isSuspended = true; + This->m_boxWrt->Suspend(); + } + + This->m_boxTouchTimer = NULL; + + return ECORE_CALLBACK_CANCEL; +} + + +Eina_Bool AppBoxRenderView::removeBoxSnapShotTimerCallback(void* data) +{ + LogD("enter"); + + AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data); + if (!(This->m_boxFinishLoad && This->m_boxFrameRendered)) { + return ECORE_CALLBACK_RENEW; + } + + if (!This->m_boxWaitFrameRender) { + This->m_boxWaitFrameRender = true; + return ECORE_CALLBACK_RENEW; + } + // hide snapshot because valid frame has been prepared generally. + This->clearSnapShot(); + This->m_boxRenderBuffer->startCanvasUpdate(); + + if (This->m_showIcon) { + evas_object_del(This->m_boxIcon); + This->m_showIcon = false; + } + + // move to inside of viewport to prevent overlap with snapshot image + evas_object_move(This->m_boxWrt->GetCurrentWebview(), 0, 0); + evas_object_show(This->m_boxWrt->GetCurrentWebview()); + + This->m_boxRemoveSnapShotTimer = NULL; + return ECORE_CALLBACK_CANCEL; +} + +Eina_Bool AppBoxRenderView::openPdIdlerCallback(void* data) +{ + LogD("enter"); + AppBoxRenderView* This = static_cast<AppBoxRenderView*>(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"); + UNUSED_PARAM(webview); + UNUSED_PARAM(data); + + std::string resultStr(result ? result : "null"); + LogD("result: %s", resultStr.c_str()); +} + +void AppBoxRenderView::startLoadCallback(Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + if(!webview) { + return; + } + // execute injection for creating js objects + std::ifstream jsFile(injectionFile); + std::string jsString((std::istreambuf_iterator<char>(jsFile)), + std::istreambuf_iterator<char>()); + + std::ostringstream script; + script << jsString; + + // add javascripts for operation of synchronous call + script << jsRegisterBoxInfoFunction << "('box-id', '" << m_boxId << "');"; + script << jsRegisterBoxInfoFunction << "('instance-id', '" << m_contentInfo << "');"; + + //LogD("injected js code: %s", script.str().c_str()); + ewk_view_script_execute(webview, script.str().c_str(), executeScriptCallback, this); +} + +void AppBoxRenderView::finishBoxLoadCallback(Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + if (!webview) { + return; + } + + ewk_view_visibility_set(webview, EINA_TRUE); + + if (!m_pdHelper) { + // start render timer + struct stat tmp; + if (stat(WEB_PROVIDER_INSPECTOR_FILE_PATH, &tmp) == 0) { + addTimer(&m_boxRenderTimer, RENDER_MAX_TIME_FOR_INSPECTOR, fireBoxRenderTimerCallback); + } else { + addTimer(&m_boxRenderTimer, RENDER_MAX_TIME, fireBoxRenderTimerCallback); + } + } else { + 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, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + if (!webview) { + return; + } + + ewk_view_visibility_set(webview, EINA_TRUE); +} + +void AppBoxRenderView::createWindowBeforeCallback(Evas** canvas, Evas_Object* parent) +{ + LogD("enter"); + + if (m_pdHelper) { + if (!(m_pdHelper->isPdOpened()) && + 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); +} + +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); + m_pdHelper->finishOpen(child); + } + } + + setWebViewBasicSetting(child); + evas_object_show(child); +} + +void AppBoxRenderView::setBufferCallback(Evas_Object* webview) +{ + LogD("enter"); + evas_object_show(webview); + evas_object_focus_set(webview, EINA_TRUE); +} + +void AppBoxRenderView::unsetBufferCallback(Evas_Object* webview) +{ + LogD("enter"); + evas_object_hide(webview); +} + +void AppBoxRenderView::decideNavigationCallback(Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(webview); + + Ewk_Policy_Decision* policyDecision = static_cast<Ewk_Policy_Decision*>(eventInfo); + const char* url = ewk_policy_decision_url_get(policyDecision); + if (!url || !*url) { + LogE("url is empty"); + return; + } + std::string uri(url); + + // navigation of box scheme should be ignored + processBoxScheme(uri); +} + +void AppBoxRenderView::crashWebProcessCallback(Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(webview); + UNUSED_PARAM(eventInfo); + LogD("instanceId: %s", m_instanceId.c_str()); + elm_exit(); +} + +void AppBoxRenderView::loadNonEmptyLayoutFinishedCallback( + void* data, Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(data); + UNUSED_PARAM(webview); + UNUSED_PARAM(eventInfo); +} + +void AppBoxRenderView::frameRenderedCallback( + void* data, Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(webview); + UNUSED_PARAM(eventInfo); + + // start to update render buffer! + AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data); + + // set flag + This->m_boxFrameRendered = true; + + // move to inside of viewport to prevent overlap with snapshot image + if (!This->m_boxRemoveSnapShotTimer) { + evas_object_move(This->m_boxWrt->GetCurrentWebview(), 0, 0); + } +} + +void AppBoxRenderView::consoleMessageCallback(Evas_Object* webview, void* eventInfo) +{ + UNUSED_PARAM(webview); + + Ewk_Console_Message* consoleMessage = static_cast<Ewk_Console_Message*>(eventInfo); + + std::stringstream buf; + unsigned int lineNumber = ewk_console_message_line_get(consoleMessage); + const char* text = ewk_console_message_text_get(consoleMessage); + const char* source = ewk_console_message_source_get(consoleMessage); + if (lineNumber) { + buf << source << ":"; + buf << lineNumber << ":"; + } + buf << text; + + int level; + switch (ewk_console_message_level_get(consoleMessage)) { + case EWK_CONSOLE_MESSAGE_LEVEL_TIP: + case EWK_CONSOLE_MESSAGE_LEVEL_LOG: + case EWK_CONSOLE_MESSAGE_LEVEL_DEBUG: + level = DLOG_DEBUG; + break; + case EWK_CONSOLE_MESSAGE_LEVEL_WARNING: + level = DLOG_WARN; + break; + case EWK_CONSOLE_MESSAGE_LEVEL_ERROR: + level = DLOG_ERROR; + break; + default: + level = DLOG_DEBUG; + break; + } + AppBoxRenderView::consoleMessage(level, "%s", buf.str().c_str()); +} + + +void AppBoxRenderView::showIcon(char *iconString, int width, int height) +{ + LogD("enter"); + + Evas_Load_Error err; + Evas_Object *snapshot; + int w,h; + int x = 0; + int y = 0; + + if (!iconString) { + LogE("iconString is NULL"); + return; + } + + snapshot = evas_object_image_add(m_boxRenderBuffer->getCanvas()); + if (!snapshot) { + LogE("evas_object_image_add FAILED"); + return; + } + + const char *string = const_cast<const char *>(iconString); + evas_object_image_colorspace_set(snapshot, EVAS_COLORSPACE_ARGB8888); + evas_object_image_alpha_set(snapshot, EINA_TRUE); + evas_object_image_file_set(snapshot, string, NULL); + err = evas_object_image_load_error_get(snapshot); + if (err != EVAS_LOAD_ERROR_NONE) { + LogE("Load error: %s\n", evas_load_error_str(err)); + evas_object_del(snapshot); + return; + } + evas_object_image_size_get(snapshot, &w, &h); + evas_object_image_filled_set(snapshot, EINA_TRUE); + + + if (width > w) { + x = (width - w) >> 1; + } + + if (height > h) { + y = (height - h) >> 1; + } + + evas_object_image_fill_set(snapshot, 0, 0, w, h); + evas_object_move(snapshot, x, y); + evas_object_show(snapshot); + evas_object_resize(snapshot, w, h); + + provider_send_updated( + m_boxId.c_str(), + m_instanceId.c_str(), + width, height, + 0, m_contentInfo.c_str(), NULL); + + m_boxIcon = snapshot; + m_showIcon = true; +} diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxRenderView.h b/src_wearable/Plugin/AppBoxPlugin/AppBoxRenderView.h new file mode 100755 index 0000000..0812d0e --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxRenderView.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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://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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxRenderView.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef APP_BOX_RENDER_VIEW_H +#define APP_BOX_RENDER_VIEW_H + +#include <string> +#include <memory> +#include <Eina.h> +#include <Ecore.h> +#include <Evas.h> +#include <ewk_context.h> +#include <i_runnable_widget_object.h> +#include <Core/BoxData.h> +#include <Core/View/IPdHelper.h> +#include <Core/View/RenderView.h> + +class AppBoxRenderBuffer; + +class AppBoxRenderView: public RenderView { + public: + typedef std::shared_ptr<Ewk_Context> EwkContextPtr; + + static IRenderViewPtr create(BoxInfoPtr boxInfo, EwkContextPtr ewkContext) + { + return IRenderViewPtr(new AppBoxRenderView(boxInfo, ewkContext)); + }; + virtual void showBox(RenderInfoPtr boxRenderInfo); + virtual void hideBox(); + virtual void pauseBox(); + virtual void resumeBox(); + virtual void showPd(RenderInfoPtr pdRenderInfo, RenderInfoPtr boxRenderInfo); + virtual void hidePd(); + virtual void didBoxTouched(int x, int y); + virtual void didPdTouched(int x, int y); + virtual ~AppBoxRenderView(); + + private: + // type definition + typedef std::shared_ptr<WRT::IRunnableWidgetObject> WrtCorePtr; + enum UrlType { + URL_TYPE_BOX, + URL_TYPE_PD + }; + + WrtCorePtr createWrtCore( + UrlType type, std::string& startUrl, + Evas_Object* win, EwkContextPtr ewkContext); + void setWebViewBasicSetting(Evas_Object* webview); + void destroyWrtCore(WrtCorePtr wrt); + void destroyBoxWrtCore(); + void destroyPdWrtCore(); + Evas_Object* getBoxWebView(); + Evas_Object* getPdWebView(); + std::string getAppId(std::string& boxId); + std::string getStartUrl(UrlType type, std::string& defaultParams); + Evas_Object* getCurrentSnapShot(); + void clearSnapShot(); + void showSnapShot(); + void hideSnapShot(); + void addTimer(Ecore_Timer** timer, double interval, Ecore_Task_Cb callback); + void deleteTimer(Ecore_Timer** timer); + void stopRenderBox(); + void consoleMessage(int level, const char* format, ...); + void showIcon(char *iconString, int width, int height); + + // timer and idler callback + static Eina_Bool fireBoxRenderTimerCallback(void* data); + static Eina_Bool fireBoxTouchTimerCallback(void* data); + static Eina_Bool removeBoxSnapShotTimerCallback(void* data); + static Eina_Bool openPdIdlerCallback(void* data); + + // ewk view callback + static void executeScriptCallback( + Evas_Object* webview, const char* result, void* data); + static void loadNonEmptyLayoutFinishedCallback( + void* data, Evas_Object* webview, void* eventInfo); + static void frameRenderedCallback( + void* data, Evas_Object* webview, void* eventInfo); + + // user Callbacks of RunnableWidgetObject + void startLoadCallback(Evas_Object* webview, void* eventInfo); + void finishBoxLoadCallback(Evas_Object* webview, void* eventInfo); + void finishPdLoadCallback(Evas_Object* webview, void* eventInfo); + void createWindowBeforeCallback(Evas** canvas, Evas_Object* parent); + void createWindowAfterCallback(Evas_Object* parent, Evas_Object* child); + void setBufferCallback(Evas_Object* webview); + void unsetBufferCallback(Evas_Object* webview); + void decideNavigationCallback(Evas_Object* webview, void* eventInfo); + void crashWebProcessCallback(Evas_Object* webview, void* eventInfo); + void consoleMessageCallback(Evas_Object* webview, void* eventInfo); + + // constructor + explicit AppBoxRenderView(BoxInfoPtr boxInfo, EwkContextPtr ewkContext); + + // members + std::string m_appId; + std::string m_boxId; + std::string m_instanceId; + std::string m_contentInfo; + EwkContextPtr m_ewkContext; + RenderInfoPtr m_boxRenderInfo; + WrtCorePtr m_boxWrt; + WrtCorePtr m_pdWrt; + IRenderBufferPtr m_boxRenderBuffer; + IRenderBufferPtr m_pdRenderBuffer; + Evas_Object* m_boxSnapshot; + Ecore_Timer* m_boxRenderTimer; + Ecore_Timer* m_boxTouchTimer; + Ecore_Timer* m_boxRemoveSnapShotTimer; + IPdHelperPtr m_pdHelper; + Evas_Object* m_boxIcon; + + // for check status of webview + bool m_pdFastOpen; + bool m_boxFinishLoad; + bool m_boxFrameRendered; + bool m_boxWaitFrameRender; + bool m_isTouchableBox; + + // TODO this temporary flag should removed! + bool m_boxWrt_isSuspended; + bool m_showed; + bool m_showIcon; +}; + +#endif // APP_BOX_RENDER_VIEW_H diff --git a/src_wearable/Plugin/AppBoxPlugin/CMakeLists.txt b/src_wearable/Plugin/AppBoxPlugin/CMakeLists.txt new file mode 100644 index 0000000..df14513 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/CMakeLists.txt @@ -0,0 +1,73 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# 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://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, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @author Yunchan Cho (yunchan.cho@samsung.com) + +SET(TARGET_NAME web-provider-plugin-app) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + ail + ewebkit2 + wrt-core + dpl-efl + evas + ecore + eina + livebox-service + dlog + provider # this should be removed + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/box_plugin_interface.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/AppBoxManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/AppBoxPluginFactory.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/AppBoxRenderView.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/AppBoxPdHelper.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LIBRARIES} + ${TARGET_CORE} +) + +INSTALL(TARGETS ${TARGET_NAME} + DESTINATION lib/${PROJECT_NAME} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) + +INSTALL_FILE(app.json lib/${PROJECT_NAME}) diff --git a/src_wearable/Plugin/AppBoxPlugin/app.json b/src_wearable/Plugin/AppBoxPlugin/app.json new file mode 100644 index 0000000..6388702 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/app.json @@ -0,0 +1,5 @@ +{ + "type" : "app", + "path" : "/usr/lib/web-provider/libweb-provider-plugin-app.so", + "supported_size" : ["1x1","2x1","2x2"] +} diff --git a/src_wearable/Plugin/AppBoxPlugin/box_plugin_interface.cpp b/src_wearable/Plugin/AppBoxPlugin/box_plugin_interface.cpp new file mode 100644 index 0000000..ca5e65e --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/box_plugin_interface.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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://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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file box_plugin_interface.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <memory> +#include <Core/BoxData.h> +#include <Core/Util/Log.h> +#include <Plugin/box_plugin_interface.h> +#include "AppBoxManager.h" +#include "AppBoxPluginFactory.h" + +static std::shared_ptr<IBoxManager> g_manager; + +int web_provider_plugin_interface_initialize() +{ + LogD("enter"); + IBoxPluginFactoryPtr factory(new AppBoxPluginFactory()); + g_manager = AppBoxManager::create(factory); + + return 0; +} + +int web_provider_plugin_interface_command(const request_cmd_type type, const BoxInfoPtr& boxInfo) +{ + LogD("enter"); + int ret = g_manager->doCommand(type, boxInfo); + + if (!ret) { + return -1; + } + + return 0; +} + +int web_provider_plugin_interface_shutdown() +{ + LogD("enter"); + g_manager.reset(); + return 0; +} diff --git a/src_wearable/Plugin/BoxPluginConnector.cpp b/src_wearable/Plugin/BoxPluginConnector.cpp new file mode 100755 index 0000000..d50bc1b --- /dev/null +++ b/src_wearable/Plugin/BoxPluginConnector.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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://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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxPluginConnector.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <map> +#include <dlfcn.h> +#include <Core/Util/Log.h> +#include <Core/BoxData.h> +#include <API/web_provider_plugin_info.h> +#include "box_plugin_interface.h" +#include "BoxPluginConnector.h" + +BoxPluginConnector::BoxPluginConnector() +{ +} + +BoxPluginConnector::~BoxPluginConnector() +{ +} + +bool BoxPluginConnector::initialize() +{ + LogD("enter"); + + int count; + web_provider_plugin_info** pluginList = NULL; + pluginList = web_provider_plugin_get_installed_list(&count); + + if (!pluginList) { + LogD("failed to get installed plugin's information"); + return false; + } + + if (count <= 0) { + LogD("There is no available livebox plugins"); + return false; + } + + m_pluginMap.clear(); + + // get information of installed plugin + LogD("get information of installed plugin"); + for (int i = 0; i < count; i++) { + if (!pluginList[i]) { + continue; + } + + LogD("plugin path: %s", pluginList[i]->path); + void* handle = dlopen(pluginList[i]->path, RTLD_LAZY); + if (!handle) { + LogD("failed to load plugin so: %s", dlerror()); + continue; + } + + std::shared_ptr<plugin_interfaces> pluginInfo(new plugin_interfaces); + + pluginInfo->handle = handle; + pluginInfo->service_boxid = NULL; + if (pluginList[i]->service_boxid) { + pluginInfo->service_boxid = strdup(pluginList[i]->service_boxid); + } + + pluginInfo->initialize = + reinterpret_cast<plugin_interface_func_initialize>( + dlsym(handle, WEB_PROVIDER_PLUGIN_INTERFACE_SYM_INITIALIZE)); + pluginInfo->command = + reinterpret_cast<plugin_interface_func_command>( + dlsym(handle, WEB_PROVIDER_PLUGIN_INTERFACE_SYM_COMMAND)); + pluginInfo->shutdown = + reinterpret_cast<plugin_interface_func_shutdown>( + dlsym(handle, WEB_PROVIDER_PLUGIN_INTERFACE_SYM_SHUTDOWN)); + + if (!pluginInfo->initialize || !pluginInfo->command || + !pluginInfo->shutdown) + { + LogD("symbol for plugin interface is not found"); + continue; + } + + m_pluginMap[std::string(pluginList[i]->type)] = pluginInfo; + } + + // initialize plugins + for (auto it = m_pluginMap.begin(); + it != m_pluginMap.end(); ++it) + { + if (it->second) { + // TODO add exception or abnormal action on loading plugin + if (it->second->initialize() < 0) { + LogD("fail to intialize plugin"); + continue; + } + } + } + + // release information + LogD("release json data of plugins"); + web_provider_plugin_release_installed_list(pluginList, count); + + return true; +} + +bool BoxPluginConnector::shutdown() +{ + LogD("enter"); + // if needed, unload each plugin's DSO. + for (auto it = m_pluginMap.begin(); + it != m_pluginMap.end(); ++it) + { + if (it->second) { + it->second->shutdown(); + dlclose(it->second->handle); + } + } + + return true; +} + +bool BoxPluginConnector::requestCommand( + const request_cmd_type type, const BoxInfoPtr& boxInfo) +{ + LogD("enter"); + + // in case of request of resume all or pause all, all plugins should handle that. + if (type == REQUEST_CMD_RESUME_ALL || + type == REQUEST_CMD_PAUSE_ALL || + type == REQUEST_CMD_UPDATE_ALL || + type == REQUEST_CMD_UPDATE_APPBOX) { + for (auto it = m_pluginMap.begin(); + it != m_pluginMap.end(); ++it) + { + if (it->second) { + it->second->command(type, boxInfo); + } + } + return true; + } + + const std::shared_ptr<plugin_interfaces> plugin = m_pluginMap[boxInfo->boxType]; + if (!plugin) { + LogD("not available livebox type"); + return false; + } + + int ret = plugin->command(type, boxInfo); + if (ret < 0) { + LogD("failed to request command"); + return false; + } + + return true; +} + +std::string BoxPluginConnector::getBoxType(const std::string& serviceBoxId) +{ + LogD("enter"); + + std::string type; + for (auto it = m_pluginMap.begin(); + it != m_pluginMap.end(); ++it) + { + if (it->second && it->second->service_boxid) { + if (serviceBoxId == it->second->service_boxid) { + LogD("service box id is matched!: %s", it->first.c_str()); + type = it->first; + break; + } + } + } + + return type; +} diff --git a/src_wearable/Plugin/BoxPluginConnector.h b/src_wearable/Plugin/BoxPluginConnector.h new file mode 100644 index 0000000..5ada8db --- /dev/null +++ b/src_wearable/Plugin/BoxPluginConnector.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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://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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxPluginConnector.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_PLUGIN_CONNECTOR_H +#define BOX_PLUGIN_CONNECTOR_H + +#include <map> +#include <Core/BoxData.h> +#include "IBoxPluginConnector.h" +#include "box_plugin_interface.h" + +class BoxPluginConnector: public IBoxPluginConnector { + public: // IBoxPluginConnector + static IBoxPluginConnectorPtr create() + { + return IBoxPluginConnectorPtr(new BoxPluginConnector()); + }; + virtual bool initialize(); + virtual bool shutdown(); + virtual bool requestCommand( + const request_cmd_type type, const BoxInfoPtr& boxInfo); + virtual std::string getBoxType(const std::string& serviceBoxId); + virtual ~BoxPluginConnector(); + + private: + BoxPluginConnector(); + + // type definition + typedef std::map<std::string, std::shared_ptr<plugin_interfaces> > pluginMap; + + pluginMap m_pluginMap; + +}; + +#endif // BOX_PLUGIN_CONNECTOR_H diff --git a/src_wearable/Plugin/CMakeLists.txt b/src_wearable/Plugin/CMakeLists.txt new file mode 100644 index 0000000..349ddb0 --- /dev/null +++ b/src_wearable/Plugin/CMakeLists.txt @@ -0,0 +1,67 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# 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://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, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @author Yunchan Cho (yunchan.cho@samsung.com) + +SET(TARGET_NAME ${TARGET_PLUGIN}) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + evas + ewebkit2 + dlog + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/BoxPluginConnector.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} STATIC ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LDFLAGS} "-ldl" + ${${DEPS}_LIBRARIES} +) + +INSTALL(TARGETS ${TARGET_NAME} + DESTINATION lib + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) + +GET_FILENAME_COMPONENT(CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) +INSTALL_FILE(IBoxPluginFactory.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(box_plugin_interface.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) + +# openable plugins of web livebox +ADD_SUBDIRECTORY(AppBoxPlugin) diff --git a/src_wearable/Plugin/IBoxPluginConnector.h b/src_wearable/Plugin/IBoxPluginConnector.h new file mode 100644 index 0000000..3e94fb8 --- /dev/null +++ b/src_wearable/Plugin/IBoxPluginConnector.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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://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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IBoxPluginConnector.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_BOX_PLUGIN_CONNECTOR_H +#define I_BOX_PLUGIN_CONNECTOR_H + +#include <memory> +#include <Core/BoxData.h> +#include <Core/Util/Noncopyable.h> +#include "box_plugin_interface.h" + +class IBoxPluginConnector: Noncopyable { + public: + virtual bool initialize() = 0; + virtual bool shutdown() = 0; + virtual bool requestCommand( + const request_cmd_type type, const BoxInfoPtr& boxInfo) = 0; + virtual std::string getBoxType(const std::string& serviceBoxId) = 0; + virtual ~IBoxPluginConnector() {}; +}; + +typedef std::shared_ptr<IBoxPluginConnector> IBoxPluginConnectorPtr; + +#endif // I_BOX_PLUGIN_CONNECTOR_H diff --git a/src_wearable/Plugin/IBoxPluginFactory.h b/src_wearable/Plugin/IBoxPluginFactory.h new file mode 100644 index 0000000..e0ff5ba --- /dev/null +++ b/src_wearable/Plugin/IBoxPluginFactory.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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://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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IBoxPluginFactory.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_BOX_PLUGIN_FACTORY_H +#define I_BOX_PLUGIN_FACTORY_H + +#include <string> +#include <memory> +#include <Evas.h> +#include <ewk_context.h> + +// forward declaration +class IRenderView; +struct BoxInfo; + +class IBoxPluginFactory { + public: + virtual std::shared_ptr<IRenderView> createRenderView( + std::shared_ptr<BoxInfo> boxInfo, + std::shared_ptr<Ewk_Context> ewkContext) = 0; + virtual ~IBoxPluginFactory() {}; +}; + +typedef std::shared_ptr<IBoxPluginFactory> IBoxPluginFactoryPtr; + +#endif //I_BOX_PLUGIN_FACTORY_H diff --git a/src_wearable/Plugin/box_plugin_interface.h b/src_wearable/Plugin/box_plugin_interface.h new file mode 100755 index 0000000..28ef571 --- /dev/null +++ b/src_wearable/Plugin/box_plugin_interface.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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://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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file box_plugin_interface.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_PLUGIN_INTERFACE_H +#define BOX_PLUGIN_INTERFACE_H + +#include <string> +#include <Core/BoxData.h> + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +#define WEB_PROVIDER_PLUGIN_INTERFACE_SYM_INITIALIZE "web_provider_plugin_interface_initialize" +#define WEB_PROVIDER_PLUGIN_INTERFACE_SYM_COMMAND "web_provider_plugin_interface_command" +#define WEB_PROVIDER_PLUGIN_INTERFACE_SYM_SHUTDOWN "web_provider_plugin_interface_shutdown" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + REQUEST_CMD_ADD_BOX, + REQUEST_CMD_REMOVE_BOX, + REQUEST_CMD_OPEN_PD, + REQUEST_CMD_CLOSE_PD, + REQUEST_CMD_RESIZE_BOX, + REQUEST_CMD_RESUME_BOX, + REQUEST_CMD_PAUSE_BOX, + REQUEST_CMD_RESUME_ALL, + REQUEST_CMD_PAUSE_ALL, + REQUEST_CMD_CHANGE_PERIOD, + REQUEST_CMD_UPDATE_BOX, + REQUEST_CMD_UPDATE_ALL, + REQUEST_CMD_UPDATE_APPBOX +} request_cmd_type; + +// definition of interface function type +typedef int (*plugin_interface_func_initialize)(void); +typedef int (*plugin_interface_func_command)( + const request_cmd_type type, const BoxInfoPtr& boxInfo); +typedef int (*plugin_interface_func_shutdown)(void); + +typedef struct { + void* handle; + const char* service_boxid; + plugin_interface_func_initialize initialize; + plugin_interface_func_command command; + plugin_interface_func_shutdown shutdown; +} plugin_interfaces; + +// inteface functions that should be implemented by each plugin +EXPORT_API int web_provider_plugin_interface_initialize(); +EXPORT_API int web_provider_plugin_interface_command( + const request_cmd_type type, const BoxInfoPtr& boxInfo); +EXPORT_API int web_provider_plugin_interface_shutdown(); + +#ifdef __cplusplus +} +#endif + +#endif // BOX_PLUGIN_INTERFACE_H |