[Tizen] Add web-engine-lite plugin
authorSunghyun kim <scholb.kim@samsung.com>
Tue, 13 Nov 2018 07:53:49 +0000 (16:53 +0900)
committerSunghyun kim <scholb.kim@samsung.com>
Tue, 13 Nov 2018 08:18:24 +0000 (17:18 +0900)
Change-Id: I5c1d1b4c80bac11f5c7790d7471d1baf2ca4f599

build/tizen/configure.ac
build/tizen/web-engine-lite/Makefile.am [new file with mode: 0644]
build/tizen/web-engine-lite/configure.ac [new file with mode: 0644]
dali-extension/web-engine-lite/file.list [new file with mode: 0644]
dali-extension/web-engine-lite/tizen-web-engine-lite.cpp [new file with mode: 0644]
dali-extension/web-engine-lite/tizen-web-engine-lite.h [new file with mode: 0644]
packaging/dali-extension.spec

index 6341d5e..54344b9 100755 (executable)
@@ -20,6 +20,7 @@ AC_CONFIG_SUBDIRS(key)
 AC_CONFIG_SUBDIRS(video-player)
 AC_CONFIG_SUBDIRS(web-engine-chromium)
 AC_CONFIG_SUBDIRS(image-loader)
+AC_CONFIG_SUBDIRS(web-engine-lite)
 
 AC_CONFIG_FILES([
 Makefile
diff --git a/build/tizen/web-engine-lite/Makefile.am b/build/tizen/web-engine-lite/Makefile.am
new file mode 100644 (file)
index 0000000..7496c3d
--- /dev/null
@@ -0,0 +1,45 @@
+#
+# Copyright (c) 2018 Samsung Electronics Co., Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (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
+#
+# 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.
+#
+
+# Build the Dali web engine lite plugin
+
+extension_src_dir = ../../../dali-extension
+
+include ../../../dali-extension/web-engine-lite/file.list
+
+lib_LTLIBRARIES =
+
+lib_LTLIBRARIES += libdali-web-engine-lite-plugin.la
+
+libdali_web_engine_lite_plugin_la_SOURCES = \
+                     $(web_engine_lite_plugin_src_files)
+
+libdali_web_engine_lite_plugin_la_DEPENDENCIES =
+
+libdali_web_engine_lite_plugin_la_CXXFLAGS = \
+                      $(DALI_CFLAGS) \
+                      $(LIBTUV_CFLAGS) \
+                      $(WEB_ENGINE_LITE_CFLAGS) \
+                      -Werror -Wall
+
+libdali_web_engine_lite_plugin_la_LIBADD = \
+                      $(DALI_LIBS) \
+                      $(LIBTUV_LIBS) \
+                      $(WEB_ENGINE_LITE_LIBS)
+
+libdali_web_engine_lite_plugin_la_LDFLAGS = \
+                      -rdynamic
+
diff --git a/build/tizen/web-engine-lite/configure.ac b/build/tizen/web-engine-lite/configure.ac
new file mode 100644 (file)
index 0000000..cb6a397
--- /dev/null
@@ -0,0 +1,29 @@
+4_define([dali_version],[0.1.0])
+AC_INIT([dali], [dali_version])
+AM_INIT_AUTOMAKE([-Wall foreign])
+
+AC_CONFIG_MACRO_DIR([m4])
+
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+LT_INIT
+
+DALI_EXTENSION_VERSION=dali_version
+AC_SUBST(DALI_EXTENSION_VERSION)
+
+PKG_CHECK_MODULES([DALI], [dali-core dali-adaptor dali-toolkit])
+PKG_CHECK_MODULES(WAYLAND, libtbm)
+PKG_CHECK_MODULES([LIBTUV], [libtuv])
+PKG_CHECK_MODULES([WEB_ENGINE_LITE], [lightweight-web-engine-dali-plugin])
+
+devincludepath=${includedir}
+AC_SUBST(devincludepath)
+
+AC_CONFIG_FILES([
+Makefile
+])
+
+AC_OUTPUT
diff --git a/dali-extension/web-engine-lite/file.list b/dali-extension/web-engine-lite/file.list
new file mode 100644 (file)
index 0000000..e68e82d
--- /dev/null
@@ -0,0 +1,2 @@
+web_engine_lite_plugin_src_files = \
+   $(extension_src_dir)/web-engine-lite/tizen-web-engine-lite.cpp
diff --git a/dali-extension/web-engine-lite/tizen-web-engine-lite.cpp b/dali-extension/web-engine-lite/tizen-web-engine-lite.cpp
new file mode 100644 (file)
index 0000000..28d246c
--- /dev/null
@@ -0,0 +1,975 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (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
+ *
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include "tizen-web-engine-lite.h"
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/stage.h>
+#include <dali/public-api/events/key-event.h>
+#include <dali/public-api/events/touch-data.h>
+
+#include <libtuv/uv.h>
+#include <unistd.h>
+
+// The plugin factories
+extern "C" DALI_EXPORT_API Dali::WebEnginePlugin* CreateWebEnginePlugin( void )
+{
+  return new Dali::Plugin::TizenWebEngineLite;
+}
+
+extern "C" DALI_EXPORT_API void DestroyWebEnginePlugin( Dali::WebEnginePlugin* plugin )
+{
+  if( plugin != NULL )
+  {
+    delete plugin;
+  }
+}
+
+#define TO_CONTAINER(ptr) (((TizenWebEngineLite*)ptr)->mWebContainer)
+
+static bool gIsNeedsUpdate = false;
+static bool gIsFirstTime = true;
+static uv_async_t gLauncherHandle;
+static pthread_mutex_t gMutex;
+static bool gIsAliveMainLoop = false;
+static int gDaliNumber = 0;
+
+class Locker {
+public:
+  Locker(pthread_mutex_t& lock)
+    : m_lock( lock )
+  {
+    pthread_mutex_lock( &m_lock );
+  }
+
+  ~Locker()
+  {
+    pthread_mutex_unlock( &m_lock );
+  }
+protected:
+  pthread_mutex_t m_lock;
+};
+
+struct UVAsyncHandleData {
+  std::function<void(void*)> cb;
+  void* data;
+};
+
+static bool IsAliveMainThread()
+{
+  return gIsAliveMainLoop;
+}
+
+static void InitMainThread( void* (*f)(void*), pthread_t& t )
+{
+  pthread_mutex_init(&gMutex, NULL);
+
+  pthread_mutex_lock(&gMutex);
+  pthread_attr_t attr;
+  pthread_attr_init(&attr);
+  pthread_create(&t, &attr, f, NULL);
+  pthread_mutex_lock(&gMutex);
+  pthread_mutex_unlock(&gMutex);
+}
+
+LWE::KeyValue KeyStringToKeyValue( const char* DALIKeyString, bool isShiftPressed )
+{
+  LWE::KeyValue keyValue = LWE::KeyValue::UnidentifiedKey;
+  if( strcmp( "Left", DALIKeyString ) == 0 )
+  {
+    keyValue = LWE::KeyValue::ArrowLeftKey;
+  }
+  else if( strcmp( "Right", DALIKeyString ) == 0 )
+  {
+    keyValue = LWE::KeyValue::ArrowRightKey;
+  }
+  else if( strcmp( "Up", DALIKeyString ) == 0 )
+  {
+    keyValue = LWE::KeyValue::ArrowUpKey;
+  }
+  else if( strcmp( "Down", DALIKeyString ) == 0 )
+  {
+    keyValue = LWE::KeyValue::ArrowDownKey;
+  }
+  else if( strcmp( "space", DALIKeyString ) == 0 )
+  {
+    keyValue = LWE::KeyValue::SpaceKey;
+  }
+  else if( strcmp( "Return", DALIKeyString ) == 0 )
+  {
+    keyValue = LWE::KeyValue::EnterKey;
+  }
+  else if( strcmp( "BackSpace", DALIKeyString ) == 0 )
+  {
+    keyValue = LWE::KeyValue::BackspaceKey;
+  }
+  else if( strcmp( "Escape", DALIKeyString ) == 0 )
+  {
+    keyValue = LWE::KeyValue::EscapeKey;
+  }
+  else if( strcmp( "minus", DALIKeyString ) == 0 )
+  {
+    if( isShiftPressed )
+    {
+      keyValue = LWE::KeyValue::MinusMarkKey;
+    }
+    else
+    {
+      keyValue = LWE::KeyValue::UnderScoreMarkKey;
+    }
+  }
+  else if( strcmp( "equal", DALIKeyString ) == 0 )
+  {
+    if( isShiftPressed )
+    {
+      keyValue = LWE::KeyValue::PlusMarkKey;
+    }
+    else
+    {
+      keyValue = LWE::KeyValue::EqualitySignKey;
+    }
+  }
+  else if( strcmp( "bracketleft", DALIKeyString ) == 0 )
+  {
+    if( isShiftPressed )
+    {
+      keyValue = LWE::KeyValue::LeftCurlyBracketMarkKey;
+    }
+    else
+    {
+      keyValue = LWE::KeyValue::LeftSquareBracketKey;
+    }
+  }
+  else if( strcmp( "bracketright", DALIKeyString ) == 0 )
+  {
+    if( isShiftPressed )
+    {
+      keyValue = LWE::KeyValue::RightCurlyBracketMarkKey;
+    }
+    else
+    {
+      keyValue = LWE::KeyValue::RightSquareBracketKey;
+    }
+  }
+  else if( strcmp( "semicolon", DALIKeyString ) == 0 )
+  {
+    if( isShiftPressed )
+    {
+      keyValue = LWE::KeyValue::ColonMarkKey;
+    }
+    else
+    {
+      keyValue = LWE::KeyValue::SemiColonMarkKey;
+    }
+  }
+  else if( strcmp( "apostrophe", DALIKeyString ) == 0 )
+  {
+    if( isShiftPressed )
+    {
+      keyValue = LWE::KeyValue::DoubleQuoteMarkKey;
+    }
+    else
+    {
+      keyValue = LWE::KeyValue::SingleQuoteMarkKey;
+    }
+  }
+  else if( strcmp( "comma", DALIKeyString ) == 0 )
+  {
+    if( isShiftPressed )
+    {
+      keyValue = LWE::KeyValue::LessThanMarkKey;
+    }
+    else
+    {
+      keyValue = LWE::KeyValue::CommaMarkKey;
+    }
+  }
+  else if( strcmp( "period", DALIKeyString ) == 0 )
+  {
+    if( isShiftPressed )
+    {
+      keyValue = LWE::KeyValue::GreaterThanSignKey;
+    }
+    else
+    {
+      keyValue = LWE::KeyValue::PeriodKey;
+    }
+  }
+  else if( strcmp( "slash", DALIKeyString ) == 0 )
+  {
+    if( isShiftPressed )
+    {
+      keyValue = LWE::KeyValue::QuestionMarkKey;
+    }
+    else
+    {
+      keyValue = LWE::KeyValue::SlashKey;
+    }
+  }
+  else if( strlen( DALIKeyString ) == 1 )
+  {
+    char ch = DALIKeyString[0];
+    if( ch >= '0' && ch <= '9' )
+    {
+      if( isShiftPressed )
+      {
+        switch( ch )
+        {
+          case '1':
+          {
+            keyValue = LWE::KeyValue::ExclamationMarkKey;
+            break;
+          }
+          case '2':
+          {
+            keyValue = LWE::KeyValue::AtMarkKey;
+            break;
+          }
+          case '3':
+          {
+            keyValue = LWE::KeyValue::SharpMarkKey;
+            break;
+          }
+          case '4':
+          {
+            keyValue = LWE::KeyValue::DollarMarkKey;
+            break;
+          }
+          case '5':
+          {
+            keyValue = LWE::KeyValue::PercentMarkKey;
+            break;
+          }
+          case '6':
+          {
+            keyValue = LWE::KeyValue::CaretMarkKey;
+            break;
+          }
+          case '7':
+          {
+            keyValue = LWE::KeyValue::AmpersandMarkKey;
+            break;
+          }
+          case '8':
+          {
+            keyValue = LWE::KeyValue::AsteriskMarkKey;
+            break;
+          }
+          case '9':
+          {
+            keyValue = LWE::KeyValue::LeftParenthesisMarkKey;
+            break;
+          }
+          case '0':
+          {
+            keyValue = LWE::KeyValue::RightParenthesisMarkKey;
+            break;
+          }
+        }
+      }
+      else
+      {
+        keyValue = ( LWE::KeyValue )( LWE::KeyValue::Digit0Key + ch - '0' );
+      }
+    }
+    else if( ch >= 'a' && ch <= 'z' )
+    {
+      int kv = LWE::KeyValue::LowerAKey + ch - 'a';
+      if( isShiftPressed )
+      {
+        kv -= ( 'z' - 'a' );
+        kv -= 7;
+      }
+      keyValue = (LWE::KeyValue)kv;
+    }
+  }
+  return keyValue;
+}
+
+
+namespace Dali
+{
+
+namespace Plugin
+{
+
+namespace
+{
+
+const int TIMER_INTERVAL( 20 );
+
+} // unnamed namespace
+
+TizenWebEngineLite::TizenWebEngineLite()
+: mThreadHandle(),
+  mIsMouseLbuttonDown( false ),
+  mTimer(),
+  mUrl( "" ),
+  mOutputWidth( 0 ),
+  mOutputHeight( 0 ),
+  mOutputStride( 0 ),
+  mOutputBuffer ( NULL ),
+  mCanGoBack( false ),
+  mCanGoForward( false ),
+  mIsRunning( false ),
+  mWebContainer( NULL ),
+#ifdef STARFISH_DALI_TBMSURFACE
+  mTbmSurface( NULL ),
+  mNativeImageSourcePtr( NULL )
+#else
+  mBufferImage( NULL )
+#endif
+{
+}
+
+TizenWebEngineLite::~TizenWebEngineLite()
+{
+}
+
+bool TizenWebEngineLite::UpdateBuffer()
+{
+  if( mIsRunning == false )
+  {
+    return true;
+  }
+
+  if( gIsNeedsUpdate )
+  {
+    Locker l( gMutex );
+#ifdef STARFISH_DALI_TBMSURFACE
+    Dali::Stage::GetCurrent().KeepRendering( 0.0f );
+#else
+    if( !mBufferImage )
+    {
+      return false;
+    }
+    mBufferImage.Update();
+#endif
+    gIsNeedsUpdate = false;
+  }
+
+  return true;
+}
+
+void TizenWebEngineLite::StartMainThreadIfNeeds()
+{
+  if ( !IsAliveMainThread() )
+  {
+    InitMainThread( StartMainThread, mThreadHandle );
+  }
+}
+
+void TizenWebEngineLite::CreateInstance()
+{
+  gDaliNumber++;
+  auto cb = []( void* data )
+  {
+    TizenWebEngineLite* engine = static_cast< TizenWebEngineLite* >( data );
+    if ( !LWE::LWE::IsInitialized() )
+    {
+      LWE::LWE::Initialize("/tmp/StarFish_localStorage.txt",
+                           "/tmp/StarFish_Cookies.txt", "/tmp/StarFish-cache");
+    }
+    engine->mWebContainer = LWE::WebContainer::Create(
+        engine->mOutputBuffer, engine->mOutputWidth, engine->mOutputHeight,
+        engine->mOutputStride, 1.0, "SamsungOne", "ko-KR", "Asia/Seoul" );
+    TO_CONTAINER( data )->RegisterOnRenderedHandler(
+        [ engine ]( LWE::WebContainer* container, const LWE::WebContainer::RenderResult& renderResult )
+        {
+          engine->onRenderedHandler( container, renderResult );
+        } );
+    TO_CONTAINER( data )->RegisterOnReceivedErrorHandler(
+        [ engine ]( LWE::WebContainer* container, LWE::ResourceError error )
+        {
+          engine->mCanGoBack = container->CanGoBack();
+          engine->mCanGoForward = container->CanGoForward();
+          engine->onReceivedError( container, error );
+        });
+    TO_CONTAINER( data )->RegisterOnPageStartedHandler(
+        [ engine ]( LWE::WebContainer* container, const std::string& url )
+        {
+          engine->mUrl = url;
+          engine->mCanGoBack = container->CanGoBack();
+          engine->mCanGoForward = container->CanGoForward();
+          engine->onPageStartedHandler( container, url );
+        });
+    TO_CONTAINER( data )->RegisterOnPageLoadedHandler(
+        [ engine ]( LWE::WebContainer* container, const std::string& url )
+        {
+          engine->mUrl = url;
+          engine->mCanGoBack = container->CanGoBack();
+          engine->mCanGoForward = container->CanGoForward();
+          engine->onPageFinishedHandler( container, url );
+        });
+    TO_CONTAINER( data )->RegisterOnLoadResourceHandler(
+        [ engine ]( LWE::WebContainer* container, const std::string& url )
+        {
+          engine->mUrl = url;
+          engine->mCanGoBack = container->CanGoBack();
+          engine->mCanGoForward = container->CanGoForward();
+          engine->onLoadResourceHandler( container, url );
+        });
+    };
+    SendAsyncHandle( cb );
+}
+
+void TizenWebEngineLite::Create( int width, int height, const std::string& locale, const std::string& timezoneId )
+{
+  mTimer = Dali::Timer::New( TIMER_INTERVAL );
+  mTimer.TickSignal().Connect( this, &TizenWebEngineLite::UpdateBuffer );
+  mTimer.Start();
+
+  StartMainThreadIfNeeds();
+
+  mIsRunning = true;
+  mOutputWidth = width;
+  mOutputHeight = height;
+  mOutputStride = width * sizeof( uint32_t );
+  mOutputBuffer = ( uint8_t* )malloc( width * height * sizeof( uint32_t ) );
+
+  if( gIsFirstTime == true )
+  {
+    gIsFirstTime = false;
+
+    onRenderedHandler = [this]( LWE::WebContainer* c, const LWE::WebContainer::RenderResult& renderResult )
+    {
+      Locker l( gMutex );
+      size_t w = mOutputWidth;
+      size_t h = mOutputHeight;
+      if( renderResult.updatedWidth != w || renderResult.updatedHeight != h )
+      {
+        return;
+      }
+
+      uint8_t* dstBuffer;
+      size_t dstStride;
+
+#ifdef STARFISH_DALI_TBMSURFACE
+      tbm_surface_info_s tbmSurfaceInfo;
+      if( tbm_surface_map( mTbmSurface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &tbmSurfaceInfo ) != TBM_SURFACE_ERROR_NONE )
+      {
+        DALI_LOG_ERROR( "Fail to map tbm_surface\n" );
+      }
+
+      DALI_ASSERT_ALWAYS( tbmSurfaceInfo.format == TBM_FORMAT_ABGR8888 && "Unsupported TizenWebEngineLite tbm format" );
+
+      dstBuffer = tbmSurfaceInfo.planes[0].ptr;
+      dstStride = tbmSurfaceInfo.planes[0].stride;
+
+#else
+      dstBuffer = mBufferImage.GetBuffer();
+      dstStride = mBufferImage.GetBufferStride();
+#endif
+
+      uint32_t srcStride = renderResult.updatedWidth * sizeof(uint32_t);
+      uint8_t* srcBuffer = static_cast< uint8_t* >( renderResult.updatedBufferAddress );
+
+      if (dstStride == srcStride)
+      {
+        memcpy( dstBuffer, srcBuffer, tbmSurfaceInfo.planes[0].size );
+      }
+      else
+      {
+        for ( auto y = renderResult.updatedY; y < ( renderResult.updatedHeight + renderResult.updatedY ); y++ )
+        {
+          auto start = renderResult.updatedX;
+          memcpy( dstBuffer + ( y * dstStride ) + ( start * 4 ), srcBuffer + ( y * srcStride ) + ( start * 4 ), srcStride );
+        }
+      }
+
+#ifdef STARFISH_DALI_TBMSURFACE
+      if( tbm_surface_unmap( mTbmSurface ) != TBM_SURFACE_ERROR_NONE )
+      {
+        DALI_LOG_ERROR( "Fail to unmap tbm_surface\n" );
+      }
+#endif
+      gIsNeedsUpdate = true;
+    };
+
+    onReceivedError = []( LWE::WebContainer* container, LWE::ResourceError error ) {
+    };
+    onPageStartedHandler = []( LWE::WebContainer* container, const std::string& url ) {
+    };
+    onPageFinishedHandler = []( LWE::WebContainer* container, const std::string& url ) {
+    };
+    onLoadResourceHandler = []( LWE::WebContainer* container, const std::string& url ) {
+    };
+  }
+
+#ifdef STARFISH_DALI_TBMSURFACE
+  mTbmSurface = tbm_surface_create( width, height, TBM_FORMAT_ABGR8888 );
+  mNativeImageSourcePtr = Dali::NativeImageSource::New( mTbmSurface );
+#else
+  mBufferImage = Dali::BufferImage::New( width, height, Dali::Pixel::RGBA8888 );
+#endif
+
+  CreateInstance();
+  while ( true )
+  {
+      if ( mWebContainer )
+      {
+          break;
+      }
+      usleep( 100 );
+  }
+}
+
+void TizenWebEngineLite::Destroy()
+{
+  if( !mWebContainer )
+  {
+    return;
+  }
+
+  if( mIsRunning == true )
+  {
+    mIsRunning = false;
+
+#ifdef STARFISH_DALI_TBMSURFACE
+    if( mTbmSurface != NULL && tbm_surface_destroy( mTbmSurface ) != TBM_SURFACE_ERROR_NONE )
+    {
+      DALI_LOG_ERROR( "Failed to destroy tbm_surface\n" );
+    }
+#endif
+
+    DestroyInstance();
+    StopLoop();
+
+    int status;
+    pthread_join( mThreadHandle, ( void** )&status );
+
+    mWebContainer = NULL;
+  }
+}
+
+void TizenWebEngineLite::DestroyInstance()
+{
+       DALI_ASSERT_ALWAYS( mWebContainer );
+       auto cb = []( void* data )
+       {
+         TizenWebEngineLite* engine = static_cast< TizenWebEngineLite* >( data );
+
+         TO_CONTAINER( data )->Destroy();
+
+         while ( !engine->mAsyncHandlePool.empty() )
+         {
+           UVAsyncHandleData* handleData = NULL;
+           {
+             Locker l( gMutex );
+             handleData = ( UVAsyncHandleData* )*engine->mAsyncHandlePool.begin();
+             engine->mAsyncHandlePool.erase( engine->mAsyncHandlePool.begin() );
+           }
+
+           if ( handleData ) {
+             handleData->cb( handleData->data );
+             delete handleData;
+           }
+         }
+         gDaliNumber--;
+       };
+       SendAsyncHandle( cb );
+}
+
+Dali::NativeImageInterfacePtr TizenWebEngineLite::GetNativeImageSource()
+{
+  return mNativeImageSourcePtr;
+}
+
+void TizenWebEngineLite::LoadUrl( const std::string& url )
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+  auto cb = [url]( void* data )
+  {
+    TO_CONTAINER( data )->LoadURL( url );
+  };
+  SendAsyncHandle( cb );
+}
+
+const std::string& TizenWebEngineLite::GetUrl()
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+  return mUrl;
+}
+
+void TizenWebEngineLite::LoadHTMLString( const std::string& str )
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+  auto cb = [str]( void* data )
+  {
+    TO_CONTAINER( data )->LoadData( str );
+  };
+  SendAsyncHandle( cb );
+}
+
+void TizenWebEngineLite::Reload()
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+  auto cb = []( void* data )
+  {
+    TO_CONTAINER( data )->Reload();
+  };
+  SendAsyncHandle( cb );
+}
+
+void TizenWebEngineLite::StopLoading()
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+  auto cb = []( void* data )
+  {
+    TO_CONTAINER( data )->StopLoading();
+  };
+  SendAsyncHandle( cb );
+}
+
+void TizenWebEngineLite::GoBack()
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+  auto cb = []( void* data )
+  {
+    TO_CONTAINER( data )->GoBack();
+  };
+  SendAsyncHandle( cb );
+}
+
+void TizenWebEngineLite::GoForward()
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+  auto cb = []( void* data )
+  {
+    TO_CONTAINER( data )->GoForward();
+  };
+  SendAsyncHandle( cb );
+}
+
+bool TizenWebEngineLite::CanGoBack()
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+  return mCanGoBack;
+}
+
+bool TizenWebEngineLite::CanGoForward()
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+  return mCanGoForward;
+}
+
+void TizenWebEngineLite::EvaluateJavaScript( const std::string& script )
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+  auto cb = [script]( void* data ) {
+      TO_CONTAINER( data )->EvaluateJavaScript( script );
+  };
+  SendAsyncHandle( cb );
+}
+
+void TizenWebEngineLite::AddJavaScriptInterface( const std::string& exposedObjectName, const std::string& jsFunctionName, std::function< std::string(const std::string&) > callback )
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+  auto cb = [exposedObjectName, jsFunctionName, callback]( void* data )
+  {
+    TO_CONTAINER( data )->AddJavaScriptInterface( exposedObjectName, jsFunctionName, callback );
+  };
+  SendAsyncHandle( cb );
+}
+
+void TizenWebEngineLite::RemoveJavascriptInterface( const std::string& exposedObjectName, const std::string& jsFunctionName )
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+  auto cb = [exposedObjectName, jsFunctionName]( void* data )
+  {
+    TO_CONTAINER( data )->RemoveJavascriptInterface( exposedObjectName, jsFunctionName );
+  };
+  SendAsyncHandle( cb );
+}
+
+void TizenWebEngineLite::ClearHistory()
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+  auto cb = []( void* data )
+  {
+    TizenWebEngineLite* engine = static_cast< TizenWebEngineLite* >( data );
+    TO_CONTAINER( data )->ClearHistory();
+    engine->mCanGoBack = TO_CONTAINER( data )->CanGoBack();
+  };
+  SendAsyncHandle( cb );
+}
+
+void TizenWebEngineLite::ClearCache()
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+  auto cb = []( void* data )
+  {
+    TO_CONTAINER( data )->ClearCache();
+  };
+  SendAsyncHandle( cb );
+}
+
+void TizenWebEngineLite::SetSize( int width, int height )
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+
+  if( mOutputWidth != ( size_t )width || mOutputHeight != ( size_t )height )
+  {
+    Locker l( gMutex );
+         mOutputWidth = width;
+         mOutputHeight = height;
+         mOutputStride = width * sizeof(uint32_t);
+
+#ifdef STARFISH_DALI_TBMSURFACE
+         tbm_surface_h prevTbmSurface = mTbmSurface;
+         mTbmSurface = tbm_surface_create( width, height, TBM_FORMAT_ABGR8888 );
+         Dali::Any source( mTbmSurface );
+         mNativeImageSourcePtr->SetSource( source );
+         if( prevTbmSurface != NULL && tbm_surface_destroy( prevTbmSurface ) != TBM_SURFACE_ERROR_NONE )
+         {
+                 DALI_LOG_ERROR( "Failed to destroy tbm_surface\n" );
+         }
+#endif
+
+         auto cb = []( void* data )
+    {
+           TizenWebEngineLite* engine = static_cast< TizenWebEngineLite* >( data );
+
+           Locker l( gMutex );
+           if (engine->mOutputBuffer) {
+             free(engine->mOutputBuffer);
+             engine->mOutputBuffer = NULL;
+           }
+
+                 engine->mOutputBuffer = ( uint8_t* )malloc( engine->mOutputWidth * engine->mOutputHeight * sizeof( uint32_t ) );
+                 engine->mOutputStride = engine->mOutputWidth * sizeof( uint32_t );
+                 engine->mWebContainer->UpdateBuffer( engine->mOutputBuffer, engine->mOutputWidth,
+                     engine->mOutputHeight, engine->mOutputStride );
+         };
+         SendAsyncHandle( cb );
+  }
+}
+
+void TizenWebEngineLite::DispatchMouseDownEvent( float x, float y )
+{
+       DALI_ASSERT_ALWAYS( mWebContainer );
+       if (!mIsRunning)
+       {
+         return;
+       }
+
+       auto cb = [x, y]( void* data )
+  {
+         TO_CONTAINER( data )->DispatchMouseDownEvent( LWE::MouseButtonValue::LeftButton, LWE::MouseButtonsValue::LeftButtonDown, x, y );
+  };
+       SendAsyncHandle( cb );
+}
+
+void TizenWebEngineLite::DispatchMouseUpEvent( float x, float y )
+{
+  DALI_ASSERT_ALWAYS( mWebContainer );
+  if (!mIsRunning)
+  {
+    return;
+  }
+
+  auto cb = [x, y]( void* data )
+  {
+    TO_CONTAINER( data )->DispatchMouseUpEvent( LWE::MouseButtonValue::NoButton, LWE::MouseButtonsValue::NoButtonDown, x, y );
+  };
+  SendAsyncHandle( cb );
+}
+
+void TizenWebEngineLite::DispatchMouseMoveEvent( float x, float y, bool isLButtonPressed, bool isRButtonPressed )
+{
+       DALI_ASSERT_ALWAYS( mWebContainer );
+       if (!mIsRunning)
+       {
+         return;
+       }
+
+       auto cb = [x, y, isLButtonPressed]( void* data )
+  {
+         TO_CONTAINER( data )->DispatchMouseMoveEvent(
+             isLButtonPressed ? LWE::MouseButtonValue::LeftButton
+                 : LWE::MouseButtonValue::NoButton,
+             isLButtonPressed ? LWE::MouseButtonsValue::LeftButtonDown
+                 : LWE::MouseButtonsValue::NoButtonDown, x, y );
+  };
+       SendAsyncHandle( cb );
+}
+
+bool TizenWebEngineLite::SendTouchEvent( const TouchData& touch )
+{
+  size_t pointCount = touch.GetPointCount();
+  if( pointCount == 1 )
+  {
+    // Single touch event
+    Dali::PointState::Type pointState = touch.GetState( 0 );
+    const Dali::Vector2& screen = touch.GetLocalPosition( 0 );
+
+    if( pointState == Dali::PointState::DOWN )
+    {
+      DispatchMouseDownEvent( screen.x, screen.y );
+      mIsMouseLbuttonDown = true;
+    }
+    else if( pointState == Dali::PointState::UP )
+    {
+      DispatchMouseUpEvent( screen.x, screen.y );
+      mIsMouseLbuttonDown = false;
+    }
+    else
+    {
+      DispatchMouseMoveEvent( screen.x, screen.y, mIsMouseLbuttonDown, false );
+    }
+  }
+
+  return false;
+}
+
+void TizenWebEngineLite::DispatchKeyDownEvent( LWE::KeyValue keyCode )
+{
+       DALI_ASSERT_ALWAYS( mWebContainer );
+       if (!mIsRunning)
+       {
+         return;
+       }
+
+       auto cb = [keyCode]( void* data )
+  {
+         TO_CONTAINER( data )->DispatchKeyDownEvent( keyCode );
+  };
+       SendAsyncHandle( cb );
+}
+
+void TizenWebEngineLite::DispatchKeyPressEvent( LWE::KeyValue keyCode )
+{
+       DALI_ASSERT_ALWAYS( mWebContainer );
+       if (!mIsRunning)
+       {
+         return;
+       }
+
+       auto cb = [keyCode]( void* data )
+  {
+         TO_CONTAINER( data )->DispatchKeyPressEvent( keyCode );
+  };
+       SendAsyncHandle( cb );
+}
+
+void TizenWebEngineLite::DispatchKeyUpEvent( LWE::KeyValue keyCode )
+{
+       DALI_ASSERT_ALWAYS( mWebContainer );
+       if (!mIsRunning)
+       {
+         return;
+       }
+
+       auto cb = [keyCode]( void* data )
+  {
+         TO_CONTAINER( data )->DispatchKeyUpEvent(keyCode);
+  };
+       SendAsyncHandle( cb );
+}
+
+bool TizenWebEngineLite::SendKeyEvent( const Dali::KeyEvent& event )
+{
+  LWE::KeyValue keyValue = LWE::KeyValue::UnidentifiedKey;
+  if( 32 < event.keyPressed.c_str()[0] && 127 > event.keyPressed.c_str()[0] )
+  {
+    keyValue = static_cast<LWE::KeyValue>(event.keyPressed.c_str()[0]);
+  }
+  else
+  {
+    keyValue = KeyStringToKeyValue( event.keyPressedName.c_str(), event.keyModifier & 1 );
+  }
+  if( event.state == Dali::KeyEvent::Down )
+  {
+    DispatchKeyDownEvent( keyValue );
+    DispatchKeyPressEvent( keyValue );
+  }
+  else if( event.state == Dali::KeyEvent::Up )
+  {
+    DispatchKeyUpEvent( keyValue );
+  }
+
+  return false;
+}
+
+void TizenWebEngineLite::CallEmptyAsyncHandle()
+{
+       DALI_ASSERT_ALWAYS( mWebContainer );
+       auto cb = []( void* data ) {
+  };
+       SendAsyncHandle( cb );
+}
+
+void TizenWebEngineLite::StopLoop()
+{
+  gDaliNumber = -1;
+  CallEmptyAsyncHandle();
+}
+
+void TizenWebEngineLite::SendAsyncHandle(std::function<void(void*)> cb)
+{
+  UVAsyncHandleData* handle = new UVAsyncHandleData();
+  handle->cb = cb;
+  handle->data = this;
+
+  {
+    Locker l( gMutex );
+    mAsyncHandlePool.push_back( ( size_t )handle );
+  }
+
+  gLauncherHandle.data = this;
+  uv_async_send(&gLauncherHandle);
+}
+
+void* TizenWebEngineLite::StartMainThread( void* data )
+{
+  uv_async_init( uv_default_loop(), &gLauncherHandle, []( uv_async_t* handle )
+  {
+    Dali::Plugin::TizenWebEngineLite* engine = static_cast< Dali::Plugin::TizenWebEngineLite* >(handle->data);
+    while ( !engine->mAsyncHandlePool.empty() )
+    {
+      UVAsyncHandleData* handleData = NULL;
+      {
+        Locker l( gMutex );
+        handleData = ( UVAsyncHandleData* )*engine->mAsyncHandlePool.begin();
+        engine->mAsyncHandlePool.erase( engine->mAsyncHandlePool.begin() );
+      }
+
+      if ( handleData )
+      {
+        handleData->cb( handleData->data );
+        delete handleData;
+      }
+    }
+  });
+
+  gIsAliveMainLoop = true;
+  pthread_mutex_unlock( &gMutex );
+  while ( true )
+  {
+    uv_run( uv_default_loop(), UV_RUN_ONCE );
+    if ( gDaliNumber < 0 )
+    {
+      break;
+    }
+  }
+  return NULL;
+}
+
+} // namespace Plugin
+} // namespace Dali
diff --git a/dali-extension/web-engine-lite/tizen-web-engine-lite.h b/dali-extension/web-engine-lite/tizen-web-engine-lite.h
new file mode 100644 (file)
index 0000000..766d8fe
--- /dev/null
@@ -0,0 +1,237 @@
+#ifndef DALI_TIZEN_WEB_ENGINE_LITE_H
+#define DALI_TIZEN_WEB_ENGINE_LITE_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (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
+ *
+ * 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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string.h>
+#include <vector>
+#include <dali/devel-api/threading/mutex.h>
+#include <dali/public-api/adaptor-framework/native-image-source.h>
+#include <dali/public-api/adaptor-framework/timer.h>
+#include <dali/devel-api/adaptor-framework/web-engine-plugin.h>
+#include <LWEWebView.h>
+#include <list>
+
+#ifndef STARFISH_TIZEN_TV
+#define STARFISH_TIZEN_TV
+#endif
+#ifndef STARFISH_DALI_TBMSURFACE
+#define STARFISH_DALI_TBMSURFACE
+#endif
+
+#ifdef STARFISH_DALI_TBMSURFACE
+#include <tbm_surface.h>
+#else
+#include <dali/public-api/images/buffer-image.h>
+#endif
+
+namespace Dali
+{
+
+namespace Plugin
+{
+
+/**
+ * @brief Implementation of the Tizen WebEngineLite class which has Tizen platform dependency.
+ */
+class TizenWebEngineLite : public Dali::WebEnginePlugin, public Dali::ConnectionTracker
+{
+public:
+
+  /**
+   * @brief Constructor.
+   */
+  TizenWebEngineLite();
+
+  /**
+   * @brief Destructor.
+   */
+  virtual ~TizenWebEngineLite();
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::Create()
+   */
+  virtual void Create( int width, int height, const std::string& locale, const std::string& timezoneId );
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::Destroy()
+   */
+  virtual void Destroy();
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::GetNativeImageSource()
+   */
+  Dali::NativeImageInterfacePtr GetNativeImageSource();
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::LoadUrl()
+   */
+  virtual void LoadUrl( const std::string& url );
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::GetUrl()
+   */
+  virtual const std::string& GetUrl();
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::LoadHTMLString()
+   */
+  virtual void LoadHTMLString( const std::string& string );
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::Reload()
+   */
+  virtual void Reload();
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::StopLoading()
+   */
+  virtual void StopLoading();
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::GoBack()
+   */
+  virtual void GoBack();
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::GoForward()
+   */
+  virtual void GoForward();
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::CanGoBack()
+   */
+  virtual bool CanGoBack();
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::CanGoForward()
+   */
+  virtual bool CanGoForward();
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::AddJavaScriptInterface()
+   */
+  virtual void AddJavaScriptInterface( const std::string& exposedObjectName, const std::string& jsFunctionName, std::function< std::string(const std::string&) > cb );
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::EvaluateJavaScript()
+   */
+  virtual void EvaluateJavaScript( const std::string& script );
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::RemoveJavascriptInterface()
+   */
+  virtual void RemoveJavascriptInterface( const std::string& exposedObjectName, const std::string& jsFunctionName );
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::ClearHistory()
+   */
+  virtual void ClearHistory();
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::ClearCache()
+   */
+  virtual void ClearCache();
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::SetSize()
+   */
+  virtual void SetSize( int width, int height );
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::SendTouchEvent()
+   */
+  virtual bool SendTouchEvent( const Dali::TouchData& touch );
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::SendKeyEvent()
+   */
+  virtual bool SendKeyEvent( const Dali::KeyEvent& event );
+
+  /**
+   * @copydoc Dali::WebEnginePlugin::FinishedSignal()
+   */
+  virtual Dali::WebEnginePlugin::WebEngineSignalType& PageLoadStartedSignal()
+  {
+    return mPageLoadStartedSignal;
+  }
+
+  virtual Dali::WebEnginePlugin::WebEngineSignalType& PageLoadFinishedSignal()
+  {
+    return mPageLoadFinishedSignal;
+  }
+
+private:
+
+  bool UpdateBuffer();
+
+  void StartMainThreadIfNeeds();
+  void CreateInstance();
+  void DestroyInstance();
+  void CallEmptyAsyncHandle();
+  void StopLoop();
+
+  void DispatchMouseDownEvent(float x, float y);
+  void DispatchMouseUpEvent(float x, float y);
+  void DispatchMouseMoveEvent(float x, float y, bool isLButtonPressed, bool isRButtonPressed);
+  void DispatchKeyDownEvent(LWE::KeyValue keyCode);
+  void DispatchKeyPressEvent(LWE::KeyValue keyCode);
+  void DispatchKeyUpEvent(LWE::KeyValue keyCode);
+
+  void SendAsyncHandle(std::function<void(void*)> cb);
+  static void* StartMainThread(void* data);
+
+  pthread_t mThreadHandle;
+  bool mIsMouseLbuttonDown;
+  Dali::Timer mTimer;
+
+  std::string mUrl;
+  size_t mOutputWidth;
+  size_t mOutputHeight;
+  size_t mOutputStride;
+  uint8_t* mOutputBuffer;
+  bool mCanGoBack, mCanGoForward;
+  bool mIsRunning;
+
+  LWE::WebContainer* mWebContainer;
+  std::list<size_t> mAsyncHandlePool;
+
+#ifdef STARFISH_DALI_TBMSURFACE
+  tbm_surface_h mTbmSurface;
+  Dali::NativeImageSourcePtr mNativeImageSourcePtr;
+#else
+  Dali::BufferImage mBufferImage;
+#endif
+
+  std::function<void(LWE::WebContainer*, const LWE::WebContainer::RenderResult&)> onRenderedHandler;
+  std::function<void(LWE::WebContainer*, LWE::ResourceError)> onReceivedError;
+  std::function<void(LWE::WebContainer*, const std::string&)> onPageFinishedHandler;
+  std::function<void(LWE::WebContainer*, const std::string&)> onPageStartedHandler;
+  std::function<void(LWE::WebContainer*, const std::string&)> onLoadResourceHandler;
+
+public:
+
+  Dali::WebEnginePlugin::WebEngineSignalType mPageLoadStartedSignal;
+  Dali::WebEnginePlugin::WebEngineSignalType mPageLoadFinishedSignal;
+};
+
+} // namespace Plugin
+} // namespace Dali;
+
+#endif
index 80e2b40..2a665a1 100755 (executable)
@@ -93,6 +93,20 @@ Group:      System/Libraries
 Image Loader plugin to image loading file for Dali
 
 ##############################
