mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 10:46:33 +02:00
[FileExplorerPreview] Move everything from WebBrowser to WebView2 (#17588)
* Move MarkdownPreviewHandler from WebBrowser to WebView2 * Disable context menu Open links in default browser * Update expect.txt * Move SvgPreviewHandler from WebBrowser to WebView2 * Migrate SvgThumbnailProvider from WebBrowser to WebView2 * Migrate CustomControlTest to WebView2 Remove WebBrowser related stuff * Update tests * Revert GetThumbnail return value Disable javascript dialogs in WebView2 for Svg thumbnail and preview * expect.txt * Increase timeout for Markdown tests * Add sleeps * Add zero check
This commit is contained in:
@@ -23,7 +23,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\codeAnalysis\GlobalSuppressions.cs" Link="GlobalSuppressions.cs" />
|
||||
<Compile Update="controls\WebBrowserExt.cs" />
|
||||
<Compile Update="examplehandler\CustomControlTest.cs" />
|
||||
<Compile Update="controls\FormHandlerControl.cs" />
|
||||
</ItemGroup>
|
||||
@@ -39,6 +38,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1150.38" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace Common
|
||||
this.Controls.Clear();
|
||||
});
|
||||
|
||||
// Call garbage collection at the time of unloading of Preview. This is to mitigate issue with WebBrowser Control not able to dispose properly.
|
||||
// Call garbage collection at the time of unloading of Preview.
|
||||
// Which is preventing prevhost.exe to exit at the time of closing File explorer.
|
||||
// Preview Handlers run in a separate process from PowerToys. This will not affect the performance of other modules.
|
||||
// Mitigate the following Github issue: https://github.com/microsoft/PowerToys/issues/1468
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Flags to control download and execution in Web Browser Control.
|
||||
/// Values of flags are defined in mshtmdid.h in distributed Windows Sdk.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Interop, keeping stuff in sync")]
|
||||
public enum WebBrowserDownloadControlFlags : int
|
||||
{
|
||||
/// <summary>
|
||||
/// Images will be downloaded from the server if this flag is set.
|
||||
/// </summary>
|
||||
DLIMAGES = 0x00000010,
|
||||
|
||||
/// <summary>
|
||||
/// Videos will be downloaded from the server if this flag is set.
|
||||
/// </summary>
|
||||
VIDEOS = 0x00000020,
|
||||
|
||||
/// <summary>
|
||||
/// Background sounds will be downloaded from the server if this flag is set.
|
||||
/// </summary>
|
||||
BGSOUNDS = 0x00000040,
|
||||
|
||||
/// <summary>
|
||||
/// Scripts will not be executed.
|
||||
/// </summary>
|
||||
NO_SCRIPTS = 0x00000080,
|
||||
|
||||
/// <summary>
|
||||
/// Java applets will not be executed.
|
||||
/// </summary>
|
||||
NO_JAVA = 0x00000100,
|
||||
|
||||
/// <summary>
|
||||
/// ActiveX controls will not be executed.
|
||||
/// </summary>
|
||||
NO_RUNACTIVEXCTLS = 0x00000200,
|
||||
|
||||
/// <summary>
|
||||
/// ActiveX controls will not be downloaded.
|
||||
/// </summary>
|
||||
NO_DLACTIVEXCTLS = 0x00000400,
|
||||
|
||||
/// <summary>
|
||||
/// The page will only be downloaded, not displayed.
|
||||
/// </summary>
|
||||
DOWNLOADONLY = 0x00000800,
|
||||
|
||||
/// <summary>
|
||||
/// WebBrowser Control will download and parse a frameSet, but not the individual frame objects within the frameSet.
|
||||
/// </summary>
|
||||
NO_FRAMEDOWNLOAD = 0x00001000,
|
||||
|
||||
/// <summary>
|
||||
/// The server will be asked for update status. Cached files will be used if the server indicates that the cached information is up-to-date.
|
||||
/// </summary>
|
||||
RESYNCHRONIZE = 0x00002000,
|
||||
|
||||
/// <summary>
|
||||
/// Files will be re-downloaded from the server regardless of the update status of the files.
|
||||
/// </summary>
|
||||
PRAGMA_NO_CACHE = 0x00004000,
|
||||
|
||||
/// <summary>
|
||||
/// Behaviors are not downloaded and are disabled in the document.
|
||||
/// </summary>
|
||||
NO_BEHAVIORS = 0x00008000,
|
||||
|
||||
/// <summary>
|
||||
/// Character sets specified in meta elements are suppressed.
|
||||
/// </summary>
|
||||
NO_METACHARSET = 0x00010000,
|
||||
|
||||
/// <summary>
|
||||
/// The browsing component will disable UTF-8 encoding.
|
||||
/// </summary>
|
||||
URL_ENCODING_DISABLE_UTF8 = 0x00020000,
|
||||
|
||||
/// <summary>
|
||||
/// The browsing component will enable UTF-8 encoding.
|
||||
/// </summary>
|
||||
URL_ENCODING_ENABLE_UTF8 = 0x00040000,
|
||||
|
||||
/// <summary>
|
||||
/// No Documentation Available.
|
||||
/// </summary>
|
||||
NOFRAMES = 0x00080000,
|
||||
|
||||
/// <summary>
|
||||
/// WebBrowser Control always operates in offline mode.
|
||||
/// </summary>
|
||||
FORCEOFFLINE = 0x10000000,
|
||||
|
||||
/// <summary>
|
||||
/// No client pull operations will be performed.
|
||||
/// </summary>
|
||||
NO_CLIENTPULL = 0x20000000,
|
||||
|
||||
/// <summary>
|
||||
/// No user interface will be displayed during downloads.
|
||||
/// </summary>
|
||||
SILENT = 0x40000000,
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using Common;
|
||||
|
||||
namespace PreviewHandlerCommon
|
||||
{
|
||||
/// <summary>
|
||||
/// Customized the WebBrowser to get control over what it downloads, displays and executes.
|
||||
/// </summary>
|
||||
public class WebBrowserExt : WebBrowser
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
|
||||
{
|
||||
// Returns instance of WebBrowserSiteExt.
|
||||
return new WebBrowserSiteExt(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extend the WebBrowserSite with IDispatch implementation to handle the DISPID_AMBIENT_DLCONTROL.
|
||||
/// More details: https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa770041(v=vs.85)?redirectedfrom=MSDN#controlling-download-and-execution.
|
||||
/// </summary>
|
||||
protected class WebBrowserSiteExt : WebBrowserSite, IReflect
|
||||
{
|
||||
// Dispid of DISPID_AMBIENT_DLCONTROL is defined in MsHtmdid.h header file in distributed Windows Sdk component.
|
||||
private const string DISPIDAMBIENTDLCONTROL = "[DISPID=-5512]";
|
||||
private WebBrowserExt browserExtControl;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebBrowserSiteExt"/> class.
|
||||
/// </summary>
|
||||
/// <param name="browserControl">Browser Control Instance pass to the site.</param>
|
||||
public WebBrowserSiteExt(WebBrowserExt browserControl)
|
||||
: base(browserControl)
|
||||
{
|
||||
this.browserExtControl = browserControl;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Type UnderlyingSystemType
|
||||
{
|
||||
get { return this.GetType(); }
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
|
||||
{
|
||||
object result;
|
||||
|
||||
if (name != null && name.Equals(DISPIDAMBIENTDLCONTROL, StringComparison.Ordinal))
|
||||
{
|
||||
// Using InvariantCulture since this is used for web browser configurations
|
||||
result = Convert.ToInt32(
|
||||
WebBrowserDownloadControlFlags.DLIMAGES |
|
||||
WebBrowserDownloadControlFlags.PRAGMA_NO_CACHE |
|
||||
WebBrowserDownloadControlFlags.FORCEOFFLINE |
|
||||
WebBrowserDownloadControlFlags.NO_CLIENTPULL |
|
||||
WebBrowserDownloadControlFlags.NO_SCRIPTS |
|
||||
WebBrowserDownloadControlFlags.NO_JAVA |
|
||||
WebBrowserDownloadControlFlags.NO_FRAMEDOWNLOAD |
|
||||
WebBrowserDownloadControlFlags.NOFRAMES |
|
||||
WebBrowserDownloadControlFlags.NO_DLACTIVEXCTLS |
|
||||
WebBrowserDownloadControlFlags.NO_RUNACTIVEXCTLS |
|
||||
WebBrowserDownloadControlFlags.NO_BEHAVIORS |
|
||||
WebBrowserDownloadControlFlags.SILENT, CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = GetType().InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public FieldInfo[] GetFields(BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetFields(bindingAttr);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public MethodInfo[] GetMethods(BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetMethods(bindingAttr);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public PropertyInfo[] GetProperties(BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetProperties(bindingAttr);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public FieldInfo GetField(string name, BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetField(name, bindingAttr);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public MemberInfo[] GetMember(string name, BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetMember(name, bindingAttr);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public MemberInfo[] GetMembers(BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetMembers(bindingAttr);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public MethodInfo GetMethod(string name, BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetMethod(name, bindingAttr);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
|
||||
{
|
||||
return this.GetType().GetMethod(name, bindingAttr, binder, types, modifiers);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public PropertyInfo GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
|
||||
{
|
||||
return this.GetType().GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public PropertyInfo GetProperty(string name, BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetProperty(name, bindingAttr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,12 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows.Forms;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Microsoft.Web.WebView2.WinForms;
|
||||
|
||||
namespace Common
|
||||
{
|
||||
@@ -12,6 +17,38 @@ namespace Common
|
||||
/// </summary>
|
||||
public class CustomControlTest : FormHandlerControl
|
||||
{
|
||||
/// <summary>
|
||||
/// WebView2 Control to display Svg.
|
||||
/// </summary>
|
||||
private WebView2 _browser;
|
||||
|
||||
/// <summary>
|
||||
/// WebView2 Environment
|
||||
/// </summary>
|
||||
private CoreWebView2Environment _webView2Environment;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the virtual host
|
||||
/// </summary>
|
||||
public const string VirtualHostName = "PowerToysLocalCustomControlTest";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path of the current assembly.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Source: https://stackoverflow.com/a/283917/14774889
|
||||
/// </remarks>
|
||||
public static string AssemblyDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
string codeBase = Assembly.GetExecutingAssembly().Location;
|
||||
UriBuilder uri = new UriBuilder(codeBase);
|
||||
string path = Uri.UnescapeDataString(uri.Path);
|
||||
return Path.GetDirectoryName(path);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the preview on the Control.
|
||||
/// </summary>
|
||||
@@ -21,13 +58,41 @@ namespace Common
|
||||
this.InvokeOnControlThread(() =>
|
||||
{
|
||||
var filePath = dataSource as string;
|
||||
WebBrowser browser = new WebBrowser();
|
||||
|
||||
browser.DocumentText = "Test";
|
||||
browser.Navigate(new Uri(filePath));
|
||||
browser.Dock = DockStyle.Fill;
|
||||
browser.IsWebBrowserContextMenuEnabled = false;
|
||||
this.Controls.Add(browser);
|
||||
_browser = new WebView2();
|
||||
_browser.Dock = DockStyle.Fill;
|
||||
_browser.Visible = true;
|
||||
_browser.NavigationCompleted += (object sender, CoreWebView2NavigationCompletedEventArgs args) =>
|
||||
{
|
||||
// Put here logic needed after WebView2 control is done navigating to url/page
|
||||
};
|
||||
|
||||
ConfiguredTaskAwaitable<CoreWebView2Environment>.ConfiguredTaskAwaiter
|
||||
webView2EnvironmentAwaiter = CoreWebView2Environment
|
||||
.CreateAsync(userDataFolder: System.Environment.GetEnvironmentVariable("USERPROFILE") +
|
||||
"\\AppData\\LocalLow\\Microsoft\\PowerToys\\CustomControlTest-Temp")
|
||||
.ConfigureAwait(true).GetAwaiter();
|
||||
webView2EnvironmentAwaiter.OnCompleted(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_webView2Environment = webView2EnvironmentAwaiter.GetResult();
|
||||
await _browser.EnsureCoreWebView2Async(_webView2Environment).ConfigureAwait(true);
|
||||
await _browser.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.addEventListener('contextmenu', window => {window.preventDefault();});");
|
||||
_browser.CoreWebView2.SetVirtualHostNameToFolderMapping(VirtualHostName, AssemblyDirectory, CoreWebView2HostResourceAccessKind.Allow);
|
||||
|
||||
// Navigate to page represented as a string
|
||||
_browser.NavigateToString("Test");
|
||||
|
||||
// Or navigate to Uri
|
||||
_browser.Source = new Uri(filePath);
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
}
|
||||
});
|
||||
|
||||
this.Controls.Add(_browser);
|
||||
base.DoPreview(dataSource);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user