From e23d212feef22617182a3c6ae74471651d328d9f Mon Sep 17 00:00:00 2001 From: ousttrue Date: Sun, 8 Jul 2018 11:31:59 +0900 Subject: [PATCH 1/9] Upgraded .NET Framework version to 4.5 --- Source/Demo/Common/HtmlRenderer.Demo.Common.csproj | 4 +++- Source/Demo/WPF/HtmlRenderer.Demo.WPF.csproj | 5 ++++- Source/Demo/WinForms/HtmlRenderer.Demo.WinForms.csproj | 5 ++++- Source/HtmlRenderer.PdfSharp/HtmlRenderer.PdfSharp.csproj | 5 ++++- Source/HtmlRenderer.WPF/HtmlRenderer.WPF.csproj | 4 +++- Source/HtmlRenderer.WinForms/HtmlRenderer.WinForms.csproj | 7 ++++++- Source/HtmlRenderer/HtmlRenderer.csproj | 6 +++++- 7 files changed, 29 insertions(+), 7 deletions(-) diff --git a/Source/Demo/Common/HtmlRenderer.Demo.Common.csproj b/Source/Demo/Common/HtmlRenderer.Demo.Common.csproj index 7413cc397..20d826cf2 100644 --- a/Source/Demo/Common/HtmlRenderer.Demo.Common.csproj +++ b/Source/Demo/Common/HtmlRenderer.Demo.Common.csproj @@ -9,7 +9,7 @@ Properties TheArtOfDev.HtmlRenderer.Demo.Common HtmlRendererDemoCommon - v2.0 + v4.5 512 @@ -21,6 +21,7 @@ DEBUG;TRACE prompt 4 + false pdbonly @@ -29,6 +30,7 @@ TRACE prompt 4 + false diff --git a/Source/Demo/WPF/HtmlRenderer.Demo.WPF.csproj b/Source/Demo/WPF/HtmlRenderer.Demo.WPF.csproj index 8c26cdcc4..253cfbfd9 100644 --- a/Source/Demo/WPF/HtmlRenderer.Demo.WPF.csproj +++ b/Source/Demo/WPF/HtmlRenderer.Demo.WPF.csproj @@ -9,7 +9,7 @@ Properties TheArtOfDev.HtmlRenderer.Demo.WPF HtmlRendererWpfDemo - v4.0 + v4.5 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 @@ -26,6 +26,7 @@ DEBUG;TRACE prompt 4 + false AnyCPU @@ -35,6 +36,7 @@ TRACE prompt 4 + false html.ico @@ -122,6 +124,7 @@ + diff --git a/Source/Demo/WinForms/HtmlRenderer.Demo.WinForms.csproj b/Source/Demo/WinForms/HtmlRenderer.Demo.WinForms.csproj index 95dafc2f1..55caf08df 100644 --- a/Source/Demo/WinForms/HtmlRenderer.Demo.WinForms.csproj +++ b/Source/Demo/WinForms/HtmlRenderer.Demo.WinForms.csproj @@ -10,7 +10,7 @@ Properties TheArtOfDev.HtmlRenderer.Demo.WinForms HtmlRendererWinFormsDemo - v2.0 + v4.5 @@ -171,6 +171,9 @@ + + Designer + diff --git a/Source/HtmlRenderer.PdfSharp/HtmlRenderer.PdfSharp.csproj b/Source/HtmlRenderer.PdfSharp/HtmlRenderer.PdfSharp.csproj index ef0fd7acc..d775d14fe 100644 --- a/Source/HtmlRenderer.PdfSharp/HtmlRenderer.PdfSharp.csproj +++ b/Source/HtmlRenderer.PdfSharp/HtmlRenderer.PdfSharp.csproj @@ -9,10 +9,11 @@ Properties TheArtOfDev.HtmlRenderer.PdfSharp HtmlRenderer.PdfSharp - v2.0 + v4.5 512 ..\ true + true @@ -22,6 +23,7 @@ DEBUG;TRACE prompt 4 + false pdbonly @@ -30,6 +32,7 @@ TRACE prompt 4 + false diff --git a/Source/HtmlRenderer.WPF/HtmlRenderer.WPF.csproj b/Source/HtmlRenderer.WPF/HtmlRenderer.WPF.csproj index 80c4b97f9..72c757431 100644 --- a/Source/HtmlRenderer.WPF/HtmlRenderer.WPF.csproj +++ b/Source/HtmlRenderer.WPF/HtmlRenderer.WPF.csproj @@ -9,7 +9,7 @@ Properties TheArtOfDev.HtmlRenderer.WPF HtmlRenderer.WPF - v3.0 + v4.5 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 @@ -24,6 +24,7 @@ DEBUG;TRACE prompt 4 + false pdbonly @@ -32,6 +33,7 @@ TRACE prompt 4 + false diff --git a/Source/HtmlRenderer.WinForms/HtmlRenderer.WinForms.csproj b/Source/HtmlRenderer.WinForms/HtmlRenderer.WinForms.csproj index ce1a98759..8730b6504 100644 --- a/Source/HtmlRenderer.WinForms/HtmlRenderer.WinForms.csproj +++ b/Source/HtmlRenderer.WinForms/HtmlRenderer.WinForms.csproj @@ -12,7 +12,7 @@ HtmlRenderer.WinForms - v2.0 + v4.5 @@ -46,6 +46,7 @@ 4 false AllRules.ruleset + false pdbonly @@ -55,6 +56,7 @@ prompt 4 AllRules.ruleset + false @@ -115,6 +117,9 @@ HtmlRenderer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Source/HtmlRenderer.SimpleBrowser/HtmlRenderer.SimpleBrowser.csproj b/Source/HtmlRenderer.SimpleBrowser/HtmlRenderer.SimpleBrowser.csproj new file mode 100644 index 000000000..93e760edb --- /dev/null +++ b/Source/HtmlRenderer.SimpleBrowser/HtmlRenderer.SimpleBrowser.csproj @@ -0,0 +1,94 @@ + + + + + Debug + AnyCPU + {EF7F91E6-B633-4C15-B0F3-93D062C0ECC3} + WinExe + HtmlRenderer.SimpleBrowser + HtmlRenderer.SimpleBrowser + v4.6.1 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + Form + + + Form1.cs + + + + + + + Form1.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + {1b058920-24b4-4140-8ae7-c8c6c38ca52d} + HtmlRenderer.WinForms + + + {fe611685-391f-4e3e-b27e-d3150e51e49b} + HtmlRenderer + + + + \ No newline at end of file diff --git a/Source/HtmlRenderer.SimpleBrowser/HttpResourceServer.cs b/Source/HtmlRenderer.SimpleBrowser/HttpResourceServer.cs new file mode 100644 index 000000000..239cd3f62 --- /dev/null +++ b/Source/HtmlRenderer.SimpleBrowser/HttpResourceServer.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TheArtOfDev.HtmlRenderer.Adapters; +using TheArtOfDev.HtmlRenderer.Core; + + +namespace HtmlRenderer.SimpleBrowser +{ + class HttpResourceServer : IResourceServer + { + string m_url; + HttpSession m_session; + + public HttpResourceServer() + { + m_session = new HttpSession(); + } + + public async Task Go(string url) + { + var result = await m_session.Get(url); + var bytes = result.GetBodyBytes(); + m_html = Encoding.UTF8.GetString(bytes.ToArray()); + } + + #region Interface + public void Dispose() + { + } + + string m_html; + public void SetHtml(string html) + { + m_html = html; + } + public async Task GetHtmlAsync() + { + return m_html; + } + + CssData m_cssData; + public void SetCssData(CssData cssData) + { + m_cssData = cssData; + } + public async Task GetCssDataAsync() + { + return m_cssData; + } + + public Task GetCssDataAsync(string location, Dictionary attributes) + { + throw new NotImplementedException(); + } + + public Task GetImageAsync(string location, Dictionary attributes) + { + throw new NotImplementedException(); + } + #endregion + } +} diff --git a/Source/HtmlRenderer.SimpleBrowser/HttpSession.cs b/Source/HtmlRenderer.SimpleBrowser/HttpSession.cs new file mode 100644 index 000000000..7b2bef848 --- /dev/null +++ b/Source/HtmlRenderer.SimpleBrowser/HttpSession.cs @@ -0,0 +1,333 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +#if NETFX_CORE +using Windows.Security.Cryptography.Certificates; +using Windows.Web.Http; +using Windows.Web.Http.Filters; +using System.Runtime.InteropServices.WindowsRuntime; +#else +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +#endif + + +namespace HtmlRenderer.SimpleBrowser +{ + static class HttpConst + { + public const string UserAgent = "HtmlRenderer"; + } + +#if NETFX_CORE + public class HttpResult + { + #region Response + public int StatusCode { get; private set; } + + List> m_headers = new List>(); + public List> Headers { get { return m_headers; } } + public string Cookie + { + get + { + foreach (var kv in Headers) + { + if (kv.Key.ToLower() == "set-cookie") + { + return kv.Value; + } + } + throw new KeyNotFoundException("set-cookie"); + } + } + + List m_body = new List(); + public List Body { get { return m_body; } } + public string GetBodyString() + { + return Encoding.UTF8.GetString(Body.ToArray()); + } + #endregion + + public HttpResult(int statusCode) + { + StatusCode = statusCode; + } + + public void AddHeader(string key, string value) + { + m_headers.Add(new KeyValuePair(key, value)); + } + + public void AddBody(IEnumerable bytes) + { + m_body.AddRange(bytes); + } + + public IEnumerable GetBodyBytes(Encoding encoding = null) + { + return m_body; + } + } + + public static class Http + { + public static Task PostForm(HttpSession session, string url, + Dictionary form) + { + var content = new HttpFormUrlEncodedContent(form); + return Post(session, url, content); + } + + public async static Task Post(HttpSession session, string url, + IHttpContent content) + { + var uri = new Uri(url); + + using (var response = await session.Client.PostAsync(uri, content)) + { + var result = new HttpResult((int)response.StatusCode); + foreach (var h in response.Headers) + { + result.AddHeader(h.Key, h.Value); + } + + // get body + var buffer = await response.Content.ReadAsBufferAsync(); + result.AddBody(buffer.ToArray()); + + return result; + } + } + + public static async Task Get(HttpSession session, string url) + { + var uri = new Uri(url); + using (var response = await session.Client.GetAsync(uri)) + { + var result = new HttpResult((int)response.StatusCode); + foreach (var h in response.Headers) + { + result.AddHeader(h.Key, h.Value); + } + + // get body + var buffer = await response.Content.ReadAsBufferAsync(); + result.AddBody(buffer.ToArray()); + + return result; + } + } + } + + public class HttpSession + { + HttpBaseProtocolFilter m_filter; + public HttpBaseProtocolFilter Filter + { + get { return m_filter; } + } + + // Windows.Web.Httpの方。 + // System.Net.Httpではない。 + HttpClient m_client; + public HttpClient Client + { + get { return m_client; } + } + + public HttpSession() + { + m_filter = new HttpBaseProtocolFilter(); + m_filter.AllowAutoRedirect = false; + m_filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Expired); + m_filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted); + m_filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName); + + m_filter.CacheControl.ReadBehavior = HttpCacheReadBehavior.MostRecent; + + m_client = new HttpClient(m_filter); + } + + public void AddCookie(string key, string value, string domain) + { + var cookieManager = Filter.CookieManager; + var cookie = new HttpCookie(key, domain, "/") + { + Value = value + }; + cookieManager.SetCookie(cookie); + } + + public Task Get(string url) + { + return Http.Get(this, url); + } + } + +#else + public static class Cert + { + static bool OnRemoteCertificateValidationCallback( + System.Object sender, + X509Certificate certificate, + X509Chain chain, + SslPolicyErrors sslPolicyErrors) + { + return true; + } + + static bool s_initialized; + + public static void Initialize() + { + if (s_initialized) return; + s_initialized = true; + + ServicePointManager.ServerCertificateValidationCallback = + new RemoteCertificateValidationCallback(OnRemoteCertificateValidationCallback); + } + } + + public class HttpResult + { + public HttpWebRequest Request; + public HttpWebResponse Response; + + public string Cookie + { + get + { + return Response.Headers["Set-Cookie"]; + } + } + + public IEnumerable GetBodyBytes() + { + var buffer = new Byte[1024]; + using (var data = Response.GetResponseStream()) + { + while(true) + { + var readSize = data.Read(buffer, 0, buffer.Length); + if (readSize == 0) + { + break; + } + for(int i=0; i Get(HttpSession session, string url) + { + var tcs = new TaskCompletionSource(); + + ThreadPool.QueueUserWorkItem(_ => + { + try + { + var request = (HttpWebRequest)System.Net.WebRequest.Create(url); + request.CookieContainer = session.CookieContainer; + request.UserAgent = HttpConst.UserAgent; + //((HttpWebRequest)request).UserAgent = ".NET Framework Example Client"; + var response = (HttpWebResponse)request.GetResponse(); + tcs.SetResult(new HttpResult(request, response)); + } + catch (Exception ex) + { + tcs.SetException(ex); + } + }); + + return tcs.Task; + } + + public static Task PostForm(HttpSession session, string url, + Dictionary form) + { + var postData = string.Join("&", form.Select(kv => kv.Key + "=" + Uri.EscapeDataString(kv.Value)).ToArray()); + var postDataBytes = Encoding.ASCII.GetBytes(postData); + return Post(session, url, "application/x-www-form-urlencoded", postDataBytes); + } + + public static Task Post(HttpSession session, string url, + string contentType, Byte[] bytes) + { + var tcs = new TaskCompletionSource(); + + ThreadPool.QueueUserWorkItem(_ => + { + try + { + var request = (HttpWebRequest)System.Net.WebRequest.Create(url); + request.Method = "POST"; + request.ContentType = contentType; + request.ContentLength = bytes.Length; + request.AllowAutoRedirect = false; + request.CookieContainer = session.CookieContainer; + request.UserAgent = HttpConst.UserAgent; + + using (var reqStream = request.GetRequestStream()) + { + reqStream.Write(bytes, 0, bytes.Length); + reqStream.Close(); + } + + var response = (HttpWebResponse)request.GetResponse(); + tcs.SetResult(new HttpResult(request, response)); + } + catch (Exception ex) + { + tcs.SetException(ex); + } + }); + + return tcs.Task; + } + } + + public class HttpSession + { + CookieContainer m_cc = new CookieContainer(); + public CookieContainer CookieContainer + { + get { return m_cc; } + } + + public HttpSession() + { + Cert.Initialize(); + } + + public void AddCookie(string key, string value, string domain) + { + var cookie = new Cookie(key, value) { Domain = domain }; + m_cc.Add(cookie); + } + + public Task Get(string url) + { + return Http.Get(this, url); + } + } +#endif +} diff --git a/Source/HtmlRenderer.SimpleBrowser/Program.cs b/Source/HtmlRenderer.SimpleBrowser/Program.cs new file mode 100644 index 000000000..476339ff2 --- /dev/null +++ b/Source/HtmlRenderer.SimpleBrowser/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace HtmlRenderer.SimpleBrowser +{ + static class Program + { + /// + /// アプリケーションのメイン エントリ ポイントです。 + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } +} diff --git a/Source/HtmlRenderer.SimpleBrowser/Properties/AssemblyInfo.cs b/Source/HtmlRenderer.SimpleBrowser/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..672d6b835 --- /dev/null +++ b/Source/HtmlRenderer.SimpleBrowser/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。 +// アセンブリに関連付けられている情報を変更するには、 +// これらの属性値を変更してください。 +[assembly: AssemblyTitle("HtmlRenderer.SimpleBrowser")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("HtmlRenderer.SimpleBrowser")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible を false に設定すると、このアセンブリ内の型は COM コンポーネントから +// 参照できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、 +// その型の ComVisible 属性を true に設定してください。 +[assembly: ComVisible(false)] + +// このプロジェクトが COM に公開される場合、次の GUID が typelib の ID になります +[assembly: Guid("ef7f91e6-b633-4c15-b0f3-93d062c0ecc3")] + +// アセンブリのバージョン情報は次の 4 つの値で構成されています: +// +// メジャー バージョン +// マイナー バージョン +// ビルド番号 +// Revision +// +// すべての値を指定するか、次を使用してビルド番号とリビジョン番号を既定に設定できます +// 既定値にすることができます: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Source/HtmlRenderer.SimpleBrowser/Properties/Resources.Designer.cs b/Source/HtmlRenderer.SimpleBrowser/Properties/Resources.Designer.cs new file mode 100644 index 000000000..db0ca651b --- /dev/null +++ b/Source/HtmlRenderer.SimpleBrowser/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// このコードはツールによって生成されました。 +// ランタイム バージョン:4.0.30319.42000 +// +// このファイルへの変更は、以下の状況下で不正な動作の原因になったり、 +// コードが再生成されるときに損失したりします +// +//------------------------------------------------------------------------------ + +namespace HtmlRenderer.SimpleBrowser.Properties +{ + + + /// + /// ローカライズされた文字列などを検索するための、厳密に型指定されたリソース クラスです。 + /// + // このクラスは StronglyTypedResourceBuilder クラスが ResGen + // または Visual Studio のようなツールを使用して自動生成されました。 + // メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に + // ResGen を実行し直すか、または VS プロジェクトをリビルドします。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// このクラスで使用されるキャッシュされた ResourceManager インスタンスを返します。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("HtmlRenderer.SimpleBrowser.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 厳密に型指定されたこのリソース クラスを使用して、すべての検索リソースに対し、 + /// 現在のスレッドの CurrentUICulture プロパティをオーバーライドします。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/Source/HtmlRenderer.SimpleBrowser/Properties/Resources.resx b/Source/HtmlRenderer.SimpleBrowser/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/Source/HtmlRenderer.SimpleBrowser/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Source/HtmlRenderer.SimpleBrowser/Properties/Settings.Designer.cs b/Source/HtmlRenderer.SimpleBrowser/Properties/Settings.Designer.cs new file mode 100644 index 000000000..b084f336b --- /dev/null +++ b/Source/HtmlRenderer.SimpleBrowser/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace HtmlRenderer.SimpleBrowser.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Source/HtmlRenderer.SimpleBrowser/Properties/Settings.settings b/Source/HtmlRenderer.SimpleBrowser/Properties/Settings.settings new file mode 100644 index 000000000..39645652a --- /dev/null +++ b/Source/HtmlRenderer.SimpleBrowser/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Source/HtmlRenderer.WinForms/HtmlLabel.cs b/Source/HtmlRenderer.WinForms/HtmlLabel.cs index 6fe034b76..79b06e34d 100644 --- a/Source/HtmlRenderer.WinForms/HtmlLabel.cs +++ b/Source/HtmlRenderer.WinForms/HtmlLabel.cs @@ -138,8 +138,23 @@ public HtmlLabel() ResumeLayout(false); } - public IResourceServer ResourceServer; - + IResourceServer _resourceServer; + public IResourceServer ResourceServer + { + get + { + if (_resourceServer == null) + { + _resourceServer = ResourceServerFactory.Create(); + } + return _resourceServer; + } + set + { + if (_resourceServer == value) return; + _resourceServer = value; + } + } /// /// Raised when the BorderStyle property value changes. /// diff --git a/Source/HtmlRenderer.WinForms/HtmlPanel.cs b/Source/HtmlRenderer.WinForms/HtmlPanel.cs index 2f57c7d7c..38e660730 100644 --- a/Source/HtmlRenderer.WinForms/HtmlPanel.cs +++ b/Source/HtmlRenderer.WinForms/HtmlPanel.cs @@ -105,7 +105,7 @@ public class HtmlPanel : ScrollableControl protected Point _lastScrollOffset; IResourceServer _resourceServer; - IResourceServer ResourceServer + public IResourceServer ResourceServer { get { @@ -115,6 +115,11 @@ IResourceServer ResourceServer } return _resourceServer; } + set + { + if (_resourceServer == value) return; + _resourceServer = value; + } } #endregion diff --git a/Source/HtmlRenderer.WinForms/HtmlToolTip.cs b/Source/HtmlRenderer.WinForms/HtmlToolTip.cs index b25055119..6eaa69bff 100644 --- a/Source/HtmlRenderer.WinForms/HtmlToolTip.cs +++ b/Source/HtmlRenderer.WinForms/HtmlToolTip.cs @@ -110,7 +110,23 @@ public HtmlToolTip() #endif } - public IResourceServer ResourceServer; + IResourceServer _resourceServer; + public IResourceServer ResourceServer + { + get + { + if (_resourceServer == null) + { + _resourceServer = ResourceServerFactory.Create(); + } + return _resourceServer; + } + set + { + if (_resourceServer == value) return; + _resourceServer = value; + } + } #if !MONO /// diff --git a/Source/HtmlRenderer.sln b/Source/HtmlRenderer.sln index cf7aaa634..e44542265 100644 --- a/Source/HtmlRenderer.sln +++ b/Source/HtmlRenderer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.30501.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.27703.2035 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Demo", "Demo", "{E263EA16-2E6A-4269-A319-AA2F97ADA8E1}" EndProject @@ -26,6 +26,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{AA47D1 .nuget\NuGet.targets = .nuget\NuGet.targets EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HtmlRenderer.SimpleBrowser", "HtmlRenderer.SimpleBrowser\HtmlRenderer.SimpleBrowser.csproj", "{EF7F91E6-B633-4C15-B0F3-93D062C0ECC3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -106,6 +108,18 @@ Global {CA249F5D-9285-40A6-B217-5889EF79FD7E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {CA249F5D-9285-40A6-B217-5889EF79FD7E}.Release|Mixed Platforms.Build.0 = Release|Any CPU {CA249F5D-9285-40A6-B217-5889EF79FD7E}.Release|x86.ActiveCfg = Release|Any CPU + {EF7F91E6-B633-4C15-B0F3-93D062C0ECC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF7F91E6-B633-4C15-B0F3-93D062C0ECC3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF7F91E6-B633-4C15-B0F3-93D062C0ECC3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {EF7F91E6-B633-4C15-B0F3-93D062C0ECC3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {EF7F91E6-B633-4C15-B0F3-93D062C0ECC3}.Debug|x86.ActiveCfg = Debug|Any CPU + {EF7F91E6-B633-4C15-B0F3-93D062C0ECC3}.Debug|x86.Build.0 = Debug|Any CPU + {EF7F91E6-B633-4C15-B0F3-93D062C0ECC3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF7F91E6-B633-4C15-B0F3-93D062C0ECC3}.Release|Any CPU.Build.0 = Release|Any CPU + {EF7F91E6-B633-4C15-B0F3-93D062C0ECC3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {EF7F91E6-B633-4C15-B0F3-93D062C0ECC3}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {EF7F91E6-B633-4C15-B0F3-93D062C0ECC3}.Release|x86.ActiveCfg = Release|Any CPU + {EF7F91E6-B633-4C15-B0F3-93D062C0ECC3}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -115,4 +129,7 @@ Global {8AD34FE8-8382-4A8A-B3AA-A0392ED42423} = {E263EA16-2E6A-4269-A319-AA2F97ADA8E1} {F02E0216-4AE3-474F-9381-FCB93411CDB0} = {E263EA16-2E6A-4269-A319-AA2F97ADA8E1} EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5BC13AB8-4BC5-46EF-BF02-084216698E5E} + EndGlobalSection EndGlobal diff --git a/Source/HtmlRenderer/Core/IResourceServer.cs b/Source/HtmlRenderer/Core/IResourceServer.cs index 4a2264aa4..008ae5f49 100644 --- a/Source/HtmlRenderer/Core/IResourceServer.cs +++ b/Source/HtmlRenderer/Core/IResourceServer.cs @@ -18,11 +18,48 @@ public interface IResourceServer: IDisposable Task GetImageAsync(string location, Dictionary attributes); } + public class DefaultResourceServer : IResourceServer + { + public void Dispose() + { + } + + string m_html; + public void SetHtml(string html) + { + m_html = html; + } + public async Task GetHtmlAsync() + { + return m_html; + } + + CssData m_cssData; + public void SetCssData(CssData cssData) + { + m_cssData = cssData; + } + public async Task GetCssDataAsync() + { + return m_cssData; + } + + public Task GetCssDataAsync(string location, Dictionary attributes) + { + throw new NotImplementedException(); + } + + public Task GetImageAsync(string location, Dictionary attributes) + { + throw new NotImplementedException(); + } + } + public static class ResourceServerFactory { public delegate IResourceServer Factory(); - static Factory s_func; + static Factory s_func = () => new DefaultResourceServer(); public static void Iniialize(Factory func) { From b80cc935ccbb36f7c8b92a1201dd29412d083116 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 10 Jul 2018 04:24:30 +0900 Subject: [PATCH 5/9] Implemented HttpResourceServer --- Source/HtmlRenderer.PdfSharp/HtmlContainer.cs | 2 +- Source/HtmlRenderer.SimpleBrowser/Form1.cs | 3 +- .../HttpResourceServer.cs | 207 ++++++++++++++++-- .../HtmlRenderer.SimpleBrowser/HttpSession.cs | 2 +- Source/HtmlRenderer.WinForms/HtmlContainer.cs | 4 +- Source/HtmlRenderer.WinForms/HtmlLabel.cs | 24 +- Source/HtmlRenderer.WinForms/HtmlPanel.cs | 28 ++- Source/HtmlRenderer.WinForms/HtmlRender.cs | 74 +++---- Source/HtmlRenderer.WinForms/HtmlToolTip.cs | 4 +- Source/HtmlRenderer/Core/Dom/CssBox.cs | 10 +- Source/HtmlRenderer/Core/Dom/CssBoxImage.cs | 14 +- Source/HtmlRenderer/Core/HtmlContainerInt.cs | 10 +- Source/HtmlRenderer/Core/IResourceServer.cs | 68 ++++-- Source/HtmlRenderer/Core/Parse/DomParser.cs | 10 +- 14 files changed, 335 insertions(+), 125 deletions(-) diff --git a/Source/HtmlRenderer.PdfSharp/HtmlContainer.cs b/Source/HtmlRenderer.PdfSharp/HtmlContainer.cs index 82fec554e..39806f52b 100644 --- a/Source/HtmlRenderer.PdfSharp/HtmlContainer.cs +++ b/Source/HtmlRenderer.PdfSharp/HtmlContainer.cs @@ -238,7 +238,7 @@ public string SelectedHtml /// optional: the stylesheet to init with, init default if not given public Task SetResourceServerAsync(IResourceServer resourceServer) { - return _htmlContainerInt.SetResoureServerAsync(resourceServer); + return _htmlContainerInt.SetResoureServer(resourceServer); } /// diff --git a/Source/HtmlRenderer.SimpleBrowser/Form1.cs b/Source/HtmlRenderer.SimpleBrowser/Form1.cs index af70a0b72..317f3235b 100644 --- a/Source/HtmlRenderer.SimpleBrowser/Form1.cs +++ b/Source/HtmlRenderer.SimpleBrowser/Form1.cs @@ -21,8 +21,7 @@ private async void Go_btn_Click(object sender, EventArgs e) { Console.WriteLine($"go {url.Text}"); await m_server.Go(url.Text); - //htmlPanel1.Invalidate(); - htmlPanel1.Text = await m_server.GetHtmlAsync(); + htmlPanel1.Text = m_server.Html; } } } diff --git a/Source/HtmlRenderer.SimpleBrowser/HttpResourceServer.cs b/Source/HtmlRenderer.SimpleBrowser/HttpResourceServer.cs index 239cd3f62..d4e4ceccb 100644 --- a/Source/HtmlRenderer.SimpleBrowser/HttpResourceServer.cs +++ b/Source/HtmlRenderer.SimpleBrowser/HttpResourceServer.cs @@ -1,10 +1,13 @@ using System; +using System.Collections; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using TheArtOfDev.HtmlRenderer.Adapters; using TheArtOfDev.HtmlRenderer.Core; +using TheArtOfDev.HtmlRenderer.WinForms.Adapters; namespace HtmlRenderer.SimpleBrowser @@ -12,6 +15,74 @@ namespace HtmlRenderer.SimpleBrowser class HttpResourceServer : IResourceServer { string m_url; + string Url + { + get { return m_url; } + set + { + if (m_url == value) return; + m_url =value; + // url updated + if (m_url.EndsWith("/")) + { + m_baseUrl = m_url; + } + else + { + m_baseUrl = Path.GetDirectoryName(m_url); + } + + var uri = new Uri(m_url); + var port = ""; + if(uri.Scheme=="http" && uri.Port != 80) + { + port = ":" + uri.Port; + } + else if(uri.Scheme=="https" && uri.Port !=443) + { + port = ":" + uri.Port; + } + m_baseUrlWithoutPath = $"{uri.Scheme}://{uri.Host}{port}"; + } + } + string m_baseUrl; + string BaseUrl + { + get { return m_baseUrl; } + } + string m_baseUrlWithoutPath; + string BaseUrlWithoutPath + { + get { return m_baseUrlWithoutPath; } + } + public async Task Go(string url) + { + var result = await m_session.GetAsync(url); + var bytes = result.GetBodyBytes(); + Url = url; + Html = Encoding.UTF8.GetString(bytes.ToArray()); + } + + string GetUrl(string href) + { + if (href.StartsWith("http:") + || href.StartsWith("https:")) + { + // external + return href; + } + else if(href.StartsWith("/")) + { + // absolute path + return BaseUrlWithoutPath + href; + } + else + { + // relative path + return BaseUrl + href; + } + } + HttpSession m_session; public HttpResourceServer() @@ -19,47 +90,143 @@ public HttpResourceServer() m_session = new HttpSession(); } - public async Task Go(string url) + public void Dispose() { - var result = await m_session.Get(url); - var bytes = result.GetBodyBytes(); - m_html = Encoding.UTF8.GetString(bytes.ToArray()); } - #region Interface - public void Dispose() + public event EventHandler Updated; + void RaiseUpdated() { + var handler = Updated; + if (handler != null) + { + handler(this, new ResourceServerUpdatedEventArgs()); + } } string m_html; - public void SetHtml(string html) + public string Html { - m_html = html; + get { return m_html; } + set + { + if (m_html == value) return; + m_html = value; + RaiseUpdated(); + } } - public async Task GetHtmlAsync() + + CssData m_cssData; + public CssData CssData { - return m_html; + get { return m_cssData; } + set + { + if (m_cssData == value) return; + m_cssData = value; + RaiseUpdated(); + } } - CssData m_cssData; - public void SetCssData(CssData cssData) + class HttpTask + { + public Task Task; + public Byte[] Bytes; + + HttpTask() { } + + public static HttpTask Create(Task task, Action callback) + { + var httpTask = new HttpTask(); + httpTask.Task = task.ContinueWith(x => + { + httpTask.Bytes = x.Result.GetBodyBytes().ToArray(); + callback(); + return x.Result; + }); + return httpTask; + } + + CssData m_cssData; + public CssData GetCssData(RAdapter adapter) + { + if (Bytes == null) return null; + + if (m_cssData == null) + { + var css = Encoding.UTF8.GetString(Task.Result.GetBodyBytes().ToArray()); + m_cssData = CssData.Parse(adapter, css); + } + return m_cssData; + } + + RImage m_image; + public RImage GetImage(RAdapter adapter) + { + if (Bytes == null) return null; + + if (m_image == null) + { + using (var ms = new MemoryStream(Bytes)) + { + m_image = adapter.ImageFromStream(ms); + } + } + return m_image; + } + } + + Dictionary m_resultMap=new Dictionary(); + void PushTask(string href, HttpTask body) { - m_cssData = cssData; + lock (((ICollection)m_resultMap).SyncRoot){ + m_resultMap[href] = body; + } } - public async Task GetCssDataAsync() + HttpTask GetTask(string href) { - return m_cssData; + lock (((ICollection)m_resultMap).SyncRoot) { + HttpTask httpTask; + if (!m_resultMap.TryGetValue(href, out httpTask)) + { + return null; + } + return httpTask; + } } - public Task GetCssDataAsync(string location, Dictionary attributes) + public CssData GetCssData(/*RAdapter adapter,*/ string href, Dictionary attributes) { - throw new NotImplementedException(); + HttpTask task; + if (m_resultMap.TryGetValue(href, out task)) + { + // found + var adapter = WinFormsAdapter.Instance; + return task.GetCssData(adapter); + } + + // not found. request + var url = GetUrl(href); + var newTask = HttpTask.Create(m_session.GetAsync(url), RaiseUpdated); + PushTask(href, newTask); + return null; } - public Task GetImageAsync(string location, Dictionary attributes) + public RImage GetImage(/*RAdapter adapter,*/ string href, Dictionary attributes) { - throw new NotImplementedException(); + HttpTask task; + if (m_resultMap.TryGetValue(href, out task)) + { + // found + var adapter = WinFormsAdapter.Instance; + return task.GetImage(adapter); + } + + // not found. request + var url = GetUrl(href); + var newTask = HttpTask.Create(m_session.GetAsync(url), RaiseUpdated); + PushTask(href, newTask); + return null; } - #endregion } } diff --git a/Source/HtmlRenderer.SimpleBrowser/HttpSession.cs b/Source/HtmlRenderer.SimpleBrowser/HttpSession.cs index 7b2bef848..5263755b3 100644 --- a/Source/HtmlRenderer.SimpleBrowser/HttpSession.cs +++ b/Source/HtmlRenderer.SimpleBrowser/HttpSession.cs @@ -324,7 +324,7 @@ public void AddCookie(string key, string value, string domain) m_cc.Add(cookie); } - public Task Get(string url) + public Task GetAsync(string url) { return Http.Get(this, url); } diff --git a/Source/HtmlRenderer.WinForms/HtmlContainer.cs b/Source/HtmlRenderer.WinForms/HtmlContainer.cs index 64cb396df..6c5832b72 100644 --- a/Source/HtmlRenderer.WinForms/HtmlContainer.cs +++ b/Source/HtmlRenderer.WinForms/HtmlContainer.cs @@ -257,9 +257,9 @@ public void ClearSelection() /// /// the html to init with, init empty if not given /// optional: the stylesheet to init with, init default if not given - public Task SetResourceServerAsync(IResourceServer resourceServer) + public void SetResourceServer(IResourceServer resourceServer) { - return _htmlContainerInt.SetResoureServerAsync(resourceServer); + _htmlContainerInt.SetResoureServer(resourceServer); } /// diff --git a/Source/HtmlRenderer.WinForms/HtmlLabel.cs b/Source/HtmlRenderer.WinForms/HtmlLabel.cs index 79b06e34d..c66d8ee1c 100644 --- a/Source/HtmlRenderer.WinForms/HtmlLabel.cs +++ b/Source/HtmlRenderer.WinForms/HtmlLabel.cs @@ -119,6 +119,7 @@ public class HtmlLabel : Control /// public HtmlLabel() { + SuspendLayout(); AutoSize = true; @@ -138,6 +139,20 @@ public HtmlLabel() ResumeLayout(false); } + private void ResourceServer_Updated(object sender, ResourceServerUpdatedEventArgs e) + { + if (InvokeRequired) + { + Action callback = () => ResourceServer_Updated(sender, e); + Invoke(callback); + return; + } + + _htmlContainer.SetResourceServer(ResourceServer); + PerformLayout(); + Invalidate(); + } + IResourceServer _resourceServer; public IResourceServer ResourceServer { @@ -153,6 +168,7 @@ public IResourceServer ResourceServer { if (_resourceServer == value) return; _resourceServer = value; + _resourceServer.Updated += ResourceServer_Updated; } } /// @@ -309,8 +325,7 @@ public virtual string BaseStylesheet { _baseRawCssData = value; _baseCssData = HtmlRender.ParseStyleSheet(value); - ResourceServer.SetCssData(_baseCssData); - _htmlContainer.SetResourceServerAsync(ResourceServer); + ResourceServer.CssData=_baseCssData; } } @@ -403,10 +418,7 @@ public override string Text base.Text = value; if (!IsDisposed) { - ResourceServer.SetHtml(_text); - _htmlContainer.SetResourceServerAsync(ResourceServer); - PerformLayout(); - Invalidate(); + ResourceServer.Html=_text; } } } diff --git a/Source/HtmlRenderer.WinForms/HtmlPanel.cs b/Source/HtmlRenderer.WinForms/HtmlPanel.cs index 38e660730..53d63f5a2 100644 --- a/Source/HtmlRenderer.WinForms/HtmlPanel.cs +++ b/Source/HtmlRenderer.WinForms/HtmlPanel.cs @@ -119,6 +119,7 @@ public IResourceServer ResourceServer { if (_resourceServer == value) return; _resourceServer = value; + _resourceServer.Updated += ResourceServer_Updated; } } #endregion @@ -143,6 +144,21 @@ public HtmlPanel() _htmlContainer.ScrollChange += OnScrollChange; } + private void ResourceServer_Updated(object sender, ResourceServerUpdatedEventArgs e) + { + if (InvokeRequired) + { + Action callback = () => ResourceServer_Updated(sender, e); + Invoke(callback); + return; + } + + _htmlContainer.SetResourceServer(ResourceServer); + PerformLayout(); + Invalidate(); + InvokeMouseMove(); + } + /// /// Raised when the BorderStyle property value changes. /// @@ -291,8 +307,7 @@ public virtual string BaseStylesheet { _baseRawCssData = value; _baseCssData = HtmlRender.ParseStyleSheet(value); - ResourceServer.SetCssData(_baseCssData); - _htmlContainer.SetResourceServerAsync(ResourceServer); + ResourceServer.CssData = _baseCssData; } } @@ -317,16 +332,13 @@ public override string Text get { return _text; } set { + if (_text == value) return; _text = value; - base.Text = value; + if (!IsDisposed) { VerticalScroll.Value = VerticalScroll.Minimum; - ResourceServer.SetHtml(_text); - _htmlContainer.SetResourceServerAsync(ResourceServer); - PerformLayout(); - Invalidate(); - InvokeMouseMove(); + ResourceServer.Html=_text; } } } diff --git a/Source/HtmlRenderer.WinForms/HtmlRender.cs b/Source/HtmlRenderer.WinForms/HtmlRender.cs index 4e29f4c21..45e536a61 100644 --- a/Source/HtmlRenderer.WinForms/HtmlRender.cs +++ b/Source/HtmlRenderer.WinForms/HtmlRender.cs @@ -149,7 +149,7 @@ public static CssData ParseStyleSheet(string stylesheet, bool combineWithDefault /// optional: can be used to overwrite stylesheet resolution logic /// optional: can be used to overwrite image resolution logic /// the size required for the html - public static Task Measure(Graphics g, IResourceServer resourceServer, + public static SizeF Measure(Graphics g, IResourceServer resourceServer, float maxWidth = 0 ) { @@ -171,7 +171,7 @@ public static Task Measure(Graphics g, IResourceServer resourceServer, /// optional: can be used to overwrite stylesheet resolution logic /// optional: can be used to overwrite image resolution logic /// the size required for the html - public static Task MeasureGdiPlus(Graphics g, IResourceServer resourceServer, + public static SizeF MeasureGdiPlus(Graphics g, IResourceServer resourceServer, float maxWidth = 0 ) { @@ -196,7 +196,7 @@ public static Task MeasureGdiPlus(Graphics g, IResourceServer resourceSer /// optional: can be used to overwrite stylesheet resolution logic /// optional: can be used to overwrite image resolution logic /// the actual size of the rendered html - public static Task Render(Graphics g, IResourceServer resourceServer, + public static SizeF Render(Graphics g, IResourceServer resourceServer, float left = 0, float top = 0, float maxWidth = 0) { ArgChecker.AssertArgNotNull(g, "g"); @@ -220,7 +220,7 @@ public static Task Render(Graphics g, IResourceServer resourceServer, /// optional: can be used to overwrite stylesheet resolution logic /// optional: can be used to overwrite image resolution logic /// the actual size of the rendered html - public static Task Render(Graphics g, IResourceServer resourceServer, + public static SizeF Render(Graphics g, IResourceServer resourceServer, PointF location, SizeF maxSize) { ArgChecker.AssertArgNotNull(g, "g"); @@ -244,7 +244,7 @@ public static Task Render(Graphics g, IResourceServer resourceServer, /// optional: can be used to overwrite stylesheet resolution logic /// optional: can be used to overwrite image resolution logic /// the actual size of the rendered html - public static Task RenderGdiPlus(Graphics g, IResourceServer resouerceServer, + public static SizeF RenderGdiPlus(Graphics g, IResourceServer resouerceServer, float left = 0, float top = 0, float maxWidth = 0 ) { @@ -269,7 +269,7 @@ public static Task RenderGdiPlus(Graphics g, IResourceServer resouerceSer /// optional: can be used to overwrite stylesheet resolution logic /// optional: can be used to overwrite image resolution logic /// the actual size of the rendered html - public static Task RenderGdiPlus(Graphics g, IResourceServer resourceServer, + public static SizeF RenderGdiPlus(Graphics g, IResourceServer resourceServer, PointF location, SizeF maxSize ) { @@ -292,7 +292,7 @@ public static async Task RenderToMetafile(IResourceServer resourceServ using (var g = Graphics.FromImage(image)) { - await Render(g, resourceServer, left, top, maxWidth); + Render(g, resourceServer, left, top, maxWidth); } } finally @@ -315,13 +315,13 @@ public static async Task RenderToMetafile(IResourceServer resourceServ /// optional: the style to use for html rendering (default - use W3 default style) /// optional: can be used to overwrite stylesheet resolution logic /// optional: can be used to overwrite image resolution logic - public static Task RenderToImage(Image image, IResourceServer resourceServer, + public static void RenderToImage(Image image, IResourceServer resourceServer, PointF location = new PointF() ) { ArgChecker.AssertArgNotNull(image, "image"); var maxSize = new SizeF(image.Size.Width - location.X, image.Size.Height - location.Y); - return RenderToImage(image, resourceServer, location, maxSize); + RenderToImage(image, resourceServer, location, maxSize); } /// @@ -337,14 +337,13 @@ public static Task RenderToImage(Image image, IResourceServer resourceServer, /// optional: the style to use for html rendering (default - use W3 default style) /// optional: can be used to overwrite stylesheet resolution logic /// optional: can be used to overwrite image resolution logic - public static async Task RenderToImage(Image image, IResourceServer resourceServer, + public static void RenderToImage(Image image, IResourceServer resourceServer, PointF location, SizeF maxSize ) { ArgChecker.AssertArgNotNull(image, "image"); - var html = await resourceServer.GetHtmlAsync(); - if (!string.IsNullOrEmpty(html)) + if (!string.IsNullOrEmpty(resourceServer.Html)) { // create memory buffer from desktop handle that supports alpha channel IntPtr dib; @@ -358,7 +357,7 @@ public static async Task RenderToImage(Image image, IResourceServer resourceServ memoryGraphics.DrawImageUnscaled(image, 0, 0); // render HTML into the memory buffer - await RenderHtml(memoryGraphics, resourceServer, location, maxSize, false); + RenderHtml(memoryGraphics, resourceServer, location, maxSize, false); } // copy from memory buffer to image @@ -387,7 +386,7 @@ public static async Task RenderToImage(Image image, IResourceServer resourceServ /// optional: can be used to overwrite image resolution logic /// the generated image of the html /// if is . - public static async Task RenderToImage(IResourceServer resourceServer, + public static Image RenderToImage(IResourceServer resourceServer, Size size, Color backgroundColor = new Color() ) { @@ -397,8 +396,7 @@ public static async Task RenderToImage(IResourceServer resourceServer, // create the final image to render into var image = new Bitmap(size.Width, size.Height, PixelFormat.Format32bppArgb); - var html = await resourceServer.GetHtmlAsync(); - if (!string.IsNullOrEmpty(html)) + if (!string.IsNullOrEmpty(resourceServer.Html)) { // create memory buffer from desktop handle that supports alpha channel IntPtr dib; @@ -411,7 +409,7 @@ public static async Task RenderToImage(IResourceServer resourceServer, memoryGraphics.Clear(backgroundColor != Color.Empty ? backgroundColor : Color.White); // render HTML into the memory buffer - await RenderHtml(memoryGraphics, resourceServer, PointF.Empty, size, true); + RenderHtml(memoryGraphics, resourceServer, PointF.Empty, size, true); } // copy from memory buffer to image @@ -446,7 +444,7 @@ public static async Task RenderToImage(IResourceServer resourceServer, /// optional: can be used to overwrite image resolution logic /// the generated image of the html /// if is . - public static Task RenderToImage(IResourceServer resourceServer, + public static Image RenderToImage(IResourceServer resourceServer, int maxWidth = 0, int maxHeight = 0, Color backgroundColor = new Color() ) { @@ -474,20 +472,19 @@ public static Task RenderToImage(IResourceServer resourceServer, /// optional: can be used to overwrite image resolution logic /// the generated image of the html /// if is . - public static async Task RenderToImage(IResourceServer resourceServer, + public static Image RenderToImage(IResourceServer resourceServer, Size minSize, Size maxSize, Color backgroundColor = new Color(), CssData cssData = null ) { if (backgroundColor == Color.Transparent) throw new ArgumentOutOfRangeException("backgroundColor", "Transparent background in not supported"); - var html = await resourceServer.GetHtmlAsync(); - if (string.IsNullOrEmpty(html)) + if (string.IsNullOrEmpty(resourceServer.Html)) return new Bitmap(0, 0, PixelFormat.Format32bppArgb); using (var container = new HtmlContainer()) { - await container.SetResourceServerAsync(resourceServer); + container.SetResourceServer(resourceServer); var finalSize = MeasureHtmlByRestrictions(container, minSize, maxSize); container.MaxSize = finalSize; @@ -534,7 +531,7 @@ public static async Task RenderToImage(IResourceServer resourceServer, /// optional: can be used to overwrite stylesheet resolution logic /// optional: can be used to overwrite image resolution logic /// the generated image of the html - public static async Task RenderToImageGdiPlus(IResourceServer resourceServer, + public static Image RenderToImageGdiPlus(IResourceServer resourceServer, Size size, TextRenderingHint textRenderingHint = TextRenderingHint.AntiAlias) { var image = new Bitmap(size.Width, size.Height, PixelFormat.Format32bppArgb); @@ -542,7 +539,7 @@ public static async Task RenderToImageGdiPlus(IResourceServer resourceSer using (var g = Graphics.FromImage(image)) { g.TextRenderingHint = textRenderingHint; - await RenderHtml(g, resourceServer, PointF.Empty, size, true); + RenderHtml(g, resourceServer, PointF.Empty, size, true); } return image; @@ -566,7 +563,7 @@ public static async Task RenderToImageGdiPlus(IResourceServer resourceSer /// optional: can be used to overwrite stylesheet resolution logic /// optional: can be used to overwrite image resolution logic /// the generated image of the html - public static Task RenderToImageGdiPlus(IResourceServer resourceServer, + public static Image RenderToImageGdiPlus(IResourceServer resourceServer, int maxWidth = 0, int maxHeight = 0, TextRenderingHint textRenderingHint = TextRenderingHint.AntiAlias, CssData cssData = null ) { @@ -592,18 +589,17 @@ public static Task RenderToImageGdiPlus(IResourceServer resourceServer, /// optional: can be used to overwrite stylesheet resolution logic /// optional: can be used to overwrite image resolution logic /// the generated image of the html - public static async Task RenderToImageGdiPlus(IResourceServer resourceServer, Size minSize, Size maxSize, TextRenderingHint textRenderingHint = TextRenderingHint.AntiAlias, CssData cssData = null + public static Image RenderToImageGdiPlus(IResourceServer resourceServer, Size minSize, Size maxSize, TextRenderingHint textRenderingHint = TextRenderingHint.AntiAlias, CssData cssData = null ) { - var html = await resourceServer.GetHtmlAsync(); - if (string.IsNullOrEmpty(html)) + if (string.IsNullOrEmpty(resourceServer.Html)) return new Bitmap(0, 0, PixelFormat.Format32bppArgb); using (var container = new HtmlContainer()) { container.UseGdiPlusTextRendering = true; - await container.SetResourceServerAsync(resourceServer); + container.SetResourceServer(resourceServer); var finalSize = MeasureHtmlByRestrictions(container, minSize, maxSize); container.MaxSize = finalSize; @@ -636,21 +632,19 @@ public static async Task RenderToImageGdiPlus(IResourceServer resourceSer /// optional: can be used to overwrite stylesheet resolution logic /// optional: can be used to overwrite image resolution logic /// the size required for the html - private static async Task Measure(Graphics g, IResourceServer resourceServer, + private static SizeF Measure(Graphics g, IResourceServer resourceServer, float maxWidth, bool useGdiPlusTextRendering ) { - var html = await resourceServer.GetHtmlAsync(); - SizeF actualSize = SizeF.Empty; - if (!string.IsNullOrEmpty(html)) + if (!string.IsNullOrEmpty(resourceServer.Html)) { using (var container = new HtmlContainer()) { container.MaxSize = new SizeF(maxWidth, 0); container.UseGdiPlusTextRendering = useGdiPlusTextRendering; - await container.SetResourceServerAsync(resourceServer); + container.SetResourceServer(resourceServer); container.PerformLayout(g); actualSize = container.ActualSize; @@ -697,7 +691,7 @@ private static Size MeasureHtmlByRestrictions(HtmlContainer htmlContainer, Size /// optional: can be used to overwrite stylesheet resolution logic /// optional: can be used to overwrite image resolution logic /// the actual size of the rendered html - private static async Task RenderClip(Graphics g, IResourceServer resourceServer, + private static SizeF RenderClip(Graphics g, IResourceServer resourceServer, PointF location, SizeF maxSize, bool useGdiPlusTextRendering ) { @@ -708,7 +702,7 @@ private static async Task RenderClip(Graphics g, IResourceServer resource g.SetClip(new RectangleF(location, maxSize)); } - var actualSize = await RenderHtml(g, resourceServer, location, maxSize, useGdiPlusTextRendering); + var actualSize = RenderHtml(g, resourceServer, location, maxSize, useGdiPlusTextRendering); if (prevClip != null) { @@ -735,13 +729,11 @@ private static async Task RenderClip(Graphics g, IResourceServer resource /// optional: can be used to overwrite stylesheet resolution logic /// optional: can be used to overwrite image resolution logic /// the actual size of the rendered html - private static async Task RenderHtml(Graphics g, IResourceServer resourceServer, PointF location, SizeF maxSize, bool useGdiPlusTextRendering + private static SizeF RenderHtml(Graphics g, IResourceServer resourceServer, PointF location, SizeF maxSize, bool useGdiPlusTextRendering ) { - var html = await resourceServer.GetHtmlAsync(); - SizeF actualSize = SizeF.Empty; - if (!string.IsNullOrEmpty(html)) + if (!string.IsNullOrEmpty(resourceServer.Html)) { using (var container = new HtmlContainer()) { @@ -749,7 +741,7 @@ private static async Task RenderHtml(Graphics g, IResourceServer resource container.MaxSize = maxSize; container.UseGdiPlusTextRendering = useGdiPlusTextRendering; - await container.SetResourceServerAsync(resourceServer); + container.SetResourceServer(resourceServer); container.PerformLayout(g); container.PerformPaint(g); diff --git a/Source/HtmlRenderer.WinForms/HtmlToolTip.cs b/Source/HtmlRenderer.WinForms/HtmlToolTip.cs index 6eaa69bff..8b25280bb 100644 --- a/Source/HtmlRenderer.WinForms/HtmlToolTip.cs +++ b/Source/HtmlRenderer.WinForms/HtmlToolTip.cs @@ -248,9 +248,9 @@ protected virtual void OnToolTipPopup(PopupEventArgs e) { //Create fragment container var cssClass = string.IsNullOrEmpty(_tooltipCssClass) ? null : string.Format(" class=\"{0}\"", _tooltipCssClass); - ResourceServer.SetHtml(string.Format("{1}", cssClass, GetToolTip(e.AssociatedControl))); + ResourceServer.Html=string.Format("{1}", cssClass, GetToolTip(e.AssociatedControl)); - _htmlContainer.SetResourceServerAsync(ResourceServer); + _htmlContainer.SetResourceServer(ResourceServer); _htmlContainer.MaxSize = MaximumSize; //Measure size of the container diff --git a/Source/HtmlRenderer/Core/Dom/CssBox.cs b/Source/HtmlRenderer/Core/Dom/CssBox.cs index 0a5b0864d..e17efcab2 100644 --- a/Source/HtmlRenderer/Core/Dom/CssBox.cs +++ b/Source/HtmlRenderer/Core/Dom/CssBox.cs @@ -690,7 +690,7 @@ protected virtual void PerformLayoutImp(RGraphics g) CreateListItemBox(g); - if (!IsFixed) + if (!IsFixed && HtmlContainer.Root!=null) { var actualWidth = Math.Max(GetMinimumWidth() + GetWidthMarginDeep(this), Size.Width < 90999 ? ActualRight - HtmlContainer.Root.Location.X : 0); HtmlContainer.ActualSize = CommonUtils.Max(HtmlContainer.ActualSize, new RSize(actualWidth, ActualBottom - HtmlContainer.Root.Location.Y)); @@ -721,13 +721,13 @@ internal virtual void MeasureWordsSize(RGraphics g) } } - async Task LoadBackgroundImageAsync() + void LoadBackgroundImageAsync() { if (BackgroundImage != CssConstants.None) { - var backgroundImage = await HtmlContainer.ResourceServer.GetImageAsync( - BackgroundImage, HtmlTag != null ? HtmlTag.Attributes : null); - + var backgroundImage = HtmlContainer.ResourceServer.GetImage( + BackgroundImage, + HtmlTag != null ? HtmlTag.Attributes : null); if (backgroundImage != null) { _backgroundImage = backgroundImage; diff --git a/Source/HtmlRenderer/Core/Dom/CssBoxImage.cs b/Source/HtmlRenderer/Core/Dom/CssBoxImage.cs index 577f9ba69..697ece644 100644 --- a/Source/HtmlRenderer/Core/Dom/CssBoxImage.cs +++ b/Source/HtmlRenderer/Core/Dom/CssBoxImage.cs @@ -137,17 +137,21 @@ internal override void MeasureWordsSize(RGraphics g) CssLayoutEngine.MeasureImageSize(_imageWord); } - async Task LoadImageAsync() + void LoadImageAsync() { RImage image; if (this.Content != null && this.Content != CssConstants.Normal) - image = await HtmlContainer.ResourceServer.GetImageAsync( - this.Content, + { + image = HtmlContainer.ResourceServer.GetImage( + this.Content, HtmlTag != null ? HtmlTag.Attributes : null); + } else - image = await HtmlContainer.ResourceServer.GetImageAsync( - GetAttribute("src"), + { + image = HtmlContainer.ResourceServer.GetImage( + GetAttribute("src"), HtmlTag != null ? HtmlTag.Attributes : null); + } _imageWord.Image = image; _imageWord.ImageRectangle = RRect.Empty; // rectangle; diff --git a/Source/HtmlRenderer/Core/HtmlContainerInt.cs b/Source/HtmlRenderer/Core/HtmlContainerInt.cs index 929c9a660..a0f4a1e0d 100644 --- a/Source/HtmlRenderer/Core/HtmlContainerInt.cs +++ b/Source/HtmlRenderer/Core/HtmlContainerInt.cs @@ -439,18 +439,16 @@ internal RColor SelectionBackColor set { _selectionBackColor = value; } } - public async Task SetResoureServerAsync(IResourceServer resourceServer) + public void SetResoureServer(IResourceServer resourceServer) { Clear(); _resourceServer = resourceServer; - var htmlSource = await resourceServer.GetHtmlAsync(); - - if (!string.IsNullOrEmpty(htmlSource)) + if (!string.IsNullOrEmpty(resourceServer.Html)) { _loadComplete = false; - var baseCssData = await resourceServer.GetCssDataAsync(); + var baseCssData = resourceServer.CssData; _cssData = baseCssData ?? _adapter.DefaultCssData; DomParser parser = new DomParser(_cssParser); @@ -458,7 +456,7 @@ public async Task SetResoureServerAsync(IResourceServer resourceServer) { cssData = _cssData }; - _root = await parser.GenerateCssTree(htmlSource, this, cssData); + _root = parser.GenerateCssTree(resourceServer.Html, this, cssData); if (cssData.cssDataChanged) { _cssData = cssData.cssData; diff --git a/Source/HtmlRenderer/Core/IResourceServer.cs b/Source/HtmlRenderer/Core/IResourceServer.cs index 008ae5f49..7043ae13b 100644 --- a/Source/HtmlRenderer/Core/IResourceServer.cs +++ b/Source/HtmlRenderer/Core/IResourceServer.cs @@ -6,50 +6,75 @@ namespace TheArtOfDev.HtmlRenderer.Core { - public interface IResourceServer: IDisposable + public class ResourceServerUpdatedEventArgs : EventArgs { - void SetHtml(string html); - Task GetHtmlAsync(); + } + + + public interface IResourceServer : IDisposable + { + String Html { get; set; } + CssData CssData { get; set; } - void SetCssData(CssData cssData); - Task GetCssDataAsync(); + event EventHandler Updated; - Task GetCssDataAsync(string location, Dictionary attributes); - Task GetImageAsync(string location, Dictionary attributes); + Task Go(string href); + CssData GetCssData(/*RAdapter adapter,*/ string href, Dictionary attributes); + RImage GetImage(/*RAdapter adapter, */ string href, Dictionary attributes); } + public class DefaultResourceServer : IResourceServer { - public void Dispose() + string m_html; + public string Html { + get { return m_html; } + set + { + if (m_html == value) return; + m_html = value; + RaiseUpdated(); + } } - string m_html; - public void SetHtml(string html) + CssData m_cssData; + public CssData CssData { - m_html = html; + get { return m_cssData; } + set + { + if (m_cssData == value) return; + m_cssData = value; + RaiseUpdated(); + } } - public async Task GetHtmlAsync() + + public event EventHandler Updated; + void RaiseUpdated() { - return m_html; + var handler = Updated; + if (handler != null) + { + handler(this, new ResourceServerUpdatedEventArgs()); + } } - CssData m_cssData; - public void SetCssData(CssData cssData) + public void Dispose() { - m_cssData = cssData; } - public async Task GetCssDataAsync() + + public CssData GetCssData(/*RAdapter adapter,*/ string href, Dictionary attributes) { - return m_cssData; + throw new NotImplementedException(); } - public Task GetCssDataAsync(string location, Dictionary attributes) + public RImage GetImage(/*RAdapter adapter,*/ string href, Dictionary attributes) { throw new NotImplementedException(); } - public Task GetImageAsync(string location, Dictionary attributes) + public Task Go(string href) { throw new NotImplementedException(); } @@ -68,6 +93,7 @@ public static void Iniialize(Factory func) public static IResourceServer Create() { - return s_func();} + return s_func(); + } } } diff --git a/Source/HtmlRenderer/Core/Parse/DomParser.cs b/Source/HtmlRenderer/Core/Parse/DomParser.cs index 3de09b99b..5b77a48ff 100644 --- a/Source/HtmlRenderer/Core/Parse/DomParser.cs +++ b/Source/HtmlRenderer/Core/Parse/DomParser.cs @@ -72,14 +72,14 @@ public void CloneCssData() /// the html container to use for reference resolve /// the css data to use /// the root of the generated tree - public async Task GenerateCssTree(string html, HtmlContainerInt htmlContainer, CssDataWithChanged cssData) + public CssBox GenerateCssTree(string html, HtmlContainerInt htmlContainer, CssDataWithChanged cssData) { var root = HtmlParser.ParseDocument(html); if (root != null) { root.HtmlContainer = htmlContainer; - await CascadeParseStyles(root, htmlContainer, cssData); + CascadeParseStyles(root, htmlContainer, cssData); CascadeApplyStyles(root, cssData.cssData); @@ -112,7 +112,7 @@ public async Task GenerateCssTree(string html, HtmlContainerInt htmlCont /// the html container to use for reference resolve /// the style data to fill with found styles /// check if the css data has been modified by the handled html not to change the base css data - private async Task CascadeParseStyles(CssBox box, HtmlContainerInt htmlContainer, CssDataWithChanged cssData) + private void CascadeParseStyles(CssBox box, HtmlContainerInt htmlContainer, CssDataWithChanged cssData) { if (box.HtmlTag != null) { @@ -122,7 +122,7 @@ private async Task CascadeParseStyles(CssBox box, HtmlContainerInt htmlContainer { cssData.CloneCssData(); - var stylesheetData = await htmlContainer.ResourceServer.GetCssDataAsync(box.GetAttribute("href", string.Empty), box.HtmlTag.Attributes); + var stylesheetData = htmlContainer.ResourceServer.GetCssData(box.GetAttribute("href", string.Empty), box.HtmlTag.Attributes); /* string stylesheet; @@ -150,7 +150,7 @@ private async Task CascadeParseStyles(CssBox box, HtmlContainerInt htmlContainer foreach (var childBox in box.Boxes) { - await CascadeParseStyles(childBox, htmlContainer, cssData); + CascadeParseStyles(childBox, htmlContainer, cssData); } } From f723cd912b498b174d0cfdd1ed3bf5f9fb74fc6e Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 10 Jul 2018 05:22:14 +0900 Subject: [PATCH 6/9] Fixed call GetBodyBytes twice --- .../HttpResourceServer.cs | 68 ++++++++++++------- .../HtmlRenderer.SimpleBrowser/HttpSession.cs | 17 +++-- 2 files changed, 57 insertions(+), 28 deletions(-) diff --git a/Source/HtmlRenderer.SimpleBrowser/HttpResourceServer.cs b/Source/HtmlRenderer.SimpleBrowser/HttpResourceServer.cs index d4e4ceccb..8702f9a37 100644 --- a/Source/HtmlRenderer.SimpleBrowser/HttpResourceServer.cs +++ b/Source/HtmlRenderer.SimpleBrowser/HttpResourceServer.cs @@ -21,7 +21,7 @@ string Url set { if (m_url == value) return; - m_url =value; + m_url = value; // url updated if (m_url.EndsWith("/")) { @@ -29,32 +29,33 @@ string Url } else { - m_baseUrl = Path.GetDirectoryName(m_url); + var splited = m_url.Split('/'); + m_baseUrl = string.Join("/", splited.Take(splited.Length-1)) + "/"; } var uri = new Uri(m_url); var port = ""; - if(uri.Scheme=="http" && uri.Port != 80) + if (uri.Scheme == "http" && uri.Port != 80) { port = ":" + uri.Port; } - else if(uri.Scheme=="https" && uri.Port !=443) + else if (uri.Scheme == "https" && uri.Port != 443) { port = ":" + uri.Port; } m_baseUrlWithoutPath = $"{uri.Scheme}://{uri.Host}{port}"; + + m_schema = "http:"; + if (uri.Scheme != "http") + { + m_schema = uri.Scheme + ":"; + } } } string m_baseUrl; - string BaseUrl - { - get { return m_baseUrl; } - } string m_baseUrlWithoutPath; - string BaseUrlWithoutPath - { - get { return m_baseUrlWithoutPath; } - } + string m_schema; + public async Task Go(string url) { var result = await m_session.GetAsync(url); @@ -71,15 +72,20 @@ string GetUrl(string href) // external return href; } - else if(href.StartsWith("/")) + else if (href.StartsWith("//")) { // absolute path - return BaseUrlWithoutPath + href; + return m_schema + href; + } + else if (href.StartsWith("/")) + { + // absolute path + return m_baseUrlWithoutPath + href; } else { // relative path - return BaseUrl + href; + return m_baseUrl + href; } } @@ -130,19 +136,35 @@ public CssData CssData class HttpTask { + public string Url; public Task Task; public Byte[] Bytes; HttpTask() { } - public static HttpTask Create(Task task, Action callback) + public static HttpTask Create(string url, Task task, Action callback) { - var httpTask = new HttpTask(); + Console.WriteLine($"[HttpTask.Create]{url}"); + var httpTask = new HttpTask + { + Url = url + }; httpTask.Task = task.ContinueWith(x => { - httpTask.Bytes = x.Result.GetBodyBytes().ToArray(); - callback(); - return x.Result; + try + { + if (x.IsCompleted) + { + httpTask.Bytes = x.Result.GetBodyBytes(); + callback(); + } + return x.Result; + } + catch(Exception ex) + { + Console.WriteLine($"{httpTask.Url} {ex}"); + throw; + } }); return httpTask; } @@ -154,7 +176,7 @@ public CssData GetCssData(RAdapter adapter) if (m_cssData == null) { - var css = Encoding.UTF8.GetString(Task.Result.GetBodyBytes().ToArray()); + var css = Encoding.UTF8.GetString(Bytes); m_cssData = CssData.Parse(adapter, css); } return m_cssData; @@ -207,7 +229,7 @@ public CssData GetCssData(/*RAdapter adapter,*/ string href, Dictionary GetBodyBytes() + public Byte[] GetBodyBytes() { - var buffer = new Byte[1024]; - using (var data = Response.GetResponseStream()) + using (var s = Response.GetResponseStream()) { - while(true) + var ms = new MemoryStream(); + s.CopyTo(ms); + return ms.ToArray(); + } + /* + { + while (true) { var readSize = data.Read(buffer, 0, buffer.Length); if (readSize == 0) { break; } - for(int i=0; i Get(HttpSession session, string url) var request = (HttpWebRequest)System.Net.WebRequest.Create(url); request.CookieContainer = session.CookieContainer; request.UserAgent = HttpConst.UserAgent; + request.KeepAlive = false; //((HttpWebRequest)request).UserAgent = ".NET Framework Example Client"; var response = (HttpWebResponse)request.GetResponse(); tcs.SetResult(new HttpResult(request, response)); From 0e1c47c851fe6f83fc6076af76e54509eca974ef Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 10 Jul 2018 13:00:54 +0900 Subject: [PATCH 7/9] Added ErrorHandling --- Source/HtmlRenderer.SimpleBrowser/HttpSession.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Source/HtmlRenderer.SimpleBrowser/HttpSession.cs b/Source/HtmlRenderer.SimpleBrowser/HttpSession.cs index 157126e3e..0a7df2501 100644 --- a/Source/HtmlRenderer.SimpleBrowser/HttpSession.cs +++ b/Source/HtmlRenderer.SimpleBrowser/HttpSession.cs @@ -210,6 +210,11 @@ public string Cookie public Byte[] GetBodyBytes() { + if (Response.StatusCode!=HttpStatusCode.OK) + { + return null; + } + using (var s = Response.GetResponseStream()) { var ms = new MemoryStream(); @@ -249,9 +254,10 @@ public static Task Get(HttpSession session, string url) ThreadPool.QueueUserWorkItem(_ => { + HttpWebRequest request = null; try { - var request = (HttpWebRequest)System.Net.WebRequest.Create(url); + request = (HttpWebRequest)System.Net.WebRequest.Create(url); request.CookieContainer = session.CookieContainer; request.UserAgent = HttpConst.UserAgent; request.KeepAlive = false; @@ -259,6 +265,11 @@ public static Task Get(HttpSession session, string url) var response = (HttpWebResponse)request.GetResponse(); tcs.SetResult(new HttpResult(request, response)); } + catch (WebException ex) + { + var response = (HttpWebResponse)ex.Response; + tcs.SetResult(new HttpResult(request, response)); + } catch (Exception ex) { tcs.SetException(ex); From 63527e2b86a572f8b961dc39a6b13fa882325f87 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 10 Jul 2018 13:01:07 +0900 Subject: [PATCH 8/9] Implemented LinkClicked --- Source/HtmlRenderer.SimpleBrowser/Form1.cs | 9 ++++++++- .../HtmlRenderer.SimpleBrowser/HttpResourceServer.cs | 10 +++++++--- Source/HtmlRenderer/Core/HtmlContainerInt.cs | 2 ++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Source/HtmlRenderer.SimpleBrowser/Form1.cs b/Source/HtmlRenderer.SimpleBrowser/Form1.cs index 317f3235b..9c8d52093 100644 --- a/Source/HtmlRenderer.SimpleBrowser/Form1.cs +++ b/Source/HtmlRenderer.SimpleBrowser/Form1.cs @@ -1,6 +1,6 @@ using System; using System.Windows.Forms; - +using TheArtOfDev.HtmlRenderer.Core.Entities; namespace HtmlRenderer.SimpleBrowser { @@ -14,9 +14,16 @@ public Form1() m_server = new HttpResourceServer(); htmlPanel1.ResourceServer = m_server; + htmlPanel1.LinkClicked += HtmlPanel1_LinkClicked; go_btn.Click += Go_btn_Click; } + private async void HtmlPanel1_LinkClicked(object sender, HtmlLinkClickedEventArgs e) + { + await m_server.Go(e.Link); + //htmlPanel1.Text = m_server.Html; + } + private async void Go_btn_Click(object sender, EventArgs e) { Console.WriteLine($"go {url.Text}"); diff --git a/Source/HtmlRenderer.SimpleBrowser/HttpResourceServer.cs b/Source/HtmlRenderer.SimpleBrowser/HttpResourceServer.cs index 8702f9a37..277cb499f 100644 --- a/Source/HtmlRenderer.SimpleBrowser/HttpResourceServer.cs +++ b/Source/HtmlRenderer.SimpleBrowser/HttpResourceServer.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net; using System.Text; using System.Threading.Tasks; using TheArtOfDev.HtmlRenderer.Adapters; @@ -56,8 +57,9 @@ string Url string m_baseUrlWithoutPath; string m_schema; - public async Task Go(string url) + public async Task Go(string href) { + var url = GetUrl(href); var result = await m_session.GetAsync(url); var bytes = result.GetBodyBytes(); Url = url; @@ -139,6 +141,7 @@ class HttpTask public string Url; public Task Task; public Byte[] Bytes; + public Exception Error; HttpTask() { } @@ -157,14 +160,15 @@ public static HttpTask Create(string url, Task task, Action callback { httpTask.Bytes = x.Result.GetBodyBytes(); callback(); + return x.Result; } - return x.Result; } catch(Exception ex) { + httpTask.Error = ex; Console.WriteLine($"{httpTask.Url} {ex}"); - throw; } + return default(HttpResult); }); return httpTask; } diff --git a/Source/HtmlRenderer/Core/HtmlContainerInt.cs b/Source/HtmlRenderer/Core/HtmlContainerInt.cs index a0f4a1e0d..d3b73b8bd 100644 --- a/Source/HtmlRenderer/Core/HtmlContainerInt.cs +++ b/Source/HtmlRenderer/Core/HtmlContainerInt.cs @@ -874,12 +874,14 @@ internal void HandleLinkClicked(RControl parent, RPoint location, CssBox link) } } } + /* else { var nfo = new ProcessStartInfo(link.HrefLink); nfo.UseShellExecute = true; Process.Start(nfo); } + */ } } From 22afbd0dd5a3b053e3e5fd74a1dbf6da1e2f5f35 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 10 Jul 2018 13:07:56 +0900 Subject: [PATCH 9/9] Added CUSTOM.md --- CUSTOM.md | 11 +++++++++++ README.md | 3 +++ 2 files changed, 14 insertions(+) create mode 100644 CUSTOM.md diff --git a/CUSTOM.md b/CUSTOM.md new file mode 100644 index 000000000..778edfc6c --- /dev/null +++ b/CUSTOM.md @@ -0,0 +1,11 @@ +# Modified + +* Use .Net4.6 for Task +* Added a HttpSession manager + +# ToDo + +* Download task scheduler(max 4 concurrency ?) +* Cancel requests when jump to other page +* Fix OutOfMemoryException of GDI + diff --git a/README.md b/README.md index 5a21ca388..0ba6ad78d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ HTML Renderer [![Build status](https://ci.appveyor.com/api/projects/status/cm8xpf8ebt3hyi3e)](https://ci.appveyor.com/project/ArthurHub/html-renderer) ============= +## This repository is modified version. +* [CUSTOM](CUSTOM.md) + ## Help Wanted * Looking for a contributor(s) to take this project forward as I'm unable to continue supporting it. * Contribute directly to the repository and update nuget packages.