+# Dali Web Engine Lite Plugin
+##############################
+
+%package web-engine-lite-plugin
+Summary:    Plugin to support WebView for Dali
+Group:      System/Libraries
+BuildRequires: pkgconfig(libtbm)
+BuildRequires: pkgconfig(libtuv)
+BuildRequires: pkgconfig(lightweight-web-engine)
+
+%description web-engine-lite-plugin
+Web Engine Lite plugin to support WebView for Dali
+
+##############################
 # Preparation
 ##############################
 %prep
@@ -174,6 +188,10 @@ exit 0
 /sbin/ldconfig
 exit 0
 
+%post web-engine-lite-plugin
+/sbin/ldconfig
+exit 0
+
 ##############################
 #   Pre Uninstall old package
 ##############################
@@ -203,6 +221,10 @@ exit 0
 /sbin/ldconfig
 exit 0
 
+%postun web-engine-lite-plugin
+/sbin/ldconfig
+exit 0
+
 ##############################
 # Files in Binary Packages
 ##############################
@@ -243,3 +265,9 @@ exit 0
 %{_libdir}/libdali-image-loader-plugin.so*
 %license LICENSE
 %endif
+
+%files web-engine-lite-plugin
+%manifest dali-extension.manifest
+%defattr(-,root,root,-)
+%{_libdir}/libdali-web-engine-lite-plugin.so*
+%license LICENSE