diff --git a/CefSharp.Core/CefSharp.Core.csproj b/CefSharp.Core/CefSharp.Core.csproj index 96f4b62f1a..34d1245d99 100644 --- a/CefSharp.Core/CefSharp.Core.csproj +++ b/CefSharp.Core/CefSharp.Core.csproj @@ -67,6 +67,7 @@ + diff --git a/CefSharp.Core/WebBrowserExtensionsEx.cs b/CefSharp.Core/WebBrowserExtensionsEx.cs new file mode 100644 index 0000000000..b6421dd573 --- /dev/null +++ b/CefSharp.Core/WebBrowserExtensionsEx.cs @@ -0,0 +1,51 @@ +// Copyright © 2021 The CefSharp Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +using CefSharp.Internals; +using System.Threading.Tasks; + +namespace CefSharp +{ + /// + /// Extended WebBrowserExtensions + /// + public static class WebBrowserExtensionsEx + { + /// + /// Retrieve the current . Contains information like + /// and + /// + /// The ChromiumWebBrowser instance this method extends. + /// + /// that when executed returns the current or null + /// + public static Task GetVisibleNavigationEntryAsync(this IWebBrowser browser) + { + var host = browser.GetBrowserHost(); + + if (host == null) + { + return Task.FromResult(null); + } + + if(Cef.CurrentlyOnThread(CefThreadIds.TID_UI)) + { + var entry = host.GetVisibleNavigationEntry(); + + return Task.FromResult(entry); + } + + var tcs = new TaskCompletionSource(); + + Cef.UIThreadTaskFactory.StartNew(delegate + { + var entry = host.GetVisibleNavigationEntry(); + + tcs.TrySetResultAsync(entry); + }); + + return tcs.Task; + } + } +} diff --git a/CefSharp.Test/CefSharp.Test.csproj b/CefSharp.Test/CefSharp.Test.csproj index ac16ef7be7..9352f053a4 100644 --- a/CefSharp.Test/CefSharp.Test.csproj +++ b/CefSharp.Test/CefSharp.Test.csproj @@ -160,6 +160,7 @@ + diff --git a/CefSharp.Test/Framework/RequestContextFacts.cs b/CefSharp.Test/Framework/RequestContextFacts.cs new file mode 100644 index 0000000000..4dbf5bba50 --- /dev/null +++ b/CefSharp.Test/Framework/RequestContextFacts.cs @@ -0,0 +1,33 @@ +// Copyright © 2021 The CefSharp Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +using Xunit; + +namespace CefSharp.Test.Framework +{ + //NOTE: All Test classes must be part of this collection as it manages the Cef Initialize/Shutdown lifecycle + [Collection(CefSharpFixtureCollection.Key)] + public class RequestContextFacts + { + [Fact] + public void IsSameAs() + { + var ctx1 = new RequestContext(); + var ctx2 = ctx1.UnWrap(); + + Assert.True(ctx1.IsSame(ctx2)); + } + + [Fact] + public void IsSharingWith() + { + var ctx1 = RequestContext.Configure() + .WithCachePath(@"c:\temp") + .Create(); + var ctx2 = new RequestContext(ctx1); + + Assert.True(ctx1.IsSharingWith(ctx2)); + } + } +} diff --git a/CefSharp.Test/OffScreen/OffScreenBrowserBasicFacts.cs b/CefSharp.Test/OffScreen/OffScreenBrowserBasicFacts.cs index 6754eb00b4..a544afcfd7 100644 --- a/CefSharp.Test/OffScreen/OffScreenBrowserBasicFacts.cs +++ b/CefSharp.Test/OffScreen/OffScreenBrowserBasicFacts.cs @@ -3,6 +3,7 @@ // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. using System.Collections.Generic; +using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -10,6 +11,7 @@ using CefSharp.Example.Handlers; using CefSharp.Internals; using CefSharp.OffScreen; +using CefSharp.Web; using Xunit; using Xunit.Abstractions; @@ -372,6 +374,43 @@ public async Task CanExecuteJavascriptInMainFrameAfterNavigatingToDifferentOrigi } } + [Theory] + [InlineData("http://httpbin.org/post")] + public async Task CanLoadRequestWithPostData(string url) + { + const string data = "Testing123"; + //To use LoadRequest we must first load a web page + using (var browser = new ChromiumWebBrowser(new HtmlString("Testing"))) + { + await browser.LoadPageAsync(); + + var request = new Request(); + request.Url = "http://httpbin.org/post"; + request.Method = "POST"; + var postData = new PostData(); + postData.AddElement(new PostDataElement + { + Bytes = Encoding.UTF8.GetBytes(data) + }); + + request.PostData = postData; + + await browser.LoadRequestAsync(request); + + var mainFrame = browser.GetMainFrame(); + Assert.Equal(url, mainFrame.Url); + + var navEntry = await browser.GetVisibleNavigationEntryAsync(); + + Assert.Equal((int)HttpStatusCode.OK, navEntry.HttpStatusCode); + Assert.True(navEntry.HasPostData); + + var source = await browser.GetTextAsync(); + + Assert.Contains(data, source); + } + } + [SkipIfRunOnAppVeyorFact] public async Task CanLoadHttpWebsiteUsingProxy() { diff --git a/CefSharp.Test/WebBrowserTestExtensions.cs b/CefSharp.Test/WebBrowserTestExtensions.cs index d1eb67e836..a226e9c0d1 100644 --- a/CefSharp.Test/WebBrowserTestExtensions.cs +++ b/CefSharp.Test/WebBrowserTestExtensions.cs @@ -37,6 +37,37 @@ public static Task LoadPageAsync(this IWebBrowser browser, string address = null return tcs.Task; } + public static Task LoadRequestAsync(this IWebBrowser browser, IRequest request) + { + if(request == null) + { + throw new ArgumentNullException("request"); + } + + //If using .Net 4.6 then use TaskCreationOptions.RunContinuationsAsynchronously + //and switch to tcs.TrySetResult below - no need for the custom extension method + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + EventHandler handler = null; + handler = (sender, args) => + { + //Wait for while page to finish loading not just the first frame + if (!args.IsLoading) + { + browser.LoadingStateChanged -= handler; + //This is required when using a standard TaskCompletionSource + //Extension method found in the CefSharp.Internals namespace + tcs.TrySetResult(true); + } + }; + + browser.LoadingStateChanged += handler; + + browser.GetMainFrame().LoadRequest(request); + + return tcs.Task; + } + public static Task WaitForQUnitTestExeuctionToComplete(this IWebBrowser browser) { //If using .Net 4.6 then use TaskCreationOptions.RunContinuationsAsynchronously