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