[NUI] Support scroll in WebView. (#2528)
authorhuayongxu <49056704+huayongxu@users.noreply.github.com>
Tue, 26 Jan 2021 11:15:57 +0000 (19:15 +0800)
committerdongsug-song <35130733+dongsug-song@users.noreply.github.com>
Wed, 27 Jan 2021 11:05:23 +0000 (20:05 +0900)
1) ScrollPosition, ScrollSize, ContentSize properties are added.
2) ScrollBy is added.
3) ScrollEdgeReached events are notified when scrolled to edge.

Co-authored-by: Jiyun Yang <ji.yang@samsung.com>
src/Tizen.NUI/src/internal/Interop/Interop.WebView.cs
src/Tizen.NUI/src/internal/WebView.cs
src/Tizen.NUI/src/internal/WebViewScrollEdgeReachedEventArgs.cs [new file with mode: 0755]
src/Tizen.NUI/src/internal/WebViewScrollEdgeReachedSignal.cs [new file with mode: 0755]
test/Tizen.NUI.WebViewTest/Tizen.NUI.WebViewTest.csproj [new file with mode: 0755]
test/Tizen.NUI.WebViewTest/Tizen.NUI.WebViewTest.sln [new file with mode: 0755]
test/Tizen.NUI.WebViewTest/WebViewApp.cs [new file with mode: 0755]
test/Tizen.NUI.WebViewTest/shared/res/Tizen.NUI.WebViewTest.png [new file with mode: 0755]
test/Tizen.NUI.WebViewTest/tizen-manifest.xml [new file with mode: 0755]

index 47f48cb..9ac1dd1 100755 (executable)
@@ -45,6 +45,15 @@ namespace Tizen.NUI
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_WebView_GetSettings")]
             public static extern global::System.IntPtr GetWebSettings(global::System.Runtime.InteropServices.HandleRef jarg1);
 
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_WebView_Property_SCROLL_POSITION_get")]
+            public static extern int ScrollPositionGet();
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_WebView_Property_SCROLL_SIZE_get")]
+            public static extern int ScrollSizeGet();
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_WebView_Property_CONTENT_SIZE_get")]
+            public static extern int ContentSizeGet();
+
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_WebView_LoadUrl")]
             public static extern void LoadUrl(global::System.Runtime.InteropServices.HandleRef jarg1, string jarg2);
 
@@ -63,6 +72,9 @@ namespace Tizen.NUI
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_WebView_Resume")]
             public static extern void Resume(global::System.Runtime.InteropServices.HandleRef jarg1);
 
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_WebView_ScrollBy")]
+            public static extern void ScrollBy(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2, int jarg3);
+
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_WebView_GoBack")]
             public static extern void GoBack(global::System.Runtime.InteropServices.HandleRef jarg1);
 
@@ -113,6 +125,18 @@ namespace Tizen.NUI
 
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_WebViewPageLoadErrorSignal_Disconnect")]
             public static extern void WebViewPageLoadErrorSignalDisconnect(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2);
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_new_WebViewScrollEdgeReachedSignal_ScrollEdgeReached")]
+            public static extern global::System.IntPtr NewWebViewScrollEdgeReachedSignalScrollEdgeReached(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_delete_WebViewScrollEdgeReachedSignal")]
+            public static extern void DeleteWebViewScrollEdgeReachedSignal(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_WebViewScrollEdgeReachedSignal_Connect")]
+            public static extern void WebViewScrollEdgeReachedSignalConnect(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2);
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_WebViewScrollEdgeReachedSignal_Disconnect")]
+            public static extern void WebViewScrollEdgeReachedSignalDisconnect(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2);
         }
     }
 }
index f425005..9ff2550 100755 (executable)
@@ -36,6 +36,9 @@ namespace Tizen.NUI
         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
         private delegate void WebViewPageLoadErrorCallbackDelegate(IntPtr data, string pageUrl, int errorCode);
 
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        private delegate void WebViewScrollEdgeReachedCallbackDelegate(IntPtr data, int edge);
+
         private readonly WebViewPageLoadSignal pageLoadStartedSignal;
         private EventHandler<WebViewPageLoadEventArgs> pageLoadStartedEventHandler;
         private WebViewPageLoadCallbackDelegate pageLoadStartedCallback;
