Merge branch 'master' into onovotny/add-strongname
This commit is contained in:
Коммит
212304df2c
|
@ -4,6 +4,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT;
|
||||
|
||||
|
@ -194,6 +195,14 @@ namespace Microsoft.Toolkit.Win32.UI.Controls
|
|||
/// <see cref="WebViewControlSettings.IsScriptNotifyAllowed" />
|
||||
bool IsScriptNotifyAllowed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a partition for this process.
|
||||
/// </summary>
|
||||
/// <value>The partition of this process.</value>
|
||||
/// <remarks>Value can be set prior to the component being initialized.</remarks>
|
||||
/// <see cref="WebViewControlProcessOptions.Partition"/>
|
||||
string Partition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="WebViewControlProcess"/> that the control is hosted in.
|
||||
/// </summary>
|
||||
|
@ -224,6 +233,12 @@ namespace Microsoft.Toolkit.Win32.UI.Controls
|
|||
/// <value>The version of EDGEHTML.DLL used by <see cref="IWebView" />.</value>
|
||||
Version Version { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds the script to be loaded before any others on the page.
|
||||
/// </summary>
|
||||
/// <param name="script">The script.</param>
|
||||
void AddPreLoadedScript(string script);
|
||||
|
||||
/// <summary>
|
||||
/// Closes this instance.
|
||||
/// </summary>
|
||||
|
@ -337,6 +352,23 @@ namespace Microsoft.Toolkit.Win32.UI.Controls
|
|||
/// navigation has completed.
|
||||
void Navigate(string source);
|
||||
|
||||
/// <summary>
|
||||
/// Navigates the web view with the URI with a HTTP request and HTTP headers.
|
||||
/// </summary>
|
||||
/// <param name="requestUri">The Uniform Resource Identifier (URI) to send the request.</param>
|
||||
/// <param name="httpMethod">The HTTP method of the request.</param>
|
||||
/// <param name="content">Optional content to send with the request.</param>
|
||||
/// <param name="headers">Optional headers to send with the request.</param>
|
||||
/// <remarks>
|
||||
/// This method only supports <see cref="HttpMethod.Get"/> and <see cref="HttpMethod.Post"/> for the <paramref name="httpMethod"/> parameter.
|
||||
/// </remarks>
|
||||
/// <seealso cref="Windows.Web.UI.Interop.WebViewControl.NavigateWithHttpRequestMessage"/>
|
||||
void Navigate(
|
||||
Uri requestUri,
|
||||
HttpMethod httpMethod,
|
||||
string content = null,
|
||||
IEnumerable<KeyValuePair<string, string>> headers = null);
|
||||
|
||||
/// <summary>
|
||||
/// Loads the specified HTML content relative to the location of the current executable.
|
||||
/// </summary>
|
||||
|
@ -345,6 +377,13 @@ namespace Microsoft.Toolkit.Win32.UI.Controls
|
|||
/// navigation has completed.
|
||||
void NavigateToLocal(string relativePath);
|
||||
|
||||
/// <summary>
|
||||
/// Loads local web content at the specified Uniform Resource Identifier (URI) using an <see cref="IUriToStreamResolver"/>.
|
||||
/// </summary>
|
||||
/// <param name="relativePath">A path identifying the local HTML content to load.</param>
|
||||
/// <param name="streamResolver">A <see cref="IUriToStreamResolver"/> instance that converts a Uniform Resource Identifier (URI) into a stream to load.</param>
|
||||
void NavigateToLocalStreamUri(Uri relativePath, IUriToStreamResolver streamResolver);
|
||||
|
||||
/// <summary>
|
||||
/// Loads the specified HTML content as a new document.
|
||||
/// </summary>
|
||||
|
@ -370,4 +409,4 @@ namespace Microsoft.Toolkit.Win32.UI.Controls
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Stop", Justification = "Method exposed in WinRT type")]
|
||||
void Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Foundation;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
||||
{
|
||||
/// <summary>
|
||||
/// An adapter converting <see cref="IUriToStreamResolver"/> to <see cref="Windows.Web.IUriToStreamResolver"/>.
|
||||
/// </summary>
|
||||
internal sealed class GenericUriToStreamResolver : Windows.Web.IUriToStreamResolver, IUriToStreamResolver
|
||||
{
|
||||
private readonly IUriToStreamResolver _streamResolver;
|
||||
|
||||
public GenericUriToStreamResolver(IUriToStreamResolver streamResolver)
|
||||
{
|
||||
_streamResolver = streamResolver ?? throw new ArgumentNullException(nameof(streamResolver));
|
||||
}
|
||||
|
||||
public Stream UriToStream(Uri uri)
|
||||
{
|
||||
return _streamResolver.UriToStream(uri);
|
||||
}
|
||||
|
||||
public IAsyncOperation<IInputStream> UriToStreamAsync(Uri uri)
|
||||
{
|
||||
var streamOp = UriToStream(uri);
|
||||
if (streamOp == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Task.FromResult(streamOp.AsInputStream()).AsAsyncOperation();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a method to translate a Uniform Resource I (URI) to a <see cref="Stream"/> for use by the <see cref="IWebView.NavigateToLocal(string)"/> method.
|
||||
/// </summary>
|
||||
/// <seealso cref="Windows.Web.IUriToStreamResolver"/>
|
||||
public interface IUriToStreamResolver
|
||||
{
|
||||
Stream UriToStream(Uri uri);
|
||||
}
|
||||
}
|
|
@ -1,63 +1,88 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32;
|
||||
using Windows.Foundation;
|
||||
using Windows.Storage.Streams;
|
||||
using Windows.Web;
|
||||
|
||||
namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
||||
{
|
||||
internal sealed class UriToLocalStreamResolver : IUriToStreamResolver
|
||||
[Obsolete("Use NavigateToLocalStreamUri(Uri, IUriToStreamResolver) instead")]
|
||||
internal class UriToLocalStreamResolver : IUriToStreamResolver
|
||||
{
|
||||
public IAsyncOperation<IInputStream> UriToStreamAsync(Uri uri)
|
||||
private readonly string _path;
|
||||
|
||||
public UriToLocalStreamResolver()
|
||||
#pragma warning disable SA1129 // Do not use default value type constructor
|
||||
: this(Path.GetDirectoryName(UnsafeNativeMethods.GetModuleFileName(new HandleRef())))
|
||||
#pragma warning restore SA1129 // Do not use default value type constructor
|
||||
{
|
||||
}
|
||||
|
||||
protected UriToLocalStreamResolver(string path)
|
||||
{
|
||||
_path = path;
|
||||
}
|
||||
|
||||
public Stream UriToStream(Uri uri)
|
||||
{
|
||||
var fullPath = ConvertToPath(uri);
|
||||
|
||||
// TODO: Make this proper async all the way through
|
||||
#pragma warning disable SCS0018 // Path traversal: injection possible in {1} argument passed to '{0}'
|
||||
return File.Open(fullPath, FileMode.Open, FileAccess.Read);
|
||||
#pragma warning restore SCS0018 // Path traversal: injection possible in {1} argument passed to '{0}'
|
||||
}
|
||||
|
||||
private string ConvertToPath(Uri uri)
|
||||
{
|
||||
if (uri == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(uri));
|
||||
}
|
||||
|
||||
var path = uri.AbsolutePath;
|
||||
return GetContentAsync(path).AsAsyncOperation();
|
||||
}
|
||||
// The incoming URI will be in the form of
|
||||
// ms-local-stream://microsoft.win32webviewhost_xxxxxxxx_yyyyyyyyyyyyyy/content.htm
|
||||
// We are only interested in the items after the application identity (x) and guid (y), e.g. "/content.htm"
|
||||
// Since we must not read content from web view host
|
||||
var path = UriHelper.RelativeUriToString(uri);
|
||||
|
||||
private bool IsRelative(string path)
|
||||
{
|
||||
return path != null && path[0] == '/';
|
||||
}
|
||||
|
||||
private static readonly Lazy<string> BasePath = new Lazy<string>(() =>
|
||||
#pragma warning disable SA1129 // Do not use default value type constructor
|
||||
Path.GetDirectoryName(UnsafeNativeMethods.GetModuleFileName(new HandleRef())));
|
||||
#pragma warning restore SA1129 // Do not use default value type constructor
|
||||
|
||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
private async Task<IInputStream> GetContentAsync(string path)
|
||||
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
{
|
||||
if (IsRelative(path))
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
// Clean up path
|
||||
while (path[0] == '/')
|
||||
{
|
||||
path = path.TrimStart('/');
|
||||
}
|
||||
|
||||
// Translate forward slash into backslash for use in file paths
|
||||
path = path.Replace(@"/", @"\");
|
||||
|
||||
var fullPath = Path.Combine(BasePath.Value, path);
|
||||
|
||||
// TODO: Make this proper async all the way through
|
||||
return File.Open(fullPath, FileMode.Open, FileAccess.Read).AsInputStream();
|
||||
throw new ArgumentException(DesignerUI.E_WEBVIEW_INVALID_URI, nameof(uri));
|
||||
}
|
||||
|
||||
throw new NotSupportedException();
|
||||
// Clean up path
|
||||
path = path.TrimStart(Path.AltDirectorySeparatorChar);
|
||||
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
// After stripping away the separator chars, we have nothing left
|
||||
// e.g. uri was "ms-local-stream://microsoft.win32webviewhost_xxxxxxxx_yyyyyyyyyyyyyy/"
|
||||
throw new ArgumentException(DesignerUI.E_WEBVIEW_INVALID_URI, nameof(uri));
|
||||
}
|
||||
|
||||
// This should never be the case, but guard just in case
|
||||
if (PathUtilities.IsAbsolute(path))
|
||||
{
|
||||
throw new ArgumentException(DesignerUI.E_WEBVIEW_INVALID_URI, nameof(uri));
|
||||
}
|
||||
|
||||
// Translate forward slash into backslash for use in file paths
|
||||
path = path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
||||
|
||||
var fullPath = Path.Combine(_path, path);
|
||||
|
||||
// At this point there should be no relative paths (e.g. ../../file.htm)
|
||||
// This check is the last guard against potential path/directory traversal attack
|
||||
if (fullPath.IndexOfAny(Path.GetInvalidPathChars()) >= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(uri));
|
||||
}
|
||||
|
||||
return fullPath;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
|||
/// <seealso cref="Windows.Web.UI.Interop.WebViewControlAcceleratorKeyPressedEventArgs"/>
|
||||
/// <summary>This class provides information for the <see cref="IWebView.AcceleratorKeyPressed"/> event.</summary>
|
||||
/// <seealso cref="System.EventArgs" />
|
||||
public class WebViewControlAcceleratorKeyPressedEventArgs : EventArgs
|
||||
public sealed class WebViewControlAcceleratorKeyPressedEventArgs : EventArgs
|
||||
{
|
||||
[SecurityCritical]
|
||||
private readonly Windows.Web.UI.Interop.WebViewControlAcceleratorKeyPressedEventArgs _args;
|
||||
|
|
|
@ -8,8 +8,9 @@ using System.Diagnostics;
|
|||
using System.IO;
|
||||
using System.Security;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Windows.Foundation.Metadata;
|
||||
using Windows.Web;
|
||||
using Windows.Web.Http;
|
||||
using Windows.Web.UI;
|
||||
using Windows.Web.UI.Interop;
|
||||
|
||||
|
@ -42,6 +43,8 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
|||
/// </remarks>
|
||||
internal sealed class WebViewControlHost : IDisposable
|
||||
{
|
||||
private const string LocalContentIdentifier = "LocalContent";
|
||||
|
||||
[SecurityCritical]
|
||||
private WebViewControl _webViewControl;
|
||||
|
||||
|
@ -80,8 +83,12 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
|||
|
||||
internal event EventHandler<WebViewControlNavigationStartingEventArgs> FrameNavigationStarting = (sender, args) => { };
|
||||
|
||||
internal event EventHandler<object> GotFocus = (sender, args) => { };
|
||||
|
||||
internal event EventHandler<WebViewControlLongRunningScriptDetectedEventArgs> LongRunningScriptDetected = (sender, args) => { };
|
||||
|
||||
internal event EventHandler<object> LostFocus = (sender, args) => { };
|
||||
|
||||
internal event EventHandler<WebViewControlMoveFocusRequestedEventArgs> MoveFocusRequested = (sender, args) => { };
|
||||
|
||||
internal event EventHandler<WebViewControlNavigationCompletedEventArgs> NavigationCompleted = (sender, args) => { };
|
||||
|
@ -282,8 +289,42 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
|||
set;
|
||||
}
|
||||
|
||||
internal void AddPreLoadedScript(string script)
|
||||
{
|
||||
if (ApiInformation.IsMethodPresent(
|
||||
"Windows.Web.UI.Interop.WebViewControl",
|
||||
"AddPreLoadedScript",
|
||||
1))
|
||||
{
|
||||
_webViewControl?.AddPreLoadedScript(script);
|
||||
}
|
||||
}
|
||||
|
||||
internal Uri BuildStream(string contentIdentifier, string relativePath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(contentIdentifier))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(contentIdentifier));
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(relativePath))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(relativePath));
|
||||
}
|
||||
|
||||
// If not passing a relative path, the method faults. No exception is thrown, the application just fails fast
|
||||
// Until that issue resolved, add our own error checking
|
||||
if (PathUtilities.IsAbsolute(relativePath))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(relativePath), DesignerUI.E_WEBVIEW_INVALID_URI);
|
||||
}
|
||||
|
||||
// The content identifier is used in conjunction with the application identity to create a guid. The
|
||||
// guid is appended to the win32webviewhost identity and a ms-local-stream URI is created.
|
||||
// Given a relative path of "/content.htm" the following is generated:
|
||||
// ms-local-stream://microsoft.win32webviewhost_xxxxxxxxxxxxx_yyyyyyyyyyyyyyyyyyyyyyyy//content.htm
|
||||
// If there is relative navigation items (e.g. "..\") they are resolved. URI will ALWAYS be relative to
|
||||
// the application container, e.g. "..\..\..\..\..\..\file" will resolve to "/file"
|
||||
return _webViewControl?.BuildLocalStreamUri(contentIdentifier, relativePath);
|
||||
}
|
||||
|
||||
|
@ -488,16 +529,109 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
|||
Navigate(UriHelper.StringToUri(source));
|
||||
}
|
||||
|
||||
[Obsolete("Use NavigateToLocalStreamUri(Uri, IUriToStreamResolver) instead")]
|
||||
internal void NavigateToLocal(string relativePath)
|
||||
{
|
||||
var uri = BuildStream("LocalContent", relativePath);
|
||||
var resolver = new UriToLocalStreamResolver();
|
||||
NavigateToLocalStreamUri(uri, resolver);
|
||||
var relativeUri = UriHelper.StringToRelativeUri(relativePath);
|
||||
NavigateToLocalStreamUri(relativeUri, new UriToLocalStreamResolver());
|
||||
}
|
||||
|
||||
internal void NavigateToLocalStreamUri(Uri source, IUriToStreamResolver streamResolver)
|
||||
internal void NavigateToLocalStreamUri(Uri relativePath, IUriToStreamResolver streamResolver)
|
||||
{
|
||||
_webViewControl?.NavigateToLocalStreamUri(source, streamResolver);
|
||||
if (relativePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(relativePath));
|
||||
}
|
||||
|
||||
if (relativePath.IsAbsoluteUri)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(relativePath), DesignerUI.E_WEBVIEW_INVALID_URI);
|
||||
}
|
||||
|
||||
if (streamResolver == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(streamResolver));
|
||||
}
|
||||
|
||||
Windows.Web.IUriToStreamResolver AsWindowsRuntimeUriToStreamResolver(IUriToStreamResolver streamResolverInterop)
|
||||
{
|
||||
// Check to see if the stream resolver is actually a wrapper of a WinRT stream resolver
|
||||
if (streamResolverInterop is Windows.Web.IUriToStreamResolver streamResolverAdapter)
|
||||
{
|
||||
return streamResolverAdapter;
|
||||
}
|
||||
|
||||
if (streamResolverInterop is GenericUriToStreamResolver genericAdapter)
|
||||
{
|
||||
return genericAdapter;
|
||||
}
|
||||
|
||||
// We have an unwrapped stream resolver
|
||||
return new GenericUriToStreamResolver(streamResolver);
|
||||
}
|
||||
|
||||
var uri = BuildStream(LocalContentIdentifier, UriHelper.UriToString(relativePath));
|
||||
_webViewControl?.NavigateToLocalStreamUri(uri, AsWindowsRuntimeUriToStreamResolver(streamResolver));
|
||||
}
|
||||
|
||||
internal void Navigate(
|
||||
Uri requestUri,
|
||||
System.Net.Http.HttpMethod method,
|
||||
string content = null,
|
||||
IEnumerable<KeyValuePair<string, string>> headers = null)
|
||||
{
|
||||
if (requestUri == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(requestUri));
|
||||
}
|
||||
|
||||
if (method == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(method));
|
||||
}
|
||||
|
||||
// Convert a System.Net.Http.HttpMethod to Windows.Web.Http.HttpMethod
|
||||
HttpMethod ToHttpMethod(System.Net.Http.HttpMethod httpMethod)
|
||||
{
|
||||
if (System.Net.Http.HttpMethod.Get.Equals(httpMethod))
|
||||
{
|
||||
return HttpMethod.Get;
|
||||
}
|
||||
|
||||
if (System.Net.Http.HttpMethod.Post.Equals(httpMethod))
|
||||
{
|
||||
return HttpMethod.Post;
|
||||
}
|
||||
|
||||
// For compatabilty with WebView.NavigateWithHttpRequestMessage, this only supports POST and GET
|
||||
throw new ArgumentOutOfRangeException(nameof(httpMethod));
|
||||
}
|
||||
|
||||
var requestMessage = new HttpRequestMessage
|
||||
{
|
||||
RequestUri = requestUri,
|
||||
Method = ToHttpMethod(method)
|
||||
};
|
||||
|
||||
if (content != null)
|
||||
{
|
||||
requestMessage.Content = new HttpStringContent(content);
|
||||
}
|
||||
|
||||
if (headers != null)
|
||||
{
|
||||
foreach (var header in headers)
|
||||
{
|
||||
requestMessage.Headers.Add(header);
|
||||
}
|
||||
}
|
||||
|
||||
NavigateWithHttpRequestMessage(requestMessage);
|
||||
}
|
||||
|
||||
internal void NavigateWithHttpRequestMessage(HttpRequestMessage requestMessage)
|
||||
{
|
||||
_webViewControl?.NavigateWithHttpRequestMessage(requestMessage);
|
||||
}
|
||||
|
||||
/// <exception cref="ArgumentNullException"><paramref name="text"/> is <see langword="null"/></exception>
|
||||
|
@ -678,8 +812,19 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
|||
}
|
||||
}
|
||||
|
||||
private void OnGotFocus(object args)
|
||||
{
|
||||
var handler = GotFocus;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, args);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnFrameNavigationStarting(IWebViewControl sender, Windows.Web.UI.WebViewControlNavigationStartingEventArgs args) => OnFrameNavigationStarting(args);
|
||||
|
||||
private void OnGotFocus(IWebViewControl sender, object args) => OnGotFocus(args);
|
||||
|
||||
private void OnLongRunningScriptDetected(WebViewControlLongRunningScriptDetectedEventArgs args)
|
||||
{
|
||||
var handler = LongRunningScriptDetected;
|
||||
|
@ -691,6 +836,17 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
|||
|
||||
private void OnLongRunningScriptDetected(IWebViewControl sender, Windows.Web.UI.WebViewControlLongRunningScriptDetectedEventArgs args) => OnLongRunningScriptDetected(args);
|
||||
|
||||
private void OnLostFocus(object args)
|
||||
{
|
||||
var handler = LostFocus;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, args);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLostFocus(IWebViewControl sender, object args) => OnLostFocus(args);
|
||||
|
||||
private void OnMoveFocusRequested(WebViewControlMoveFocusRequestedEventArgs args)
|
||||
{
|
||||
var handler = MoveFocusRequested;
|
||||
|
@ -910,6 +1066,16 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
|||
_webViewControl.UnsafeContentWarningDisplaying += OnUnsafeContentWarningDisplaying;
|
||||
_webViewControl.UnsupportedUriSchemeIdentified += OnUnsupportedUriSchemeIdentified;
|
||||
_webViewControl.UnviewableContentIdentified += OnUnviewableContentIdentified;
|
||||
|
||||
if (ApiInformation.IsEventPresent("Windows.Web.UI.Interop", "GotFocus"))
|
||||
{
|
||||
_webViewControl.GotFocus += OnGotFocus;
|
||||
}
|
||||
|
||||
if (ApiInformation.IsEventPresent("Windows.Web.UI.Interop", "LostFocus"))
|
||||
{
|
||||
_webViewControl.LostFocus += OnLostFocus;
|
||||
}
|
||||
}
|
||||
|
||||
[SecurityCritical]
|
||||
|
@ -948,6 +1114,16 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
|||
_webViewControl.UnsafeContentWarningDisplaying -= OnUnsafeContentWarningDisplaying;
|
||||
_webViewControl.UnsupportedUriSchemeIdentified -= OnUnsupportedUriSchemeIdentified;
|
||||
_webViewControl.UnviewableContentIdentified -= OnUnviewableContentIdentified;
|
||||
|
||||
if (ApiInformation.IsEventPresent("Windows.Web.UI.Interop", "GotFocus"))
|
||||
{
|
||||
_webViewControl.GotFocus -= OnGotFocus;
|
||||
}
|
||||
|
||||
if (ApiInformation.IsEventPresent("Windows.Web.UI.Interop", "LostFocus"))
|
||||
{
|
||||
_webViewControl.LostFocus -= OnLostFocus;
|
||||
}
|
||||
}
|
||||
|
||||
private void UnsubscribeProcessExited()
|
||||
|
|
|
@ -7,6 +7,7 @@ using System.Security;
|
|||
using System.Threading.Tasks;
|
||||
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Metadata;
|
||||
using Windows.Web.UI.Interop;
|
||||
|
||||
namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
||||
|
@ -14,7 +15,7 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
|||
/// <summary>
|
||||
/// A proxy for <see cref="Windows.Web.UI.Interop.WebViewControlProcess"/>.
|
||||
/// </summary>
|
||||
public class WebViewControlProcess
|
||||
public sealed class WebViewControlProcess
|
||||
{
|
||||
[SecurityCritical]
|
||||
private readonly Windows.Web.UI.Interop.WebViewControlProcess _process;
|
||||
|
@ -60,12 +61,50 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
|||
/// <value><c>true</c> if this instance can access the private network; otherwise, <c>false</c>.</value>
|
||||
public bool IsPrivateNetworkClientServerCapabilityEnabled => _process.IsPrivateNetworkClientServerCapabilityEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating the partition of the web view.
|
||||
/// </summary>
|
||||
/// <value>The partition.</value>
|
||||
public string Partition
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ApiInformation.IsPropertyPresent(
|
||||
"Windows.Web.UI.Interop.WebViewControlProcessOptions",
|
||||
"Partition"))
|
||||
{
|
||||
return _process.Partition;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the process identifier (PID) of the underlying WWAHost.
|
||||
/// </summary>
|
||||
/// <value>The process identifier (PID).</value>
|
||||
public uint ProcessId => _process.ProcessId;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user agent of the underlying web view
|
||||
/// </summary>
|
||||
/// <value>The user agent.</value>
|
||||
public string UserAgent
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ApiInformation.IsPropertyPresent(
|
||||
"Windows.Web.UI.Interop.WebViewControlProcessOptions",
|
||||
"UserAgent"))
|
||||
{
|
||||
return _process.UserAgent;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an implicit conversion from <see cref="Windows.Web.UI.Interop.WebViewControlProcess"/> to <see cref="WebViewControlProcess"/>.
|
||||
/// </summary>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using Windows.Foundation.Metadata;
|
||||
|
||||
namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
||||
{
|
||||
|
@ -13,7 +14,7 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
|||
/// Copy from <see cref="Windows.Web.UI.Interop.WebViewControlProcessOptions"/> to avoid requirement to link Windows.winmd.
|
||||
/// </remarks>
|
||||
/// <seealso cref="Windows.Web.UI.Interop.WebViewControlProcessOptions"/>
|
||||
public class WebViewControlProcessOptions
|
||||
public sealed class WebViewControlProcessOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the enterprise identifier for apps that are WIP-enabled.
|
||||
|
@ -21,37 +22,83 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
|||
/// <value>The enterprise identifier.</value>
|
||||
public string EnterpriseId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the partition for the web view.
|
||||
/// </summary>
|
||||
/// <value>The partition.</value>
|
||||
public string Partition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the private network client server capability.
|
||||
/// </summary>
|
||||
/// <value>The private network client server capability.</value>
|
||||
public WebViewControlProcessCapabilityState PrivateNetworkClientServerCapability { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the user agent.
|
||||
/// </summary>
|
||||
/// <value>The user agent.</value>
|
||||
public string UserAgent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebViewControlProcessOptions"/> class.
|
||||
/// </summary>
|
||||
public WebViewControlProcessOptions()
|
||||
{
|
||||
EnterpriseId = string.Empty;
|
||||
Partition = string.Empty;
|
||||
UserAgent = string.Empty;
|
||||
PrivateNetworkClientServerCapability = WebViewControlProcessCapabilityState.Default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an implicit conversion from <see cref="Windows.Web.UI.Interop.WebViewControlProcessOptions"/> to <see cref="WebViewControlProcessOptions"/>.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator WebViewControlProcessOptions(Windows.Web.UI.Interop.WebViewControlProcessOptions options) => ToWinRtWebViewControlProcessOptions(options);
|
||||
|
||||
public static Windows.Web.UI.Interop.WebViewControlProcessOptions ToWinRtWebViewControlProcessOptions(WebViewControlProcessOptions options)
|
||||
{
|
||||
var retval = new Windows.Web.UI.Interop.WebViewControlProcessOptions();
|
||||
|
||||
if (!string.IsNullOrEmpty(options?.EnterpriseId) && !StringComparer.InvariantCulture.Equals(retval.EnterpriseId, options?.EnterpriseId))
|
||||
{
|
||||
retval.EnterpriseId = options.EnterpriseId;
|
||||
}
|
||||
|
||||
if (ApiInformation.IsPropertyPresent(
|
||||
"Windows.Web.UI.Interop.WebViewControlProcessOptions",
|
||||
"Partition"))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(options?.Partition))
|
||||
{
|
||||
retval.Partition = options.Partition;
|
||||
}
|
||||
}
|
||||
|
||||
retval.PrivateNetworkClientServerCapability = (Windows.Web.UI.Interop.WebViewControlProcessCapabilityState)options?.PrivateNetworkClientServerCapability;
|
||||
|
||||
if (ApiInformation.IsPropertyPresent(
|
||||
"Windows.Web.UI.Interop.WebViewControlProcessOptions",
|
||||
"UserAgent"))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(options?.UserAgent))
|
||||
{
|
||||
retval.UserAgent = options.UserAgent;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts this instance to a <seealso cref="Windows.Web.UI.Interop.WebViewControlProcessOptions"/> instance.
|
||||
/// </summary>
|
||||
/// <returns>A <seealso cref="Windows.Web.UI.Interop.WebViewControlProcessOptions"/> instance.</returns>
|
||||
internal Windows.Web.UI.Interop.WebViewControlProcessOptions ToWinRtWebViewControlProcessOptions()
|
||||
{
|
||||
var retval = new Windows.Web.UI.Interop.WebViewControlProcessOptions();
|
||||
|
||||
if (!string.IsNullOrEmpty(EnterpriseId) && !StringComparer.InvariantCulture.Equals(retval.EnterpriseId, EnterpriseId))
|
||||
{
|
||||
retval.EnterpriseId = EnterpriseId;
|
||||
}
|
||||
|
||||
retval.PrivateNetworkClientServerCapability = (Windows.Web.UI.Interop.WebViewControlProcessCapabilityState)PrivateNetworkClientServerCapability;
|
||||
|
||||
return retval;
|
||||
return ToWinRtWebViewControlProcessOptions(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT
|
|||
public const bool IsJavaScriptEnabled = true;
|
||||
public const bool IsPrivateNetworkEnabled = false;
|
||||
public const bool IsScriptNotifyEnabled = false;
|
||||
public const string Partition = "";
|
||||
public static readonly Uri AboutBlankUri = new Uri(AboutBlank);
|
||||
}
|
||||
}
|
|
@ -13,9 +13,18 @@
|
|||
|
||||
<!-- Need Metadata contract 6.0 or later -->
|
||||
<!-- First introduced in 17110: Insider Preview (Fast) -->
|
||||
<TargetPlatformMinVersion>10.0.17110.0</TargetPlatformMinVersion>
|
||||
<!-- Most people will have RTM 17134: Insider Preview (Fast), Spring Creators (RS4) -->
|
||||
<TargetPlatformVersion>10.0.17134.0</TargetPlatformVersion>
|
||||
<!-- Most people will have RTM 17134: April 2018 Update -->
|
||||
<TargetPlatformMinVersion>10.0.17134.0</TargetPlatformMinVersion>
|
||||
<!--
|
||||
When changing this value, ensure the SDK is installed with the build process.
|
||||
Need to check several files:
|
||||
- /.vsts-ci.yml
|
||||
- /.vsts-pr.yml
|
||||
|
||||
This also needs to be installed on your local machine. Can do this with PowerShell:
|
||||
./build/Install-WindowsSDKISO.ps1 17704
|
||||
-->
|
||||
<TargetPlatformVersion>10.0.17704.0</TargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
|
@ -32,6 +41,7 @@
|
|||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xaml" />
|
||||
<Reference Include="WindowsBase" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.0.0" />
|
||||
<PackageReference Include="System.Runtime.WindowsRuntime" PrivateAssets="All">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.Toolkit.Win32.UI.Controls
|
||||
{
|
||||
// Contains path parsing utilities
|
||||
internal static class PathUtilities
|
||||
{
|
||||
// true if the character is the platform directory separator character or the alternate directory separator
|
||||
public static bool IsDirectorySeparator(char c) => c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar;
|
||||
|
||||
public static bool IsAbsolute(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// "C:\"
|
||||
if (IsDriveRootedAbsolutePath(path))
|
||||
{
|
||||
// Including invalid paths (e.g. "*:\")
|
||||
return true;
|
||||
}
|
||||
|
||||
// "\\machine\share"
|
||||
// Including invalid/incomplete UNC paths (e.g. "\\foo")
|
||||
return path.Length >= 2 &&
|
||||
IsDirectorySeparator(path[0]) &&
|
||||
IsDirectorySeparator(path[1]);
|
||||
}
|
||||
|
||||
// true if given path is absolute and starts with a drive specification (e.g. "C:\"); otherwise, false.
|
||||
private static bool IsDriveRootedAbsolutePath(string path)
|
||||
{
|
||||
return path.Length >= 3 && path[1] == Path.VolumeSeparatorChar && IsDirectorySeparator(path[2]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -36,6 +36,20 @@ namespace Microsoft.Toolkit.Win32.UI.Controls
|
|||
MAX_URL_LENGTH).ToString();
|
||||
}
|
||||
|
||||
internal static string RelativeUriToString(Uri uri)
|
||||
{
|
||||
if (uri == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(uri));
|
||||
}
|
||||
|
||||
return new StringBuilder(
|
||||
uri.GetComponents(
|
||||
UriComponents.PathAndQuery,
|
||||
UriFormat.SafeUnescaped),
|
||||
MAX_URL_LENGTH).ToString();
|
||||
}
|
||||
|
||||
internal static Uri StringToUri(string source)
|
||||
{
|
||||
if (string.IsNullOrEmpty(source))
|
||||
|
@ -51,5 +65,21 @@ namespace Microsoft.Toolkit.Win32.UI.Controls
|
|||
// Unrecognized URI
|
||||
throw new ArgumentException(DesignerUI.E_WEBVIEW_INVALID_URI);
|
||||
}
|
||||
|
||||
internal static Uri StringToRelativeUri(string source)
|
||||
{
|
||||
if (string.IsNullOrEmpty(source))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
}
|
||||
|
||||
if (Uri.TryCreate(source, UriKind.Relative, out Uri result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// Unrecognized URI
|
||||
throw new ArgumentException(DesignerUI.E_WEBVIEW_INVALID_URI);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ using System.ComponentModel;
|
|||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Threading;
|
||||
|
@ -90,6 +91,12 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WPF
|
|||
typeof(WebView),
|
||||
new PropertyMetadata(WebViewDefaults.AboutBlankUri, PropertyChangedCallback));
|
||||
|
||||
private static readonly DependencyProperty PartitionProperty = DependencyProperty.Register(
|
||||
nameof(Partition),
|
||||
typeof(string),
|
||||
typeof(WebView),
|
||||
new PropertyMetadata(WebViewDefaults.Partition, PropertyChangedCallback));
|
||||
|
||||
private WebViewControlProcess _process;
|
||||
|
||||
private volatile WebViewControlHost _webViewControl;
|
||||
|
@ -424,6 +431,15 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WPF
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[StringResourceCategory(Constants.CategoryBehavior)]
|
||||
[DefaultValue(WebViewDefaults.Partition)]
|
||||
public string Partition
|
||||
{
|
||||
get => (string)GetValue(PartitionProperty);
|
||||
set => SetValue(PartitionProperty, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Browsable(false)]
|
||||
public WebViewControlProcess Process
|
||||
|
@ -475,6 +491,14 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WPF
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IWebView.AddPreLoadedScript" />
|
||||
public void AddPreLoadedScript(string script)
|
||||
{
|
||||
VerifyAccess();
|
||||
Verify.IsNotNull(_webViewControl);
|
||||
_webViewControl?.AddPreLoadedScript(script);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IWebView.Close" />
|
||||
public override void Close()
|
||||
{
|
||||
|
@ -583,6 +607,26 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WPF
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Navigate(
|
||||
Uri requestUri,
|
||||
HttpMethod httpMethod,
|
||||
string content = null,
|
||||
IEnumerable<KeyValuePair<string, string>> headers = null)
|
||||
{
|
||||
VerifyAccess();
|
||||
|
||||
do
|
||||
{
|
||||
Dispatcher.CurrentDispatcher.DoEvents();
|
||||
}
|
||||
while (!_initializationComplete.WaitOne(InitializationBlockingTime));
|
||||
|
||||
Verify.IsNotNull(_webViewControl);
|
||||
_webViewControl.Navigate(requestUri, httpMethod, content, headers);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Obsolete("Use NavigateToLocalStreamUri(Uri, IUriToStreamResolver) instead")]
|
||||
public void NavigateToLocal(string relativePath)
|
||||
{
|
||||
VerifyAccess();
|
||||
|
@ -597,6 +641,21 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WPF
|
|||
_webViewControl.NavigateToLocal(relativePath);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void NavigateToLocalStreamUri(Uri relativePath, IUriToStreamResolver streamResolver)
|
||||
{
|
||||
VerifyAccess();
|
||||
|
||||
do
|
||||
{
|
||||
Dispatcher.CurrentDispatcher.DoEvents();
|
||||
}
|
||||
while (!_initializationComplete.WaitOne(InitializationBlockingTime));
|
||||
|
||||
Verify.IsNotNull(_webViewControl);
|
||||
_webViewControl.NavigateToLocalStreamUri(relativePath, streamResolver);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void NavigateToString(string text)
|
||||
{
|
||||
|
@ -645,13 +704,17 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WPF
|
|||
var enterpriseId = !Dispatcher.CheckAccess()
|
||||
? Dispatcher.Invoke(() => EnterpriseId)
|
||||
: EnterpriseId;
|
||||
var partition = !Dispatcher.CheckAccess()
|
||||
? Dispatcher.Invoke(() => Partition)
|
||||
: Partition;
|
||||
|
||||
_process = new WebViewControlProcess(new WebViewControlProcessOptions
|
||||
{
|
||||
PrivateNetworkClientServerCapability = privateNetworkEnabled
|
||||
? WebViewControlProcessCapabilityState.Enabled
|
||||
: WebViewControlProcessCapabilityState.Disabled,
|
||||
EnterpriseId = enterpriseId
|
||||
EnterpriseId = enterpriseId,
|
||||
Partition = partition
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -670,7 +733,14 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WPF
|
|||
|
||||
Verify.IsNotNull(_webViewControl);
|
||||
|
||||
UpdateSize(RenderSize);
|
||||
if (!Dispatcher.CheckAccess())
|
||||
{
|
||||
Dispatcher.Invoke(() => UpdateSize(RenderSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateSize(RenderSize);
|
||||
}
|
||||
|
||||
DestroyWindowCore(ChildWindow);
|
||||
|
||||
|
@ -825,6 +895,14 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WPF
|
|||
throw new InvalidOperationException(DesignerUI.E_CANNOT_CHANGE_AFTER_INIT);
|
||||
}
|
||||
}
|
||||
else if (dependencyPropertyChangedEventArgs.Property.Name == nameof(Partition))
|
||||
{
|
||||
Verify.IsFalse(wv.WebViewControlInitialized);
|
||||
if (wv.WebViewControlInitialized)
|
||||
{
|
||||
throw new InvalidOperationException(DesignerUI.E_CANNOT_CHANGE_AFTER_INIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -900,6 +978,11 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WPF
|
|||
}
|
||||
}
|
||||
|
||||
private void OnGotFocus(object sender, object args)
|
||||
{
|
||||
OnGotFocus(new RoutedEventArgs(GotFocusEvent));
|
||||
}
|
||||
|
||||
private void OnLongRunningScriptDetected(object sender, WebViewControlLongRunningScriptDetectedEventArgs args)
|
||||
{
|
||||
var handler = LongRunningScriptDetected;
|
||||
|
@ -909,6 +992,11 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WPF
|
|||
}
|
||||
}
|
||||
|
||||
private void OnLostFocus(object sender, object args)
|
||||
{
|
||||
OnLostFocus(new RoutedEventArgs(GotFocusEvent));
|
||||
}
|
||||
|
||||
private void OnMoveFocusRequested(object sender, WebViewControlMoveFocusRequestedEventArgs args)
|
||||
{
|
||||
var handler = MoveFocusRequested;
|
||||
|
@ -1012,7 +1100,9 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WPF
|
|||
_webViewControl.FrameDOMContentLoaded += OnFrameDOMContentLoaded;
|
||||
_webViewControl.FrameNavigationCompleted += OnFrameNavigationCompleted;
|
||||
_webViewControl.FrameNavigationStarting += OnFrameNavigationStarting;
|
||||
_webViewControl.GotFocus += OnGotFocus;
|
||||
_webViewControl.LongRunningScriptDetected += OnLongRunningScriptDetected;
|
||||
_webViewControl.LostFocus += OnLostFocus;
|
||||
_webViewControl.MoveFocusRequested += OnMoveFocusRequested;
|
||||
_webViewControl.NavigationCompleted += OnNavigationCompleted;
|
||||
_webViewControl.NavigationStarting += OnNavigationStarting;
|
||||
|
@ -1040,7 +1130,9 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WPF
|
|||
_webViewControl.FrameDOMContentLoaded -= OnFrameDOMContentLoaded;
|
||||
_webViewControl.FrameNavigationCompleted -= OnFrameNavigationCompleted;
|
||||
_webViewControl.FrameNavigationStarting -= OnFrameNavigationStarting;
|
||||
_webViewControl.GotFocus -= OnGotFocus;
|
||||
_webViewControl.LongRunningScriptDetected -= OnLongRunningScriptDetected;
|
||||
_webViewControl.LostFocus -= OnLostFocus;
|
||||
_webViewControl.MoveFocusRequested -= OnMoveFocusRequested;
|
||||
_webViewControl.NavigationCompleted -= OnNavigationCompleted;
|
||||
_webViewControl.NavigationStarting -= OnNavigationStarting;
|
||||
|
|
|
@ -239,6 +239,11 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms
|
|||
}
|
||||
}
|
||||
|
||||
private void OnGotFocus(object sender, object args)
|
||||
{
|
||||
OnGotFocus(EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void OnLongRunningScriptDetected(object sender, WebViewControlLongRunningScriptDetectedEventArgs args)
|
||||
{
|
||||
var handler = LongRunningScriptDetected;
|
||||
|
@ -248,6 +253,11 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms
|
|||
}
|
||||
}
|
||||
|
||||
private void OnLostFocus(object sender, object args)
|
||||
{
|
||||
OnLostFocus(EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void OnMoveFocusRequested(object sender, WebViewControlMoveFocusRequestedEventArgs args)
|
||||
{
|
||||
var handler = MoveFocusRequested;
|
||||
|
|
|
@ -124,7 +124,8 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms
|
|||
PrivateNetworkClientServerCapability = _delayedPrivateNetworkEnabled
|
||||
? WebViewControlProcessCapabilityState.Enabled
|
||||
: WebViewControlProcessCapabilityState.Disabled,
|
||||
EnterpriseId = _delayedEnterpriseId
|
||||
EnterpriseId = _delayedEnterpriseId,
|
||||
Partition = _delayedPartition
|
||||
});
|
||||
_webViewControl = Process.CreateWebViewControlHost(Handle, ClientRectangle);
|
||||
SubscribeEvents();
|
||||
|
@ -164,7 +165,9 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms
|
|||
_webViewControl.FrameDOMContentLoaded += OnFrameDOMContentLoaded;
|
||||
_webViewControl.FrameNavigationCompleted += OnFrameNavigationCompleted;
|
||||
_webViewControl.FrameNavigationStarting += OnFrameNavigationStarting;
|
||||
_webViewControl.GotFocus += OnGotFocus;
|
||||
_webViewControl.LongRunningScriptDetected += OnLongRunningScriptDetected;
|
||||
_webViewControl.LostFocus += OnLostFocus;
|
||||
_webViewControl.MoveFocusRequested += OnMoveFocusRequested;
|
||||
_webViewControl.NavigationCompleted += OnNavigationCompleted;
|
||||
_webViewControl.NavigationStarting += OnNavigationStarting;
|
||||
|
@ -191,7 +194,9 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms
|
|||
_webViewControl.FrameDOMContentLoaded -= OnFrameDOMContentLoaded;
|
||||
_webViewControl.FrameNavigationCompleted -= OnFrameNavigationCompleted;
|
||||
_webViewControl.FrameNavigationStarting -= OnFrameNavigationStarting;
|
||||
_webViewControl.GotFocus -= OnGotFocus;
|
||||
_webViewControl.LongRunningScriptDetected -= OnLongRunningScriptDetected;
|
||||
_webViewControl.LostFocus -= OnLostFocus;
|
||||
_webViewControl.MoveFocusRequested -= OnMoveFocusRequested;
|
||||
_webViewControl.NavigationCompleted -= OnNavigationCompleted;
|
||||
_webViewControl.NavigationStarting -= OnNavigationStarting;
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Net.Http;
|
||||
using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT;
|
||||
|
||||
namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms
|
||||
{
|
||||
|
@ -95,5 +98,34 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Navigate(Uri source) => _webViewControl?.Navigate(source);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Navigate(string source)
|
||||
{
|
||||
Verify.IsFalse(IsDisposed);
|
||||
Verify.IsNotNull(_webViewControl);
|
||||
_webViewControl?.Navigate(source);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Obsolete("Use NavigateToLocalStreamUri(Uri, IUriToStreamResolver) instead")]
|
||||
public void NavigateToLocal(string relativePath) => _webViewControl?.NavigateToLocal(relativePath);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void NavigateToString(string text) => _webViewControl?.NavigateToString(text);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void NavigateToLocalStreamUri(Uri relativePath, IUriToStreamResolver streamResolver) => _webViewControl?.NavigateToLocalStreamUri(relativePath, streamResolver);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Navigate(
|
||||
Uri requestUri,
|
||||
HttpMethod httpMethod,
|
||||
string content = null,
|
||||
IEnumerable<KeyValuePair<string, string>> headers = null) =>
|
||||
_webViewControl.Navigate(requestUri, httpMethod, content, headers);
|
||||
}
|
||||
}
|
|
@ -41,6 +41,7 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms
|
|||
private bool _delayedIsIndexDbEnabled = WebViewDefaults.IsIndexedDBEnabled;
|
||||
private bool _delayedIsJavaScriptEnabled = WebViewDefaults.IsJavaScriptEnabled;
|
||||
private bool _delayedIsScriptNotifyAllowed = WebViewDefaults.IsScriptNotifyEnabled;
|
||||
private string _delayedPartition = WebViewDefaults.Partition;
|
||||
private bool _delayedPrivateNetworkEnabled = WebViewDefaults.IsPrivateNetworkEnabled;
|
||||
private Uri _delayedSource;
|
||||
private WebViewControlHost _webViewControl;
|
||||
|
@ -55,6 +56,8 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms
|
|||
Layout += OnWebViewLayout;
|
||||
}
|
||||
|
||||
internal WebViewControlHost Host => _webViewControl;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether <see cref="WebView"/> is supported in this environment.
|
||||
/// </summary>
|
||||
|
@ -291,6 +294,37 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[StringResourceCategory(Constants.CategoryBehavior)]
|
||||
[DefaultValue(WebViewDefaults.Partition)]
|
||||
public string Partition
|
||||
{
|
||||
get
|
||||
{
|
||||
Verify.IsFalse(IsDisposed);
|
||||
Verify.Implies(Initializing, !Initialized);
|
||||
Verify.Implies(Initialized, WebViewControlInitialized);
|
||||
return WebViewControlInitialized
|
||||
? _webViewControl.Process.Partition
|
||||
: _delayedPartition;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
Verify.IsFalse(IsDisposed);
|
||||
_delayedPartition = value;
|
||||
if (!DesignMode)
|
||||
{
|
||||
EnsureInitialized();
|
||||
if (WebViewControlInitialized
|
||||
&& !string.Equals(_delayedPartition, _webViewControl.Process.Partition, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new InvalidOperationException(DesignerUI.E_CANNOT_CHANGE_AFTER_INIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="WebViewControlProcess" /> object that the control is hosted in.
|
||||
/// </summary>
|
||||
|
@ -369,6 +403,15 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms
|
|||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public Version Version => _webViewControl?.Version;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void AddPreLoadedScript(string script)
|
||||
{
|
||||
Verify.IsFalse(IsDisposed);
|
||||
Verify.Implies(Initializing, !Initialized);
|
||||
Verify.Implies(Initialized, WebViewControlInitialized);
|
||||
_webViewControl?.AddPreLoadedScript(script);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes this control.
|
||||
/// </summary>
|
||||
|
@ -420,23 +463,6 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms
|
|||
/// <inheritdoc />
|
||||
public void MoveFocus(WebViewControlMoveFocusReason reason) => _webViewControl?.MoveFocus(reason);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Navigate(Uri source) => _webViewControl?.Navigate(source);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Navigate(string source)
|
||||
{
|
||||
Verify.IsFalse(IsDisposed);
|
||||
Verify.IsNotNull(_webViewControl);
|
||||
_webViewControl?.Navigate(source);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void NavigateToLocal(string relativePath) => _webViewControl?.NavigateToLocal(relativePath);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void NavigateToString(string text) => _webViewControl?.NavigateToString(text);
|
||||
|
||||
/// <summary>
|
||||
/// Releases the unmanaged resources used by the <see cref="T:System.Windows.Forms.Control" /> and its child controls and optionally releases the managed resources.
|
||||
/// </summary>
|
||||
|
|
|
@ -19,6 +19,9 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared
|
|||
|
||||
// Local navigation: when using a null value for Source the uri is about:blank
|
||||
public static readonly Uri AboutBlank = new Uri("about:blank");
|
||||
|
||||
// A simple HTTP Request & Response Service
|
||||
public static readonly Uri HttpBin = new Uri("http://httpbin.org", UriKind.Absolute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Should;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.NavigateToLocalStreamUri
|
||||
{
|
||||
public abstract class BuildStreamContextSpecification : HostFormWebViewContextSpecification
|
||||
{
|
||||
public Uri Actual { get; set; }
|
||||
public Uri Expected { get; set; }
|
||||
public string RelativePath { get; set; }
|
||||
|
||||
protected override void When()
|
||||
{
|
||||
Actual = WebView.Host.BuildStream("Test", RelativePath);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public virtual void GeneratedStreamUriIsExpectedValue()
|
||||
{
|
||||
Actual.ShouldEqual(Expected);
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class Given_a_relative_path_referencing_two_ancestors : BuildStreamContextSpecification
|
||||
{
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
Expected = new Uri("ms-local-stream://microsoft.win32webviewhost_cw5n1h2txyewy_54657374/foo.htm");
|
||||
RelativePath = @"..\..\foo.htm";
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class Given_a_relative_path_referencing_sibling : BuildStreamContextSpecification
|
||||
{
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
Expected = new Uri("ms-local-stream://microsoft.win32webviewhost_cw5n1h2txyewy_54657374/foo.htm");
|
||||
RelativePath = @"foo.htm";
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class Given_a_relative_path_referencing_sibling_backslash : BuildStreamContextSpecification
|
||||
{
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
Expected = new Uri("ms-local-stream://microsoft.win32webviewhost_cw5n1h2txyewy_54657374//foo.htm");
|
||||
RelativePath = @"\foo.htm";
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class Given_a_relative_path_referencing_sibling_dotbackslash : BuildStreamContextSpecification
|
||||
{
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
Expected = new Uri("ms-local-stream://microsoft.win32webviewhost_cw5n1h2txyewy_54657374/foo.htm");
|
||||
RelativePath = @".\foo.htm";
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class Given_a_relative_path_referencing_sibling_frontslash : BuildStreamContextSpecification
|
||||
{
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
Expected = new Uri("ms-local-stream://microsoft.win32webviewhost_cw5n1h2txyewy_54657374/foo.htm");
|
||||
RelativePath = @"/foo.htm";
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class Given_a_relative_path_referencing_sibling_dotfrontslash : BuildStreamContextSpecification
|
||||
{
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
Expected = new Uri("ms-local-stream://microsoft.win32webviewhost_cw5n1h2txyewy_54657374/foo.htm");
|
||||
RelativePath = @"./foo.htm";
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class Given_a_relative_path_referencing_descendant : BuildStreamContextSpecification
|
||||
{
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
Expected = new Uri("ms-local-stream://microsoft.win32webviewhost_cw5n1h2txyewy_54657374/bar/foo.htm");
|
||||
RelativePath = @"bar/foo.htm";
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class Given_a_relative_path_referencing_descendant_backslash : BuildStreamContextSpecification
|
||||
{
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
Expected = new Uri("ms-local-stream://microsoft.win32webviewhost_cw5n1h2txyewy_54657374//bar/foo.htm");
|
||||
RelativePath = @"\bar\foo.htm";
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class Given_a_relative_path_referencing_descendant_dotbackslash : BuildStreamContextSpecification
|
||||
{
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
Expected = new Uri("ms-local-stream://microsoft.win32webviewhost_cw5n1h2txyewy_54657374/bar/foo.htm");
|
||||
RelativePath = @".\bar\foo.htm";
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class Given_a_relative_path_referencing_descendant_frontslash : BuildStreamContextSpecification
|
||||
{
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
Expected = new Uri("ms-local-stream://microsoft.win32webviewhost_cw5n1h2txyewy_54657374/bar/foo.htm");
|
||||
RelativePath = @"/bar/foo.htm";
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class Given_a_relative_path_referencing_descendant_dotfrontslash : BuildStreamContextSpecification
|
||||
{
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
Expected = new Uri("ms-local-stream://microsoft.win32webviewhost_cw5n1h2txyewy_54657374/bar/foo.htm");
|
||||
RelativePath = @"./bar/foo.htm";
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class Given_an_absolute_path_referencing_two_ancestors : BuildStreamContextSpecification
|
||||
{
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
|
||||
RelativePath = @"C:\foo.htm";
|
||||
}
|
||||
|
||||
protected override void When()
|
||||
{
|
||||
// Intentionally blank
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentOutOfRangeException))]
|
||||
public override void GeneratedStreamUriIsExpectedValue()
|
||||
{
|
||||
// The error actually occurs in the BuildStream(String, String) method
|
||||
base.When();
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class Given_an_UNC_path_referencing_two_ancestors : BuildStreamContextSpecification
|
||||
{
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
|
||||
RelativePath = @"\\machine\share\foo.htm";
|
||||
}
|
||||
|
||||
protected override void When()
|
||||
{
|
||||
// Intentionally blank
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentOutOfRangeException))]
|
||||
public override void GeneratedStreamUriIsExpectedValue()
|
||||
{
|
||||
// The error actually occurs in the BuildStream(String, String) method
|
||||
base.When();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Should;
|
||||
|
||||
namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.NavigateToLocalStreamUri
|
||||
{
|
||||
[TestClass]
|
||||
[TestCategory(TestConstants.Categories.Nav)]
|
||||
[DeploymentItem("FunctionalTests\\NavigateToLocalStreamUri\\async.htm")]
|
||||
public class Given_a_local_htm_file : HostFormWebViewContextSpecification
|
||||
{
|
||||
private bool _success;
|
||||
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
|
||||
WebView.NavigationCompleted += (o, e) =>
|
||||
{
|
||||
_success = e.IsSuccess;
|
||||
|
||||
Form.Close();
|
||||
};
|
||||
}
|
||||
|
||||
protected override void When()
|
||||
{
|
||||
NavigateToLocalAndWaitForFormClose(new Uri("async.htm", UriKind.Relative), new TestStreamResolver());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void LocalNavigationCompleted()
|
||||
{
|
||||
_success.ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
[TestCategory(TestConstants.Categories.Nav)]
|
||||
[DeploymentItem("FunctionalTests\\NavigateToLocalStreamUri\\async.htm")]
|
||||
public class Given_a_local_htm_file_with_async_XHR_for_local_content : HostFormWebViewContextSpecification
|
||||
{
|
||||
private string _scriptNotifyResult;
|
||||
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
WebView.IsJavaScriptEnabled = true;
|
||||
WebView.IsScriptNotifyAllowed = true;
|
||||
|
||||
|
||||
WebView.ScriptNotify += (o, e) =>
|
||||
{
|
||||
_scriptNotifyResult = e.Value;
|
||||
Form.Close();
|
||||
};
|
||||
}
|
||||
|
||||
protected override void When()
|
||||
{
|
||||
NavigateToLocalAndWaitForFormClose(new Uri("async.htm", UriKind.Relative), new TestStreamResolver());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void LocalNavigationCompleted()
|
||||
{
|
||||
_scriptNotifyResult.ShouldEqual("Success");
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
[TestCategory(TestConstants.Categories.Nav)]
|
||||
[DeploymentItem("FunctionalTests\\NavigateToLocalStreamUri\\sync.htm")]
|
||||
public class Given_a_local_htm_file_with_sync_XHR_for_local_content : HostFormWebViewContextSpecification
|
||||
{
|
||||
private string _scriptNotifyResult;
|
||||
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
WebView.IsJavaScriptEnabled = true;
|
||||
WebView.IsScriptNotifyAllowed = true;
|
||||
|
||||
|
||||
WebView.ScriptNotify += (o, e) =>
|
||||
{
|
||||
_scriptNotifyResult = e.Value;
|
||||
Form.Close();
|
||||
};
|
||||
}
|
||||
|
||||
protected override void When()
|
||||
{
|
||||
NavigateToLocalAndWaitForFormClose(new Uri("sync.htm", UriKind.Relative), new TestStreamResolver());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void LocalNavigationCompleted()
|
||||
{
|
||||
_scriptNotifyResult.ShouldEqual("Success");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT;
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.NavigateToLocalStreamUri
|
||||
{
|
||||
internal class TestStreamResolver : UriToLocalStreamResolver
|
||||
{
|
||||
public TestStreamResolver()
|
||||
:base(Path.GetDirectoryName(typeof(TestStreamResolver).Assembly.Location))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Async XHR Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<span id="progress">Loading...</span>
|
||||
|
||||
<script type="text/javascript">
|
||||
// Set timeout to show the page before causing the deadlock
|
||||
setTimeout(function () {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', '/async.htm', /* async */ true);
|
||||
xhr.onload = function () {
|
||||
/* this will never be called... */
|
||||
document.getElementById('progress').textContent = 'Success';
|
||||
window.external.notify('Success');
|
||||
};
|
||||
xhr.onerror = function () {
|
||||
/* this will never be called... */
|
||||
document.getElementById('progress').textContent = 'Error';
|
||||
window.external.notify('Error');
|
||||
};
|
||||
xhr.send();
|
||||
}, 1);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Sync XHR Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<span id="progress">Loading...</span>
|
||||
|
||||
<script type="text/javascript">
|
||||
// Set timeout to show the page before causing the deadlock
|
||||
setTimeout(function () {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', '/sync.htm', /* async */ false);
|
||||
xhr.onload = function () {
|
||||
/* this will never be called... */
|
||||
document.getElementById('progress').textContent = 'Success';
|
||||
window.external.notify('Success');
|
||||
};
|
||||
xhr.onerror = function () {
|
||||
/* this will never be called... */
|
||||
document.getElementById('progress').textContent = 'Error';
|
||||
window.external.notify('Error');
|
||||
};
|
||||
xhr.send();
|
||||
}, 1);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -3,7 +3,10 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Should;
|
||||
|
@ -83,4 +86,185 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTe
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class Navigate2Tests : HostFormWebViewContextSpecification
|
||||
{
|
||||
private bool _navigationCompleted;
|
||||
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
WebView.NavigationCompleted += (o, e) =>
|
||||
{
|
||||
_navigationCompleted = e.IsSuccess;
|
||||
Form.Close();
|
||||
};
|
||||
}
|
||||
|
||||
protected override void When()
|
||||
{
|
||||
PerformActionAndWaitForFormClose(() =>
|
||||
{
|
||||
WebView.Navigate(TestConstants.Uris.HttpBin, HttpMethod.Get);
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Explict_HTTP_GET_succeeds()
|
||||
{
|
||||
_navigationCompleted.ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class NavigateGetWithHeaders : HostFormWebViewContextSpecification
|
||||
{
|
||||
private bool _navigationCompleted;
|
||||
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
WebView.NavigationCompleted += (o, e) =>
|
||||
{
|
||||
_navigationCompleted = e.IsSuccess;
|
||||
Form.Close();
|
||||
};
|
||||
}
|
||||
|
||||
protected override void When()
|
||||
{
|
||||
PerformActionAndWaitForFormClose(() =>
|
||||
{
|
||||
WebView.Navigate(
|
||||
TestConstants.Uris.HttpBin,
|
||||
HttpMethod.Get,
|
||||
null,
|
||||
new[] { new KeyValuePair<string, string>("pragma", "no-cache") });
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Explict_HTTP_GET_with_HEADERS_succeeds()
|
||||
{
|
||||
_navigationCompleted.ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class NavigateGetWithBasicAuth : HostFormWebViewContextSpecification
|
||||
{
|
||||
private bool _navigationCompleted;
|
||||
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
WebView.NavigationCompleted += (o, e) =>
|
||||
{
|
||||
_navigationCompleted = e.IsSuccess;
|
||||
Form.Close();
|
||||
};
|
||||
}
|
||||
|
||||
protected override void When()
|
||||
{
|
||||
PerformActionAndWaitForFormClose(() =>
|
||||
{
|
||||
const string user = "usr";
|
||||
const string password = "pwd";
|
||||
const string header = "Authorization";
|
||||
|
||||
var authInfo = Convert.ToBase64String(Encoding.Default.GetBytes($"{user}:{password}"));
|
||||
|
||||
WebView.Navigate(
|
||||
new Uri(TestConstants.Uris.HttpBin, new Uri($"/basic-auth/{user}/{password}", UriKind.Relative)),
|
||||
HttpMethod.Get,
|
||||
null,
|
||||
new[] { new KeyValuePair<string, string>(header, $"Basic {authInfo}") });
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Explict_HTTP_GET_with_AUTH_BASIC_succeeds()
|
||||
{
|
||||
_navigationCompleted.ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class NavigateOption : HostFormWebViewContextSpecification
|
||||
{
|
||||
private bool _navigationCompleted;
|
||||
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
WebView.NavigationCompleted += (o, e) =>
|
||||
{
|
||||
_navigationCompleted = e.IsSuccess;
|
||||
Form.Close();
|
||||
};
|
||||
}
|
||||
|
||||
protected override void When()
|
||||
{
|
||||
PerformActionAndWaitForFormClose(() =>
|
||||
{
|
||||
|
||||
|
||||
WebView.Navigate(
|
||||
TestConstants.Uris.ExampleCom,
|
||||
HttpMethod.Options
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentOutOfRangeException))]
|
||||
[Ignore("Pops UI that stalls test")]
|
||||
public void Explict_HTTP_OPTION_fails()
|
||||
{
|
||||
_navigationCompleted.ShouldBeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class NavigatePostWithContent : HostFormWebViewContextSpecification
|
||||
{
|
||||
private bool _navigationCompleted;
|
||||
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
WebView.NavigationCompleted += (o, e) =>
|
||||
{
|
||||
_navigationCompleted = e.IsSuccess;
|
||||
Form.Close();
|
||||
};
|
||||
}
|
||||
|
||||
protected override void When()
|
||||
{
|
||||
PerformActionAndWaitForFormClose(() =>
|
||||
{
|
||||
string Foo()
|
||||
{
|
||||
var c = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("Foo", "Bar"), });
|
||||
return c.ReadAsStringAsync().Result;
|
||||
}
|
||||
|
||||
WebView.Navigate(
|
||||
new Uri(TestConstants.Uris.HttpBin, "/post"),
|
||||
HttpMethod.Post,
|
||||
Foo()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Explict_HTTP_POST_with_data_succeeds()
|
||||
{
|
||||
_navigationCompleted.ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Should;
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.PreLoad
|
||||
{
|
||||
[TestClass]
|
||||
public class NullPreLoadScript : HostFormWebViewContextSpecification
|
||||
{
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
WebView.IsJavaScriptEnabled = true;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotPassNullForPreLoadScript()
|
||||
{
|
||||
WebView.AddPreLoadedScript(null);
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class EmptyPreLoadScript : HostFormWebViewContextSpecification
|
||||
{
|
||||
private bool _navSuccess;
|
||||
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
WebView.IsJavaScriptEnabled = true;
|
||||
WebView.AddPreLoadedScript(string.Empty);
|
||||
|
||||
WebView.NavigationCompleted += (o, e) =>
|
||||
{
|
||||
_navSuccess = e.IsSuccess;
|
||||
Form.Close();
|
||||
};
|
||||
}
|
||||
|
||||
protected override void When()
|
||||
{
|
||||
NavigateAndWaitForFormClose(TestConstants.Uris.ExampleCom);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NavigationCompletesForEmptyPreLoadScript()
|
||||
{
|
||||
_navSuccess.ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class NonExistentPreLoadScript : HostFormWebViewContextSpecification
|
||||
{
|
||||
private bool _navSuccess;
|
||||
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
WebView.IsJavaScriptEnabled = true;
|
||||
WebView.AddPreLoadedScript($"./non-exist.js");
|
||||
|
||||
WebView.NavigationCompleted += (o, e) =>
|
||||
{
|
||||
_navSuccess = e.IsSuccess;
|
||||
Form.Close();
|
||||
};
|
||||
}
|
||||
|
||||
protected override void When()
|
||||
{
|
||||
NavigateAndWaitForFormClose(TestConstants.Uris.ExampleCom);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NavigateCompletesWithoutError()
|
||||
{
|
||||
_navSuccess.ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
[DeploymentItem("FunctionalTests/PreLoad/preload.js")]
|
||||
public class RelativePreLoadScript : HostFormWebViewContextSpecification
|
||||
{
|
||||
private bool _scriptNotifyCalled;
|
||||
|
||||
protected override void Given()
|
||||
{
|
||||
base.Given();
|
||||
WebView.IsScriptNotifyAllowed = true;
|
||||
WebView.IsJavaScriptEnabled = true;
|
||||
|
||||
// Not sure how to get this to execute
|
||||
WebView.AddPreLoadedScript(Path.Combine(TestContext.TestDeploymentDir, "preload.js"));
|
||||
|
||||
// Set up the event handler
|
||||
WebView.ScriptNotify += (o, e) =>
|
||||
{
|
||||
_scriptNotifyCalled = true;
|
||||
Form.Close();
|
||||
};
|
||||
}
|
||||
|
||||
protected override void When()
|
||||
{
|
||||
NavigateAndWaitForFormClose(TestConstants.Uris.ExampleCom);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[Timeout(TestConstants.Timeouts.Longest)]
|
||||
public void ScriptNotifyRaised()
|
||||
{
|
||||
_scriptNotifyCalled.ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
window.external.notify('preload');
|
|
@ -5,6 +5,7 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Forms;
|
||||
using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT;
|
||||
using Should;
|
||||
|
||||
namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests
|
||||
|
@ -110,6 +111,22 @@ namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTe
|
|||
});
|
||||
}
|
||||
|
||||
protected virtual void NavigateToLocalAndWaitForFormClose(string relativePath)
|
||||
{
|
||||
PerformActionAndWaitForFormClose(() =>
|
||||
{
|
||||
WriteLine("Navigating WebView:");
|
||||
WebView.NavigateToLocal(relativePath);
|
||||
});
|
||||
}
|
||||
|
||||
protected virtual void NavigateToLocalAndWaitForFormClose(Uri relativePath, IUriToStreamResolver streamResolver)
|
||||
{
|
||||
PerformActionAndWaitForFormClose(() =>
|
||||
{
|
||||
WriteLine("Navigating WebView");
|
||||
WebView.NavigateToLocalStreamUri(relativePath, streamResolver);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -55,10 +55,14 @@
|
|||
<Compile Include="FunctionalTests\Ctor\WebViewControlProcessCreateWebViewAsyncTests.cs" />
|
||||
<Compile Include="FunctionalTests\DocumentTitle\DocumentTitleTests.cs" />
|
||||
<Compile Include="FunctionalTests\FullScreen\FullScreenTests.cs" />
|
||||
<Compile Include="FunctionalTests\NavigateToLocalStreamUri\BuildStreamTests.cs" />
|
||||
<Compile Include="FunctionalTests\NavigateToLocalStreamUri\NavigateToLocalStreamUriTests.cs" />
|
||||
<Compile Include="FunctionalTests\NavigateToLocalStreamUri\TestStreamResolver.cs" />
|
||||
<Compile Include="FunctionalTests\Navigation\NavigateTests.cs" />
|
||||
<Compile Include="FunctionalTests\Navigation\StopTests.cs" />
|
||||
<Compile Include="FunctionalTests\NewWindow\NewWindowTests.cs" />
|
||||
<Compile Include="FunctionalTests\PartialTrust\PartialTrustTests.cs" />
|
||||
<Compile Include="FunctionalTests\PreLoad\PreLoadTests.cs" />
|
||||
<Compile Include="FunctionalTests\Termination\TerminationTests.cs" />
|
||||
<Compile Include="FunctionalTests\TestHostForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
|
@ -114,6 +118,17 @@
|
|||
<Version>1.1.20</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="FunctionalTests\NavigateToLocalStreamUri\sync.htm">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="FunctionalTests\NavigateToLocalStreamUri\async.htm">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="FunctionalTests\PreLoad\preload.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="Pack">
|
||||
|
|
Загрузка…
Ссылка в новой задаче