[NUI]Set response body in binary format when intercepting http request. (#3884)
authorhuayongxu <49056704+huayongxu@users.noreply.github.com>
Mon, 7 Feb 2022 04:04:15 +0000 (12:04 +0800)
committerdongsug-song <35130733+dongsug-song@users.noreply.github.com>
Tue, 8 Feb 2022 04:41:28 +0000 (13:41 +0900)
src/Tizen.NUI/src/internal/Interop/Interop.WebHttpRequestInterceptor.cs
src/Tizen.NUI/src/internal/WebView/WebHttpRequestInterceptor.cs
test/Tizen.NUI.WebViewTest/SimpleWebViewApp.cs

index 7a7a6a4..dd42bcd 100755 (executable)
@@ -15,6 +15,8 @@
  *
  */
 
+using System.Runtime.InteropServices;
+
 namespace Tizen.NUI
 {
     internal static partial class Interop
@@ -50,13 +52,25 @@ namespace Tizen.NUI
             [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
             public static extern bool AddResponseBody(global::System.Runtime.InteropServices.HandleRef jarg1, string jarg2, uint jarg3);
 
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "CSharp_Dali_WebRequestInterceptor_AddResponseBody")]
+            [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
+            public static extern bool AddResponseBody(global::System.Runtime.InteropServices.HandleRef jarg1, [MarshalAs(UnmanagedType.LPArray)] byte[] jarg2, uint jarg3);
+
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_WebRequestInterceptor_AddResponse")]
             [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
             public static extern bool AddResponse(global::System.Runtime.InteropServices.HandleRef jarg1, string jarg2, string jarg3, uint jarg4);
 
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "CSharp_Dali_WebRequestInterceptor_AddResponse")]
+            [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
+            public static extern bool AddResponse(global::System.Runtime.InteropServices.HandleRef jarg1, string jarg2, [MarshalAs(UnmanagedType.LPArray)] byte[] jarg3, uint jarg4);
+
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_WebRequestInterceptor_WriteResponseChunk")]
             [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
             public static extern bool WriteResponseChunk(global::System.Runtime.InteropServices.HandleRef jarg1, string jarg2, uint jarg3);
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "CSharp_Dali_WebRequestInterceptor_WriteResponseChunk")]
+            [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
+            public static extern bool WriteResponseChunk(global::System.Runtime.InteropServices.HandleRef jarg1, [MarshalAs(UnmanagedType.LPArray)] byte[] jarg2, uint jarg3);
         }
     }
 }
index be46f86..84c3a8d 100755 (executable)
@@ -188,6 +188,23 @@ namespace Tizen.NUI
         }
 
         /// <summary>
+        /// Writes whole response body at once.
+        /// To call it, application should have full response body ready for the intercepted request.
+        /// This function can be used inside or outside WebContext.HttpRequestIntercepted.
+        /// After this call, any further call on WebHttpRequestInterceptor results in undefined behavior.
+        /// </summary>
+        /// <param name="body">Contents of response</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public bool SetResponseBody(byte[] body)
+        {
+            if (body == null)
+                return false;
+            bool result = Interop.WebHttpRequestInterceptor.AddResponseBody(interceptorHandle, body, (uint)body.Length);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return result;
+        }
+
+        /// <summary>
         /// Writes whole response body with headers at once.
         /// To call it, application should have full response headers and body ready for the intercepted request.
         /// This function can be used inside or outside WebContext.HttpRequestIntercepted.
@@ -206,6 +223,24 @@ namespace Tizen.NUI
         }
 
         /// <summary>
+        /// Writes whole response body with headers at once.
+        /// To call it, application should have full response headers and body ready for the intercepted request.
+        /// This function can be used inside or outside WebContext.HttpRequestIntercepted.
+        /// After this call, any further call on WebHttpRequestInterceptor results in undefined behavior.
+        /// </summary>
+        /// <param name="headers">Headers of response</param>
+        /// <param name="body">Contents of response</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public bool SetResponse(string headers, byte[] body)
+        {
+            if (body == null)
+                return false;
+            bool result = Interop.WebHttpRequestInterceptor.AddResponse(interceptorHandle, headers, body, (uint)body.Length);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return result;
+        }
+
+        /// <summary>
         /// Writes a part of response body.
         /// This function can be called only OUTSIDE WebContext.HttpRequestIntercepted.
         /// If it returns false, handling the request is done.