@@ -48,11 +51,16 @@ namespace Tizen.NUI
         private EventHandler<WebViewPageLoadErrorEventArgs> pageLoadErrorEventHandler;
         private WebViewPageLoadErrorCallbackDelegate pageLoadErrorCallback;
 
+        private readonly WebViewScrollEdgeReachedSignal scrollEdgeReachedSignal;
+        private EventHandler<WebViewScrollEdgeReachedEventArgs> scrollEdgeReachedEventHandler;
+        private WebViewScrollEdgeReachedCallbackDelegate scrollEdgeReachedCallback;
+
         internal WebView(global::System.IntPtr cPtr, bool cMemoryOwn) : base(Interop.WebView.Upcast(cPtr), cMemoryOwn)
         {
             pageLoadStartedSignal = new WebViewPageLoadSignal(Interop.WebView.NewWebViewPageLoadSignalPageLoadStarted(SwigCPtr));
             pageLoadFinishedSignal = new WebViewPageLoadSignal(Interop.WebView.NewWebViewPageLoadSignalPageLoadFinished(SwigCPtr));
             pageLoadErrorSignal = new WebViewPageLoadErrorSignal(Interop.WebView.NewWebViewPageLoadErrorSignalPageLoadError(SwigCPtr));
+            scrollEdgeReachedSignal = new WebViewScrollEdgeReachedSignal(Interop.WebView.NewWebViewScrollEdgeReachedSignalScrollEdgeReached(SwigCPtr));
 
             BackForwardList = new WebBackForwardList(Interop.WebView.GetWebBackForwardList(SwigCPtr), false);
             Context = new WebContext(Interop.WebView.GetWebContext(SwigCPtr), false);
@@ -147,10 +155,19 @@ namespace Tizen.NUI
             pageLoadErrorEventHandler?.Invoke(this, e);
         }
 
+        private void OnScrollEdgeReached(IntPtr data, int edge)
+        {
+            WebViewScrollEdgeReachedEventArgs arg = new WebViewScrollEdgeReachedEventArgs((WebViewScrollEdgeReachedEventArgs.Edge)edge);
+            scrollEdgeReachedEventHandler?.Invoke(this, arg);
+        }
+
         internal static new class Property
         {
             internal static readonly int Url = Interop.WebView.UrlGet();
             internal static readonly int UserAgent = Interop.WebView.UserAgentGet();
+            internal static readonly int ScrollPosition = Interop.WebView.ScrollPositionGet();
+            internal static readonly int ScrollSize = Interop.WebView.ScrollSizeGet();
+            internal static readonly int ContentSize = Interop.WebView.ContentSizeGet();
         }
 
         private static readonly BindableProperty UrlProperty = BindableProperty.Create(nameof(Url), typeof(string), typeof(WebView), string.Empty, propertyChanged: (BindableProperty.BindingPropertyChangedDelegate)((bindable, oldValue, newValue) =>
@@ -185,6 +202,38 @@ namespace Tizen.NUI
             return temp;
         }));
 
+        private static readonly BindableProperty ScrollPositionProperty = BindableProperty.Create(nameof(ScrollPosition), typeof(Vector2), typeof(WebView), null, propertyChanged: (bindable, oldValue, newValue) =>
+        {
+            var webview = (WebView)bindable;
+            if (newValue != null)
+            {
+                Tizen.NUI.Object.SetProperty(webview.SwigCPtr, WebView.Property.ScrollPosition, new Tizen.NUI.PropertyValue((Vector2)newValue));
+            }
+        },
+        defaultValueCreator: (bindable) =>
+        {
+            var webview = (WebView)bindable;
+            Vector2 temp = new Vector2(0.0f, 0.0f); ;
+            Tizen.NUI.Object.GetProperty(webview.SwigCPtr, WebView.Property.ScrollPosition).Get(temp);
+            return temp;
+        });
+
+        private static readonly BindableProperty ScrollSizeProperty = BindableProperty.Create(nameof(ScrollSize), typeof(Vector2), typeof(WebView), null, defaultValueCreator: (bindable) =>
+        {
+            var webview = (WebView)bindable;
+            Vector2 temp = new Vector2(0.0f, 0.0f); ;
+            Tizen.NUI.Object.GetProperty(webview.SwigCPtr, WebView.Property.ScrollSize).Get(temp);
+            return temp;
+        });
+
+        private static readonly BindableProperty ContentSizeProperty = BindableProperty.Create(nameof(ContentSize), typeof(Vector2), typeof(WebView), null, defaultValueCreator: (bindable) =>
+        {
+            var webview = (WebView)bindable;
+            Vector2 temp = new Vector2(0.0f, 0.0f); ;
+            Tizen.NUI.Object.GetProperty(webview.SwigCPtr, WebView.Property.ContentSize).Get(temp);
+            return temp;
+        });
+
         /// <summary>
         /// Creates an uninitialized WebView.
         /// </summary>
