<?xml version="1.0" encoding="utf-8" ?>
-<manifest xmlns="http://tizen.org/ns/packages" package="livebox.web-provider" version="1.0" install-location="auto">
- <label>Web Livebox Provider</label>
+<manifest xmlns="http://tizen.org/ns/packages" package="livebox.web-provider" version="1.0" install-location="internal-only">
+ <label>Web Dynamic Box Provider</label>
<author email="yunchan.cho@samsung.com" href="www.samsung.com">Yunchan Cho</author>
- <description>Web Livebox Provider Executable</description>
-
- <ui-application appid="livebox.web-provider" exec="/usr/apps/livebox.web-provider/bin/web-provider" nodisplay="true" multiple="true" type="capp" taskmanage="false">
+ <description>Web Dynamic Box Provider Executable</description>
+ <ui-application appid="livebox.web-provider" exec="/usr/apps/livebox.web-provider/bin/web-provider" nodisplay="true" multiple="false" type="capp" taskmanage="false">
<icon>livebox.web-provider.png</icon>
- <label>Web Livebox Provider</label>
- <label xml:lang="en-us">Web Livebox Provider</label>
+ <label>Web Dynamic Box Provider</label>
+ <label xml:lang="en-us">Web Dynamic Box Provider</label>
+ <application-service>
+ <operation name="http://tizen.org/appcontrol/operation/dynamicbox/web/update"/>
+ <uri name="box-service"/>
+ </application-service>
</ui-application>
</manifest>
#git:framework/web/web-provider
Name: livebox.web-provider
Summary: web framework for livebox
-Version: 1.33.1
+Version: 1.36
Release: 1
Group: main/app
License: Flora License, Version 1.1
if (!supportedSizeChk) {
LogD("Not supported size: %s", size[configCnt]);
+ web_provider_plugin_release_info(jsonData);
return false;
}
}
+ //release the jsonData
+ web_provider_plugin_release_info(jsonData);
if (!mendatoryChk) {
LogD("Mandatory members don't exist ");
return false;
, m_currentTab(true)
, m_paused(false)
, m_updateNeeded(false)
+ , m_lastUpdateRequestTime()
{
LogD("enter");
try {
if (m_updateNeeded) {
m_updateNeeded = false;
- return update();
+ updateInternal();
} else {
m_view->resumeBox();
}
return true;
}
-bool Box::update()
+bool Box::update(time_t requestTime, std::string& contentInfo)
{
LogD("enter");
+ m_lastUpdateRequestTime = requestTime;
+ m_boxInfo->contentInfo = contentInfo;
if (m_paused) {
// update is dalayed until this box goes to current tab
m_updateNeeded = true;
}
try {
- RenderInfoPtr renderInfo = makeRenderInfo(renderTypeUpdate);
- m_boxBuffer->stopCanvasUpdate();
- m_view->showBox(renderInfo);
- ecore_idler_add(startUpdateRenderBufferIdlerCallback, m_boxBuffer.get());
+ updateInternal();
} catch (...) {
return false;
}
return m_currentTab;
}
+time_t Box::getLastUpdateRequestTime()
+{
+ return m_lastUpdateRequestTime;
+}
+
RenderInfoPtr Box::makeRenderInfo(const std::string& renderType) const
{
LogD("enter");
return renderInfo;
}
+void Box::updateInternal()
+{
+ LogD("enter");
+ RenderInfoPtr renderInfo = makeRenderInfo(renderTypeUpdate);
+ m_boxBuffer->stopCanvasUpdate();
+ m_view->showBox(renderInfo);
+ ecore_idler_add(startUpdateRenderBufferIdlerCallback, m_boxBuffer.get());
+}
+
void Box::setState(IBoxStatePtr state)
{
// assign new state
LogD("enter");
Box* This = static_cast<Box*>(data);
- This->update();
+ This->updateInternal();
return ECORE_CALLBACK_RENEW;
}
#ifndef BOX_H
#define BOX_H
+#include <string>
#include <memory>
+#include <ctime>
#include <Ecore.h>
#include <Plugin/IBoxPluginFactory.h>
#include "Buffer/IRenderBuffer.h"
bool pause(bool background);
bool openPd(int width, int height, double x, double y);
bool closePd();
- bool update();
+ bool update(time_t requestTime, std::string& contentInfo);
bool changePeriod(float period);
bool isCurrentTab();
+ time_t getLastUpdateRequestTime();
~Box();
private:
RenderInfoPtr makeRenderInfo(const std::string& renderType) const;
+ void updateInternal();
// IBoxContext
void setState(IBoxStatePtr state);
IRenderBufferPtr m_pdBuffer;
IRenderViewPtr m_view;
ITimerPtr m_updateTimer;
+ //IBoxStatePtr m_state;
// flag for knowing this box is on current tab
bool m_currentTab;
// flag for knowing this box has been already paused
bool m_paused;
// flag for knowing this box should be updated when the box is resumed
bool m_updateNeeded;
- //IBoxStatePtr m_state;
+ // timestamp for saving last update request from external app
+ time_t m_lastUpdateRequestTime;
friend class BoxSchemeHandler;
};
*/
#include <string>
#include <map>
+#include <ctime>
#include <ewk_context.h>
#include <Plugin/IBoxPluginFactory.h>
#include <Plugin/box_plugin_interface.h>
#include "BoxData.h"
#include "BoxManager.h"
+#define UPDATE_REQUEST_MIN_TIME 60 // seconds
+
BoxManager::BoxManager(IBoxPluginFactoryPtr factory)
: m_boxFactory(factory)
{
result = requestChangePeriod(boxInfo->instanceId, boxInfo->period);
break;
case REQUEST_CMD_UPDATE_BOX:
- result = requestUpdateBox(boxInfo->boxId);
+ result = requestUpdateBox(boxInfo->boxId, boxInfo->contentInfo);
break;
default:
LogD("not available request type");
return box->changePeriod(period);
}
-bool BoxManager::requestUpdateBox(std::string& boxId)
+bool BoxManager::requestUpdateBox(std::string& boxId, std::string& contentInfo)
{
LogD("enter");
IBoxPtr box;
box.reset();
+
+ time_t requestTime = time(NULL);
+
for (auto it = m_boxMap.begin(); it != m_boxMap.end(); ++it) {
if (it->first.find(boxId) == std::string::npos) {
continue;
}
box = it->second;
- box->update();
+ int interval = requestTime - box->getLastUpdateRequestTime();
+ if (interval < UPDATE_REQUEST_MIN_TIME) {
+ LogD("this update request is skipped");
+ continue;
+ }
+ // set last request time to new one
+ box->update(requestTime, contentInfo);
}
return true;
int width, int height, double x, double y);
virtual bool requestClosePd(std::string& instanceId);
virtual bool requestChangePeriod(std::string& instanceId, float period);
- virtual bool requestUpdateBox(std::string& instanceId);
+ virtual bool requestUpdateBox(std::string& boxId, std::string& contentInfo);
// ewk context deleter
struct EwkContextDeleter {
*/
#include <string.h>
+#include <ctime>
#include "Box.h"
#include "Service/AppControl.h"
#include "Service/PeriodChanger.h"
return false;
}
- box->update();
+ // In the future, new content info can be set by caller
+ box->update(time(NULL), box->m_boxInfo->contentInfo);
return true;
}
#ifndef I_BOX_H
#define I_BOX_H
+#include <string>
+#include <memory>
+#include <ctime>
#include <ewk_view.h>
#include <ewk_context.h>
virtual bool pause(bool background) = 0;
virtual bool openPd(int width, int height, double x, double y) = 0;
virtual bool closePd() = 0;
- virtual bool update() = 0;
+ virtual bool update(time_t requestTime, std::string& contentInfo) = 0;
+
+ // functions for getting/setting box's data by BoxManager
virtual bool changePeriod(float period) = 0;
virtual bool isCurrentTab() = 0;
+ virtual time_t getLastUpdateRequestTime() = 0;
//virtual IBox& operator=(const IBox& rhs) = 0;
//virtual bool operator==(const IBox& rhs) const = 0;
// For future, only window.appwidget will be used
window.appwidget = new Object();
+
+window.appwidget.fireReadyEvent = function () {
+ // If every functionalities of appwidget are initialized, fire appwidget ready event
+ var readyevent = document.createEvent("CustomEvent");
+ readyevent.initCustomEvent("appwidgetready", true, true);
+ document.dispatchEvent(readyevent);
+};
+
// these are functions for overriding standard javascript functions regarding event
var original_addEventListener = window.addEventListener;
var original_removeEventListener = window.removeEventListener;
} else {
original_addEventListener.call(window, event, callback, capture);
}
+
+ if (e == 'appwidgetready') {
+ // fire ready event to content
+ setTimeout(window.appwidget.fireReadyEvent(), 0);
+ }
};
window.removeEventListener = function(event, callback, capture) {
window.tizen.appwidget.scrollStart = window.appwidget.scrollStart;
window.tizen.appwidget.scrollStop = window.appwidget.scrollStop;
}
-
-// If every functionalities of appwidget are initialized, fire appwidget ready event
-var readyevent = document.createEvent("CustomEvent");
-readyevent.initCustomEvent("appwidgetready", true, true);
-document.dispatchEvent(readyevent);
* @author Yunchan Cho (yunchan.cho@samsung.com)
*/
#include <string>
+#include <app.h>
#include "BoxDaemon.h"
#include "BoxDaemonImpl.h"
{
return m_impl->stop();
}
+
+bool BoxDaemon::handleAppService(service_h service)
+{
+ return m_impl->handleAppService(service);
+}
#include <string>
#include <memory>
+#include <app.h>
#include <Core/Util/Noncopyable.h>
class BoxDaemonImpl;
public:
bool start(std::string& name);
bool stop();
+ bool handleAppService(service_h service);
explicit BoxDaemon();
~BoxDaemon();
#include <unistd.h>
#include <string>
#include <cstring>
+#include <app.h>
#include <aul.h>
#include <Ecore_X.h>
#include <provider.h>
#define MASTER_PROVIDER_PING_TIME 120.0f
+// These are string for handling application service from app
+static const std::string BOX_SERVICE_SCHEME("box-service://");
+static const std::string OPERATION_UPDATE_BOX(
+ "http://tizen.org/appcontrol/operation/dynamicbox/web/update");
+static const std::string CONTENT_INFO_KEY("content-info");
+
BoxDaemonImpl::BoxDaemonImpl()
: m_pluginConnector(BoxPluginConnector::create())
{
return true;
}
+bool BoxDaemonImpl::handleAppService(service_h service)
+{
+ LogD("enter");
+ int ret;
+ bool result = false;
+ Ecore_Job* jobResult = NULL;
+ char* operation;
+
+ ret = service_get_operation(service, &operation);
+ if (ret != SERVICE_ERROR_NONE) {
+ LogD("no operation");
+ return false;
+ }
+
+ if (OPERATION_UPDATE_BOX == operation) {
+ BoxInfoPtr info = handleOperationUpdate(service);
+ if (info) {
+ JobInfo* jobInfo = new JobInfo(REQUEST_CMD_UPDATE_BOX, info, this);
+ jobResult = ecore_job_add(requestBoxJobCallback, jobInfo);
+ if (jobResult) {
+ result = true;
+ }
+ }
+ } else {
+ LogD("unknown operation: %s", operation);
+ }
+
+ delete[] operation;
+ return result;
+}
+
int BoxDaemonImpl::connectedCallback(ProviderEventArgPtr arg, void* data)
{
LogD("enter");
if (arg->info.pd_create.w == 0 || arg->info.pd_create.h == 0) {
return -1;
}
-
- info->pdWidth = arg->info.pd_create.w;
+ //Use the screen width to fix the device width
+ ecore_x_window_size_get(0, &info->pdWidth, NULL);
info->pdHeight = arg->info.pd_create.h;
info->pdX = arg->info.pd_create.x;
info->pdY = arg->info.pd_create.y;
if (!type) {
return BoxInfoPtr();
}
-
BoxInfoPtr infoPtr = BoxInfoPtr(new BoxInfo(type, arg->pkgname, arg->id));
delete[] type;
return infoPtr;
}
+std::string BoxDaemonImpl::getBoxIdFromService(service_h service)
+{
+ LogD("enter");
+
+ int ret;
+ char* serviceUri = NULL;
+ ret = service_get_uri(service, &serviceUri);
+ if (ret != SERVICE_ERROR_NONE) {
+ LogD("no box uri");
+ return std::string();
+ }
+
+ std::string uri(serviceUri);
+ delete[] serviceUri;
+
+ if(uri.compare(0, BOX_SERVICE_SCHEME.size(), BOX_SERVICE_SCHEME)) {
+ // uri is not box-service scheme
+ return std::string();
+ }
+
+ std::string boxId = uri.substr(BOX_SERVICE_SCHEME.size());
+ return boxId;
+}
+
+bool BoxDaemonImpl::isServiceCallerBoxOwner(service_h service)
+{
+ LogD("enter");
+
+ int ret;
+
+ std::string boxId = getBoxIdFromService(service);
+ if (boxId.empty()) {
+ LogD("error box-id");
+ return false;
+ }
+
+ // check if caller is owner of this box
+ const char* appId = web_provider_livebox_get_app_id(boxId.c_str());
+ if (!appId) {
+ return false;
+ }
+ std::string ownerAppId(appId);
+ delete[] appId;
+
+ char* caller = NULL;
+ ret = service_get_caller(service, &caller);
+ if (ret != SERVICE_ERROR_NONE) {
+ return false;
+ }
+ std::string callerAppId(caller);
+
+ // release strings
+ delete[] caller;
+
+ if (ownerAppId != callerAppId) {
+ LogD("caller is not matched with owner of requested box");
+ return false;
+ }
+
+ return true;
+}
+
+BoxInfoPtr BoxDaemonImpl::handleOperationUpdate(service_h service)
+{
+ LogD("enter");
+
+ int ret;
+
+ if (!isServiceCallerBoxOwner(service)) {
+ return BoxInfoPtr();
+ }
+
+ std::string boxId = getBoxIdFromService(service);
+ if (boxId.empty()) {
+ LogD("error box-id");
+ return BoxInfoPtr();
+ }
+
+ char* contentInfo = NULL;
+ service_get_extra_data(service, CONTENT_INFO_KEY.c_str(), &contentInfo);
+
+ std::string type(getBoxType(boxId.c_str()));
+ if (type.empty()) {
+ LogD("no type for this box");
+ delete[] contentInfo;
+ return BoxInfoPtr();
+ }
+ BoxInfoPtr info = BoxInfoPtr(new BoxInfo(type, boxId, ""));
+ if (contentInfo) {
+ info->contentInfo = std::string(contentInfo);
+ }
+
+ // release string
+ delete[] contentInfo;
+
+ return info;
+}
+
Eina_Bool BoxDaemonImpl::pingToMasterCallback(void* data)
{
LogD("enter");
#include <string>
#include <memory>
+#include <app.h>
#include <provider.h>
#include <Eina.h>
#include <Ecore.h>
public:
bool start(std::string& name);
bool stop();
+ bool handleAppService(service_h service);
public:
explicit BoxDaemonImpl();
// common private functions
void setProviderCallbacks(ProviderCallbacks& callbacks);
const char* getBoxType(const char* boxId);
- //bool checkProviderEventArg(ProviderEventArgPtr arg);
BoxInfoPtr initializeBoxInfo(ProviderEventArgPtr arg);
+ // functions for handling appcontrol per operation
+ std::string getBoxIdFromService(service_h service);
+ bool isServiceCallerBoxOwner(service_h service);
+ BoxInfoPtr handleOperationUpdate(service_h service);
+
// callback for ping to master daemon
static Eina_Bool pingToMasterCallback(void* data);
* @author Yunchan Cho (yunchan.cho@samsung.com)
*/
#include <aul.h>
-#include <bundle.h>
-#include <appcore-efl.h>
+#include <app.h>
#include <Elementary.h>
#include <Core/Util/Log.h>
#include "BoxDaemon.h"
-static int app_create(void *data)
+static bool app_create(void *data)
{
LogD("app create");
- elm_config_preferred_engine_set("opengl_x11");
- return 0;
+ elm_config_preferred_engine_set("opengl_x11");
+ return true;
}
-static int app_reset(bundle *b, void *data)
+static void app_reset(service_h service, void *data)
{
- bool ret;
- const char *name;
-
LogD("app reset");
- name = bundle_get_val(b, "name");
- if (!name) {
- LogD("slave name is NULL");
- return -EINVAL;
- }
+ int ret;
+ char* name;
BoxDaemon *daemon = static_cast<BoxDaemon*>(data);
- std::string daemonName(name);
- ret = daemon->start(daemonName);
- if (!ret) {
- LogD("livebox daemon failed to start");
- aul_terminate_pid(getpid());
+ ret = service_get_extra_data(service, "name", &name);
+ if (ret == SERVICE_ERROR_NONE) {
+ std::string daemonName(name);
+ if(!(daemon->start(daemonName))) {
+ LogD("daemon failed to start");
+ aul_terminate_pid(getpid());
+ }
+ return;
}
- return static_cast<int>(ret);
+ daemon->handleAppService(service);
}
-static int app_pause(void *data)
+static void app_pause(void *data)
{
- return 0;
}
-static int app_resume(void *data)
+static void app_resume(void *data)
{
- return 0;
}
-static int app_terminate(void *data)
+static void app_terminate(void *data)
{
BoxDaemon *daemon = static_cast<BoxDaemon *>(data);
daemon->stop();
-
- return 0;
}
int main (int argc, char *argv[])
{
int ret;
- struct appcore_ops ops;
+ app_event_callback_s ops;
+ memset(&ops, 0x00, sizeof(app_event_callback_s));
BoxDaemon daemon;
ops.create = app_create;
ops.terminate = app_terminate;
ops.pause = app_pause;
ops.resume = app_resume;
- ops.reset = app_reset;
- ops.data = &daemon;
+ ops.service = app_reset;
#if !defined(TIZEN_PUBLIC)
setenv("COREGL_FASTPATH", "1", 1);
setenv("CAIRO_GL_LAZY_FLUSHING", "yes", 1);
setenv("ELM_IMAGE_CACHE", "0", 1);
- ret = appcore_efl_main("web-provider", &argc, &argv, &ops);
+ ret = app_efl_main(&argc, &argv, &ops, &daemon);
return ret;
}
#include <Ecore.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 "AppBoxPdHelper.h"
#include "AppBoxRenderView.h"
-#define RENDER_MAX_TIME 10.0
+#define RENDER_MAX_TIME 30.0
// injection javascript file regarding creating js object used by box and pd
static const std::string injectionFile("/usr/share/web-provider/injection.js");
cbs->webCrash = DPL::MakeDelegate(this, &AppBoxRenderView::crashWebProcessCallback);
wrt->SetUserDelegates(cbs);
- // To support transparent background
- evas_object_color_set(wrt->GetCurrentWebview(), 0, 0, 0, 0);
- //evas_object_layer_set(wrt->GetCurrentWebview(), EVAS_LAYER_MAX);
-
+ // set basic webview setting
+ setWebViewBasicSetting(wrt->GetCurrentWebview());
// To know starting point for updating buffer
evas_object_smart_callback_add(
wrt->GetCurrentWebview(),
LogD("enter");
clearSnapShot();
m_snapshot = m_renderBuffer->getSnapshot();
- //evas_object_layer_set(m_snapshot, EVAS_LAYER_MAX);
return m_snapshot;
}
{
LogD("enter");
if (m_snapshot) {
- //evas_object_layer_set(m_snapshot, EVAS_LAYER_MIN);
evas_object_del(m_snapshot);
m_snapshot = NULL;
}
}
}
+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, 0);
+ ewk_view_visibility_set(webview, EINA_TRUE);
+}
+
Eina_Bool AppBoxRenderView::fireRenderTimerCallback(void* data)
{
LogD("enter");
{
LogD("enter");
- // To support transparent background
- evas_object_color_set(child, 0, 0, 0, 0);
-
if (m_pdHelper) {
Evas* parentCanvas = evas_object_evas_get(parent);
Evas* childCanvas = evas_object_evas_get(child);
}
}
- ewk_view_visibility_set(child, EINA_TRUE);
+ setWebViewBasicSetting(child);
evas_object_show(child);
}
WrtCorePtr createWrtCore(
std::string& startUrl, Evas_Object* win, EwkContextPtr ewkContext);
+ void setWebViewBasicSetting(Evas_Object* webview);
void destroyWrtCore(WrtCorePtr wrt);
void destroyBoxWrtCore();
void destroyPdWrtCore();