@@ -229,5 +264,30 @@ namespace Tizen.NUI
             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
             return result;
         }
+
+        /// <summary>
+        /// Writes a part of response body.
+        /// This function can be called only OUTSIDE WebContext.HttpRequestIntercepted.
+        /// If it returns false, handling the request is done.
+        /// Any further calls result in undefined behavior.
+        /// User should always check return value, because response to this request might not be needed any more,
+        /// and the function can return false even though user still has data to write.
+        ///
+        /// After writing full response body in chunks using this function,
+        /// call it again with null as chunk, to signal that response body is finished.
+        /// </summary>
+        /// <param name="chunk">Chunk of response</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public bool WriteResponseChunk(byte[] chunk)
+        {
+            int length = 0;
+            if (chunk != null)
+            {
+                length = chunk.Length;
+            }
+            bool result = Interop.WebHttpRequestInterceptor.WriteResponseChunk(interceptorHandle, chunk, (uint)length);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return result;
+        }
     }
 }
index 9b931bb..200bb59 100755 (executable)
@@ -16,6 +16,8 @@
  */
 using System;
 using System.Collections.Generic;
+using System.IO;
+using System.Text;
 using Tizen.NUI.BaseComponents;
 using Tizen.NUI.Components;
 
@@ -112,6 +114,8 @@ namespace Tizen.NUI.WebViewTest
             "https://www.youtube.com"
         };
 
+        private string invalidUrl = "https://test/";
+
         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;
@@ -377,9 +381,32 @@ namespace Tizen.NUI.WebViewTest
         {
             Log.Info("WebView", $"------------http request intercepted, Url: {interceptor.Url}-------");
 
-            interceptor.Ignore();
+            //interceptor.Ignore();
+            if (interceptor.Url.Equals(invalidUrl))
+            {
+                byte[] bData = Encoding.UTF8.GetBytes("<html><body><img src='test.jpg'></body></html>");
+                interceptor.SetResponseStatus(200, "OK");
+                interceptor.AddResponseHeader("Content-Type", "text/html; charset=UTF-8");
+                interceptor.AddResponseHeader("Content-Length", bData.Length.ToString());
+                interceptor.SetResponseBody(bData);
+                Log.Info("WebView", $"------------http request intercepted set response body end-------");
+            }
+            else if (interceptor.Url.Equals($"{invalidUrl}test.jpg"))
+            {
+                string path = Tizen.Applications.Application.Current.DirectoryInfo.SharedResource + "Tizen.NUI.WebViewTest.png";
+                using (FileStream fs = File.OpenRead(path))
+                {
+                    byte[] bData = new byte[1024];
+                    while (fs.Read(bData, 0, bData.Length) > 0)
+                    {
+                        interceptor.WriteResponseChunk(bData);
+                    }
+                    interceptor.WriteResponseChunk((byte[])null);
+                    Log.Info("WebView", $"------------http request intercepted write chunk end-------");
+                }
+            }
 
-            Log.Info("WebView", $"------------http request intercepted-------");
+            Log.Info("WebView", $"------------http request intercepted end-------");
         }
 
         private void OnSslCertificateChanged(object sender, WebViewCertificateReceivedEventArgs e)
@@ -724,18 +751,14 @@ namespace Tizen.NUI.WebViewTest
                 //    succeeded = simpleWebView.HitTestAsynchronously(100, 100, BaseComponents.WebView.HitTestMode.Default, OnHitTestFinished);
                 //    Log.Info("WebView", $"HitTestAsynchronously, {succeeded}");
                 //}
+                else if (args.Key.KeyPressedName == "1")
+                {
+                    simpleWebView.Context.RegisterHttpRequestInterceptedCallback(OnHttpRequestIntercepted);
+                    simpleWebView.LoadUrl(invalidUrl);
+                    result = true;
+                }
                 else if (args.Key.KeyPressedName == "XF86Red")
                 {
-                    if (redKeyPressedCount % 2 == 0)
-                    {
-                        simpleWebView.Context.RegisterHttpRequestInterceptedCallback(OnHttpRequestIntercepted);
-                        redKeyPressedCount = 0;
-                    }
-                    else
-                    {
-                        simpleWebView.Context.RegisterHttpRequestInterceptedCallback(null);
-                    }
-                    redKeyPressedCount++;
                     FocusManager.Instance.SetCurrentFocusView(addressBar);
                     result = true;
                 }