@@ -371,6 +420,55 @@ namespace Tizen.NUI
         }
 
         /// <summary>
+        /// The postion of scroll.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Position ScrollPosition
+        {
+            get
+            {
+                Vector2 pv = (Vector2)GetValue(ScrollPositionProperty);
+                return new Position(pv.X, pv.Y);
+            }
+            set
+            {
+                if (value != null)
+                {
+                    Position pv = value;
+                    Vector2 vpv = new Vector2(pv.X, pv.Y);
+                    SetValue(ScrollPositionProperty, vpv);
+                    NotifyPropertyChanged();
+                }
+            }
+        }
+
+        /// <summary>
+        /// The size of scroll, read-only.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Size ScrollSize
+        {
+            get
+            {
+                Vector2 sv = (Vector2)GetValue(ScrollSizeProperty);
+                return new Size(sv.Width, sv.Height);
+            }
+        }
+
+        /// <summary>
+        /// The size of content, read-only.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Size ContentSize
+        {
+            get
+            {
+                Vector2 sv = (Vector2)GetValue(ContentSizeProperty);
+                return new Size(sv.Width, sv.Height);
+            }
+        }
+
+        /// <summary>
         /// Event for the PageLoadStarted signal which can be used to subscribe or unsubscribe the event handler.<br />
         /// This signal is emitted when page loading has started.<br />
         /// </summary>
@@ -449,6 +547,32 @@ namespace Tizen.NUI
         }
 
         /// <summary>
+        /// Event for the ScrollEdgeReached signal which can be used to subscribe or unsubscribe the event handler.<br />
+        /// This signal is emitted when web view is scrolled to edge.<br />
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public event EventHandler<WebViewScrollEdgeReachedEventArgs> ScrollEdgeReached
+        {
+            add
+            {
+                if (scrollEdgeReachedEventHandler == null)
+                {
+                    scrollEdgeReachedCallback = OnScrollEdgeReached;
+                    scrollEdgeReachedSignal.Connect(scrollEdgeReachedCallback);
+                }
+                scrollEdgeReachedEventHandler += value;
+            }
+            remove
+            {
+                scrollEdgeReachedEventHandler -= value;
+                if (scrollEdgeReachedEventHandler == null && scrollEdgeReachedCallback != null)
+                {
+                    scrollEdgeReachedSignal.Disconnect(scrollEdgeReachedCallback);
+                }
+            }
+        }
+
+        /// <summary>
         /// Loads a html.
         /// <param name="url">The path of Web</param>
         /// </summary>
@@ -522,6 +646,18 @@ namespace Tizen.NUI
         }
 
         /// <summary>
+        /// Scroll web view by deltaX and detlaY.
+        /// <param name="deltaX">The deltaX of scroll</param>
+        /// <param name="deltaY">The deltaY of scroll</param>
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void ScrollBy(int deltaX, int deltaY)
+        {
+            Interop.WebView.ScrollBy(SwigCPtr, deltaX, deltaY);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+        }
+
+        /// <summary>
         /// Goes to the back
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
diff --git a/src/Tizen.NUI/src/internal/WebViewScrollEdgeReachedEventArgs.cs b/src/Tizen.NUI/src/internal/WebViewScrollEdgeReachedEventArgs.cs
new file mode 100755 (executable)
index 0000000..8cf0464
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021 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.
+ *
+ */
+
+using System;
+using System.ComponentModel;
+
+namespace Tizen.NUI
+{
+    /// <summary>
+    /// Event arguments that passed via the WebView.ScrollEdgeReached.
+    /// </summary>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public class WebViewScrollEdgeReachedEventArgs : EventArgs
+    {
+        /// <summary>
+        /// The enumeration for edge.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public enum Edge
+        {
+            [EditorBrowsable(EditorBrowsableState.Never)]
+            Left,
+
+            [EditorBrowsable(EditorBrowsableState.Never)]
+            Right,
+
+            [EditorBrowsable(EditorBrowsableState.Never)]
+            Top,
+
+            [EditorBrowsable(EditorBrowsableState.Never)]
+            Bottom,
+        }
+
+        /// <summary>
+        /// The edge, e.g. left, right, etc.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Edge ScrollEdge { get; }
+
+        internal WebViewScrollEdgeReachedEventArgs(Edge e)
+        {
+            ScrollEdge = e;
+        }
+    }
+}
diff --git a/src/Tizen.NUI/src/internal/WebViewScrollEdgeReachedSignal.cs b/src/Tizen.NUI/src/internal/WebViewScrollEdgeReachedSignal.cs
new file mode 100755 (executable)
index 0000000..d04c921
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright(c) 2021 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.
+ *
+ */
+
+namespace Tizen.NUI
+{
+    internal class WebViewScrollEdgeReachedSignal : Disposable
+    {
+        public WebViewScrollEdgeReachedSignal(global::System.IntPtr cPtr) : base(cPtr, true)
+        {
+        }
+
+        public void Connect(System.Delegate func)
+        {
+            System.IntPtr ip = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(func);
+            {
+                Interop.WebView.WebViewScrollEdgeReachedSignalConnect(SwigCPtr, new System.Runtime.InteropServices.HandleRef(this, ip));
+                if (NDalicPINVOKE.SWIGPendingException.Pending)
+                {
+                    throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+                }
+            }
+        }
+
+        public void Disconnect(System.Delegate func)
+        {
+            System.IntPtr ip = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate<System.Delegate>(func);
+            {
+                Interop.WebView.WebViewScrollEdgeReachedSignalDisconnect(SwigCPtr, new System.Runtime.InteropServices.HandleRef(this, ip));
+                if (NDalicPINVOKE.SWIGPendingException.Pending)
+                {
+                    throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+                }
+            }
+        }
+
+        protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
+        {
+            Interop.WebView.DeleteWebViewScrollEdgeReachedSignal(swigCPtr);
+        }
+    }
+}
diff --git a/test/Tizen.NUI.WebViewTest/Tizen.NUI.WebViewTest.csproj b/test/Tizen.NUI.WebViewTest/Tizen.NUI.WebViewTest.csproj
new file mode 100755 (executable)
index 0000000..bbd4ac1
--- /dev/null
@@ -0,0 +1,27 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp2.0</TargetFramework>
+    <AssemblyName>Tizen.NUI.WebViewTest</AssemblyName>
+    <SignAssembly>true</SignAssembly>
+    <PackageId>Tizen.NUI.WebViewTest</PackageId>
+    <Authors>Tizen.NUI.WebViewTest</Authors>
+    <Company>Tizen.NUI.WebViewTest</Company>
+    <Product>Tizen.NUI.WebViewTest</Product>
+  </PropertyGroup>
+
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugType>portable</DebugType>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>None</DebugType>
+  </PropertyGroup>
+
+  <ItemGroup>
+       <PackageReference Include="Tizen.NET" Version="8.0.0.15722" />
+       <PackageReference Include="Tizen.NET.Sdk" Version="1.0.9" />
+  </ItemGroup>
+
+</Project>
+
diff --git a/test/Tizen.NUI.WebViewTest/Tizen.NUI.WebViewTest.sln b/test/Tizen.NUI.WebViewTest/Tizen.NUI.WebViewTest.sln
new file mode 100755 (executable)
index 0000000..ee67c4e
--- /dev/null
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30309.148
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tizen.NUI.WebViewTest", "Tizen.NUI.WebViewTest.csproj", "{3C6CE4CE-9D35-42C9-B23D-BBFFA96B3955}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Any CPU = Debug|Any CPU
+               Release|Any CPU = Release|Any CPU
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {3C6CE4CE-9D35-42C9-B23D-BBFFA96B3955}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {3C6CE4CE-9D35-42C9-B23D-BBFFA96B3955}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {3C6CE4CE-9D35-42C9-B23D-BBFFA96B3955}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {3C6CE4CE-9D35-42C9-B23D-BBFFA96B3955}.Release|Any CPU.Build.0 = Release|Any CPU
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+       GlobalSection(ExtensibilityGlobals) = postSolution
+               SolutionGuid = {355D568D-D02A-490A-A6AC-FD6C7D97457A}
+       EndGlobalSection
+EndGlobal
diff --git a/test/Tizen.NUI.WebViewTest/WebViewApp.cs b/test/Tizen.NUI.WebViewTest/WebViewApp.cs
new file mode 100755 (executable)
index 0000000..5839c10
--- /dev/null
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2020 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.
+ *
+ */
+using System;
+using Tizen.NUI.BaseComponents;
+
+namespace Tizen.NUI.WebViewTest
+{
+    public class WebViewApplication : NUIApplication
+    {
+        private WebView simpleWebView = null;
+        private TextField addressBar = null;
+
+        private int index = 0;
+        private const int WEBSITES_COUNT = 93;
+        private string[] websites = 
+        {
+            "http://www.baidu.com","http://www.Google.com","http://www.Facebook.com","http://www.Youtube.com","http://www.Yahoo.com",
+            "http://www.Amazon.com","http://www.Wikipedia.org","http://www.Google.co.in","http://www.Qq.com","http://www.Twitter.com",
+            "http://www.Live.com","http://www.Taobao.com","http://www.Msn.com","http://www.Yahoo.co.jp","http://www.Linkedin.com",
+            "http://www.Google.co.jp","http://www.Sina.com.cn","http://www.Bing.com","http://www.Weibo.com","http://www.Yandex.ru",
+            "http://www.Vk.com","http://www.Instagram.com","http://www.Hao123.com","http://www.Ebay.com","http://www.Google.de",
+            "http://www.Amazon.co.jp","http://www.Mail.ru","http://www.Google.co.uk","http://www.Google.ru","http://www.Pinterest.com",
+            "http://www.360.cn","http://www.T.co","http://www.Reddit.com","http://www.Google.com.br","http://www.Netflix.com",
+            "http://www.Tmall.com","http://www.Google.fr","http://www.Paypal.com","http://www.Microsoft.com","http://www.Wordpress.com",
+            "http://www.Sohu.com","http://www.Blogspot.com","http://www.Google.it","http://www.Google.es","http://www.Onclickads.net",
+            "http://www.Tumblr.com","http://www.Imgur.com","http://www.Gmw.cn","http://www.Ok.ru","http://www.Aliexpress.com",
+            "http://www.Apple.com","http://www.Imdb.com","http://www.Stackoverflow.com","http://www.Fc2.com","http://www.Google.com.mx",
+            "http://www.Ask.com","http://www.Amazon.de","http://www.Google.com.hk","http://www.Google.com.tr","http://www.Alibaba.com",
+            "http://www.Google.ca","http://www.Office.com","http://www.Rakuten.co.jp","http://www.Google.co.id","http://www.Tianya.cn",
+            "http://www.Xinhuanet.com","http://www.Github.com","http://www.Craigslist.org","http://www.Nicovideo.jp","http://www.Soso.com",
+            "http://www.Amazon.co.uk","http://www.Amazon.in","http://www.Blogger.com","http://www.Kat.cr","http://www.Outbrain.com",
+            "http://www.Pixnet.net","http://www.Cnn.com","http://www.Go.com","http://www.Google.pl","http://www.Dropbox.com",
+            "http://www.Google.com.au","http://www.360.com","http://www.Haosou.com","http://www.Naver.com","http://www.Jd.com",
+            "http://www.Adobe.com","http://www.Flipkart.com","http://www.Whatsapp.com","http://www.Nytimes.com","http://www.Coccoc.com",
+            "http://www.Chase.com","http://www.Chinadaily.com.cn","http://www.bbc.co.uk"
+        };
+
+        private const string USER_AGENT = "Mozilla/5.0 (SMART-TV; Linux; Tizen 6.0) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/76.0.3809.146 TV Safari/537.36";
+
+        private const int ADDRESSBAR_HEIGHT = 100;
+
+        private const int SCREEN_WIDTH = 1920;
+        private const int SCREEN_HEIGHT = 1080;
+
+        private const int MIN_WEBVIEW_WIDTH = 1000;
+        private const int MIN_WEBVIEW_HEIGHT = 600;
+
+        private const int WEBVIEW_WIDTH = SCREEN_WIDTH;
+        private const int WEBVIEW_HEIGHT = SCREEN_HEIGHT - ADDRESSBAR_HEIGHT;
+
+        private int blueKeyPressedCount = 0;
+        private int yellowKeyPressedCount = 0;
+
+        private static long startTime = 0;
+
+        private TextLabel messageLabel = null;
+        private Timer messageTimer = null;
+
+        protected override void OnCreate()
+        {
+            base.OnCreate();
+
+            GetDefaultWindow().BackgroundColor = new Color((float)189 /255, (float)179 /255, (float)204 /255, 1.0f);
+            //EnvironmentVariable.SetEnvironmentVariable("DALI_WEB_ENGINE_NAME", "lwe");
+
+            addressBar = new TextField()
+            {
+                BackgroundColor = Color.White,
+                Size = new Size(SCREEN_WIDTH, ADDRESSBAR_HEIGHT),
+                EnableGrabHandlePopup = false,
+                EnableGrabHandle = false,
+                EnableSelection = true,
+                Focusable = true,
+                PlaceholderText = "Please input url here like Www.baidu.com.",
+            };
+            addressBar.FocusGained += OnTextEditorFocusGained;
+            addressBar.FocusLost += OnTextEditorFocusLost;
+            addressBar.KeyEvent += OnAddressBarKeyEvent;
+            addressBar.TouchEvent += OnAddressBarTouchEvent;
+            GetDefaultWindow().Add(addressBar);
+
+            simpleWebView = new WebView()
+            {
+                Position = new Position(0, ADDRESSBAR_HEIGHT),
+                Size = new Size(WEBVIEW_WIDTH, WEBVIEW_HEIGHT),
+                UserAgent = USER_AGENT,
+                Focusable = true,
+            };
+            simpleWebView.FocusGained += OnWebViewFocusGained;
+            simpleWebView.FocusLost += OnWebViewFocusLost;
+            simpleWebView.KeyEvent += OnWebViewKeyEvent;
+            simpleWebView.TouchEvent += OnWebViewTouchEvent;
+            simpleWebView.PageLoadStarted += OnPageLoadStarted;
+            simpleWebView.ScrollEdgeReached += OnScrollEdgeReached;
+            GetDefaultWindow().Add(simpleWebView);
+
+            GetDefaultWindow().KeyEvent += Instance_KeyEvent;
+            simpleWebView.LoadUrl(websites[index]);
+            FocusManager.Instance.SetCurrentFocusView(simpleWebView);
+
+            messageTimer = new Timer(10000);
+            messageTimer.Tick += OnTick;
+        }
+
+        protected override void OnTerminate()
+        {
+            GetDefaultWindow().Remove(simpleWebView);
+            GetDefaultWindow().Remove(addressBar);
+
+            messageTimer.Tick -= OnTick;
+            messageTimer.Dispose();
+            messageTimer = null;
+
+            base.OnTerminate();
+        }
+
+        private bool OnTick(object sender, EventArgs e)
+        {
+            GetDefaultWindow().Remove(messageLabel);
+            messageLabel.Dispose();
+            messageLabel = null;
+            return false;
+        }
+
+        private bool OnWebViewTouchEvent(object source, View.TouchEventArgs args)
+        {
+            if (!simpleWebView.HasFocus())
+            {
+                FocusManager.Instance.SetCurrentFocusView(simpleWebView);
+            }
+            return false;
+        }
+
+        private void OnScrollEdgeReached(object sender, WebViewScrollEdgeReachedEventArgs e)
+        {
+            Log.Info("WebView", $"------------scroll edge reached: {e.ScrollEdge}-------");
+        }
+
+        private void OnPageLoadStarted(object sender, WebViewPageLoadEventArgs e)
+        {
+            Log.Info("WebView", $"------------web view start to load time: {DateTime.Now.Ticks - startTime}-------");
+        }
+
+        private void OnWebViewFocusGained(object source, EventArgs args)
+        {
+            Log.Info("WebView", $"------------web view focus is gained-------");
+        }
+
+        private void OnWebViewFocusLost(object source, EventArgs args)
+        {
+            Log.Info("WebView", $"------------web view focus is lost-------");
+        }
+
+        private bool OnWebViewKeyEvent(object source, View.KeyEventArgs args)
+        {
+            bool result = false;
+
+            Log.Info("WebView", $"----web view key is {args.Key.KeyPressedName}, state is {args.Key.State}-------");
+
+            if (args.Key.State == Key.StateType.Up)
+            {
+                if (args.Key.KeyPressedName == "XF86RaiseChannel")
+                {
+                    Log.Info("WebView", $"old url is {simpleWebView.Url}.");
+                    if (index != 0)
+                    {
+                        simpleWebView.Url = websites[--index].ToLowerInvariant();
+                    }
+                    else
+                    {
+                        simpleWebView.Url = websites[WEBSITES_COUNT - 1].ToLowerInvariant();
+                    }
+                    result = true;
+                    Log.Info("WebView", $"new url is {simpleWebView.Url}.");
+                }
+                else if (args.Key.KeyPressedName == "XF86LowerChannel")
+                {
+                    Log.Info("WebView", $"old url is {simpleWebView.Url}.");
+                    if (index != WEBSITES_COUNT - 1)
+                    {
+                        simpleWebView.Url = websites[++index].ToLowerInvariant();
+                    }
+                    else
+                    {
+                        simpleWebView.Url = websites[0].ToLowerInvariant();
+                    }
+                    result = true;
+                    Log.Info("WebView", $"new url is {simpleWebView.Url}.");
+                }
+                else if (args.Key.KeyPressedName == "XF86Back")
+                {
+                    simpleWebView.GoBack();
+                    result = true;
+                }
+                else if (args.Key.KeyPressedName == "XF86Red")
+                {
+                    FocusManager.Instance.SetCurrentFocusView(addressBar);
+                    result = true;
+                }
+                else if (args.Key.KeyPressedName == "XF86Blue")
+                {
+                    blueKeyPressedCount++;
+                    if (blueKeyPressedCount % 6 == 0)
+                    {
+                        simpleWebView.Position = new Position(0, ADDRESSBAR_HEIGHT);
+                        simpleWebView.Orientation = new Rotation(new Radian(new Degree(60 * blueKeyPressedCount)), Vector3.ZAxis);
+                        blueKeyPressedCount = 0;
+                    }
+                    else
+                    {
+                        simpleWebView.Orientation = new Rotation(new Radian(new Degree(60 * blueKeyPressedCount)), Vector3.ZAxis);
+                    }
+                    result = true;
+                }
+                else if (args.Key.KeyPressedName == "XF86Yellow")
+                {
+                    yellowKeyPressedCount++;
+                    int wdistance = (SCREEN_WIDTH - MIN_WEBVIEW_WIDTH) / 5;
+                    int hdistance = (SCREEN_HEIGHT - MIN_WEBVIEW_HEIGHT - ADDRESSBAR_HEIGHT) / 5;
+                    simpleWebView.Position = new Position((SCREEN_WIDTH - MIN_WEBVIEW_WIDTH - yellowKeyPressedCount * wdistance) / 2, ADDRESSBAR_HEIGHT);
+                    simpleWebView.Size = new Size(MIN_WEBVIEW_WIDTH + yellowKeyPressedCount * wdistance, MIN_WEBVIEW_HEIGHT + hdistance * yellowKeyPressedCount);
+                    if (yellowKeyPressedCount % 5 == 0)
+                    {
+                        yellowKeyPressedCount = 0;
+                    }
+                    result = true;
+                }
+                else if (args.Key.KeyPressedName == "XF86Green")
+                {
+                    if (messageLabel != null)
+                        return result;
+
+                    Log.Info("WebView", $"key XF86Green is pressed.");
+
+                    simpleWebView.ScrollPosition = new Position(0, 200);
+                    simpleWebView.ScrollBy(0, 50);
+                    Log.Info("WebView", $"scroll position is ({simpleWebView.ScrollPosition.X}, {simpleWebView.ScrollPosition.Y}).");
+                    Log.Info("WebView", $"scroll size is ({simpleWebView.ScrollSize.Width}, {simpleWebView.ScrollSize.Height}).");
+                    Log.Info("WebView", $"content size is ({simpleWebView.ContentSize.Width}, {simpleWebView.ContentSize.Height}).");
+
+                    result = true;
+                }
+            }
+
+            return result;
+        }
+
+        private bool OnAddressBarTouchEvent(object source, View.TouchEventArgs args)
+        {
+            FocusManager.Instance.SetCurrentFocusView(addressBar);
+            return false;
+        }
+
+        private void OnTextEditorFocusGained(object source, EventArgs args)
+        {
+            Log.Info("WebView", $"------------address bar focus is gained-------");
+
+            addressBar.Text = "";
+
+            addressBar.GetInputMethodContext().Activate();
+            addressBar.GetInputMethodContext().ShowInputPanel();
+        }
+
+        private void OnTextEditorFocusLost(object source, EventArgs args)
+        {
+            Log.Info("WebView", $"------------address bar focus lost-------");
+        }
+
+        private bool OnAddressBarKeyEvent(object source, View.KeyEventArgs args)
+        {
+            Log.Info("WebView", $"------------address bar key is {args.Key.KeyPressedName}-------");
+
+            if (args.Key.State == Key.StateType.Up)
+            {
+                if (args.Key.KeyPressedName == "Select")
+                {
+                    Log.Info("WebView", $"------------address bar text is {addressBar.Text}-------");
+
+                    if (addressBar.Text.Length > 0)
+                    {
+                        addressBar.GetInputMethodContext().HideInputPanel();
+                        addressBar.GetInputMethodContext().Deactivate();
+
+                        simpleWebView.Url = $"http://{addressBar.Text.ToLowerInvariant()}";
+
+                        // set focus to webview.
+                        FocusManager.Instance.SetCurrentFocusView(simpleWebView);
+                    }
+                }
+                else if (args.Key.KeyPressedName == "BackSpace")
+                {
+                    if (addressBar.Text.Length > 0)
+                    {
+                        addressBar.Text = addressBar.Text.Substring(0, addressBar.Text.Length - 1);
+                    }
+                }
+                else if (args.Key.KeyPressedName == "XF86Red")
+                {
+                    FocusManager.Instance.SetCurrentFocusView(simpleWebView);
+                }
+            }
+
+            return true;
+        }
+
+        private void Instance_KeyEvent(object sender, Window.KeyEventArgs args)
+        {
+            if (args.Key.State == Key.StateType.Up)
+            {
+                Log.Info("WebView", $"window key is {args.Key.KeyPressedName}.");
+            }
+        }
+
+        [STAThread]
+        static void Main(string[] args)
+        {
+            startTime = DateTime.Now.Ticks;
+            Log.Info("WebView", $"------------web view start time: {startTime}-------");
+            new WebViewApplication().Run(args);
+        }
+    }
+}
+
diff --git a/test/Tizen.NUI.WebViewTest/shared/res/Tizen.NUI.WebViewTest.png b/test/Tizen.NUI.WebViewTest/shared/res/Tizen.NUI.WebViewTest.png
new file mode 100755 (executable)
index 0000000..9f3cb98
Binary files /dev/null and b/test/Tizen.NUI.WebViewTest/shared/res/Tizen.NUI.WebViewTest.png differ
diff --git a/test/Tizen.NUI.WebViewTest/tizen-manifest.xml b/test/Tizen.NUI.WebViewTest/tizen-manifest.xml
new file mode 100755 (executable)
index 0000000..b96f378
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest package="Tizen.NUI.WebViewTest" version="1.0.0" api-version="4" xmlns="http://tizen.org/ns/packages">
+    <profile name="common" />
+    <ui-application appid="Tizen.NUI.WebViewTest" exec="Tizen.NUI.WebViewTest.dll" multiple="false" nodisplay="false" taskmanage="true" splash-screen-display="true" type="dotnet" launch_mode="single">
+        <label>WebViewTest</label>
+        <icon>Tizen.NUI.WebViewTest.png</icon>
+        <metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" />
+        <splash-screens />
+    </ui-application>
+    <shortcut-list />
+    <provides-appdefined-privileges />
+</manifest>