Merge pull request #2022 from mRemoteNG/webview2

Replace CefSharp with Webview2
This commit is contained in:
Faryan Rezagholi
2021-08-12 23:46:04 +02:00
committed by GitHub
15 changed files with 3390 additions and 501 deletions

View File

@@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- #283: Support for native PowerShell remoting as new protocol
- #1850: Minify config xml
### Changed
- #2022: Replaced CefSharp with WebView2
- #2014: Revised icons
- #2013: Removed components check
- #2011: Removed screenshot manager

View File

@@ -90,10 +90,6 @@ Copyright © 2004 Marc Merritt © 2008 Felix Deimel
# Included Components
**[CefSharp](https://github.com/cefsharp/CefSharp)**
Copyright © The CefSharp Authors
MIT License
**[DockPanel Suite](https://github.com/dockpanelsuite/dockpanelsuite)**
Copyright © 2018 @roken and @lextm (formerly Weifen Luo)
MIT License

View File

@@ -1,34 +0,0 @@
// Copyright © 2013 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;
using System;
namespace mRemoteNG.Connection.Protocol.Http
{
public class DownloadHandler : IDownloadHandler
{
public event EventHandler<DownloadItem> OnBeforeDownloadFired;
public event EventHandler<DownloadItem> OnDownloadUpdatedFired;
public void OnBeforeDownload(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback)
{
OnBeforeDownloadFired?.Invoke(this, downloadItem);
if (!callback.IsDisposed)
{
using (callback)
{
callback.Continue(downloadItem.SuggestedFileName, showDialog: true);
}
}
}
public void OnDownloadUpdated(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback)
{
OnDownloadUpdatedFired?.Invoke(this, downloadItem);
}
}
}

View File

@@ -1,68 +0,0 @@
using CefSharp;
using System.Diagnostics;
using System.Security.Cryptography.X509Certificates;
namespace mRemoteNG.Connection.Protocol.Http
{
partial class RequestHandler : IRequestHandler
{
public bool GetAuthCredentials(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
{
return false;
}
public IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
{
return null;
}
public bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect)
{
if (request.Url.StartsWith(Cef.CefCommitHash))
{
return false;
}
else
{
Process.Start(request.Url);
return true;
}
}
public void OnDocumentAvailableInMainFrame(IWebBrowser chromiumWebBrowser, IBrowser browser)
{
}
public bool OnCertificateError(IWebBrowser chromiumWebBrowser, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback)
{
return false;
}
public bool OnOpenUrlFromTab(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture)
{
return false;
}
public void OnPluginCrashed(IWebBrowser chromiumWebBrowser, IBrowser browser, string pluginPath)
{
}
public bool OnQuotaRequest(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, long newSize, IRequestCallback callback)
{
return true;
}
public void OnRenderProcessTerminated(IWebBrowser chromiumWebBrowser, IBrowser browser, CefTerminationStatus status)
{
}
public void OnRenderViewReady(IWebBrowser chromiumWebBrowser, IBrowser browser)
{
}
public bool OnSelectClientCertificate(IWebBrowser chromiumWebBrowser, IBrowser browser, bool isProxy, string host, int port, X509Certificate2Collection certificates, ISelectClientCertificateCallback callback)
{
return true;
}
}
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;
using Microsoft.Web.WebView2.WinForms;
using mRemoteNG.Tools;
using mRemoteNG.App;
using mRemoteNG.Resources.Language;
@@ -14,24 +13,22 @@ namespace mRemoteNG.Connection.Protocol.Http
{
#region Private Properties
private Control wBrowser;
private Control _wBrowser;
private string _tabTitle;
protected string httpOrS;
protected int defaultPort;
private string tabTitle;
private bool browserInitialised = false;
private bool connectCalled = false;
#endregion
#region Public Methods
protected HTTPBase(RenderingEngine RenderingEngine)
protected HTTPBase(RenderingEngine renderingEngine)
{
try
{
if (RenderingEngine == RenderingEngine.CEF)
if (renderingEngine == RenderingEngine.EdgeChromium)
{
Control = new ChromiumWebBrowser("about:blank")
Control = new WebView2()
{
Dock = DockStyle.Fill,
};
@@ -53,33 +50,26 @@ namespace mRemoteNG.Connection.Protocol.Http
try
{
if (InterfaceControl.Parent is ConnectionTab objConnectionTab) tabTitle = objConnectionTab.TabText;
if (InterfaceControl.Parent is ConnectionTab objConnectionTab) _tabTitle = objConnectionTab.TabText;
}
catch (Exception)
{
tabTitle = "";
_tabTitle = "";
}
try
{
wBrowser = Control;
_wBrowser = Control;
if (InterfaceControl.Info.RenderingEngine == RenderingEngine.CEF)
if (InterfaceControl.Info.RenderingEngine == RenderingEngine.EdgeChromium)
{
var CEFBrowser = (ChromiumWebBrowser)wBrowser;
if (CEFBrowser != null)
{
CEFBrowser.LoadingStateChanged += CefBrowser_LoadingStateChanged;
CEFBrowser.TitleChanged += WBrowser_DocumentTitleChanged;
}
else
{
throw new Exception("Failed to initialize CEF Rendering Engine.");
}
var edge = (WebView2)_wBrowser;
edge.CoreWebView2InitializationCompleted += Edge_CoreWebView2InitializationCompleted;
}
else
{
var objWebBrowser = (WebBrowser)wBrowser;
var objWebBrowser = (WebBrowser)_wBrowser;
objWebBrowser.ScrollBarsEnabled = true;
// http://stackoverflow.com/questions/4655662/how-to-ignore-script-errors-in-webbrowser
@@ -87,7 +77,6 @@ namespace mRemoteNG.Connection.Protocol.Http
objWebBrowser.Navigated += WBrowser_Navigated;
objWebBrowser.DocumentTitleChanged += WBrowser_DocumentTitleChanged;
browserInitialised = true;
}
return true;
@@ -103,20 +92,16 @@ namespace mRemoteNG.Connection.Protocol.Http
{
try
{
if (InterfaceControl.Info.RenderingEngine == RenderingEngine.CEF)
if (InterfaceControl.Info.RenderingEngine == RenderingEngine.EdgeChromium)
{
if (browserInitialised)
{
((ChromiumWebBrowser)wBrowser).Load(GetURL());
}
((WebView2)_wBrowser).Source = new Uri(GetUrl());
}
else
{
((WebBrowser)wBrowser).Navigate(GetURL());
((WebBrowser)_wBrowser).Navigate(GetUrl());
}
base.Connect();
connectCalled = true;
return true;
}
catch (Exception ex)
@@ -130,22 +115,12 @@ namespace mRemoteNG.Connection.Protocol.Http
#region Private Methods
private string GetURL()
private string GetUrl()
{
try
{
var strHost = InterfaceControl.Info.Hostname;
/*
* Commenting out since this codes doesn't actually do anything at this time...
* Possibly related to MR-221 and/or MR-533 ????
*
string strAuth = "";
if (((int)Force & (int)ConnectionInfo.Force.NoCredentials) != (int)ConnectionInfo.Force.NoCredentials && !string.IsNullOrEmpty(InterfaceControl.Info.Username) && !string.IsNullOrEmpty(InterfaceControl.Info.Password))
{
strAuth = "Authorization: Basic " + Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(InterfaceControl.Info.Username + ":" + InterfaceControl.Info.Password)) + Environment.NewLine;
}
*/
if (InterfaceControl.Info.Port != defaultPort)
{
if (strHost.EndsWith("/"))
@@ -161,6 +136,7 @@ namespace mRemoteNG.Connection.Protocol.Http
if (strHost.Contains(httpOrS + "://") == false)
strHost = httpOrS + "://" + strHost;
}
return strHost;
}
catch (Exception ex)
@@ -174,26 +150,17 @@ namespace mRemoteNG.Connection.Protocol.Http
#region Events
private void CefBrowser_LoadingStateChanged(object sender, LoadingStateChangedEventArgs e)
private void Edge_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
{
browserInitialised = !e.IsLoading;
if (browserInitialised)
if (!e.IsSuccess)
{
// Unhook the loading state changes now, as navigation is done by the user on links in the control
((ChromiumWebBrowser)wBrowser).LoadingStateChanged -= CefBrowser_LoadingStateChanged;
// If this Connection has already been asked to connect but the browser hadn't finished initalising
// then the connect wouldn't have been allowed to take place, so now we can call it!
if (connectCalled)
{
Connect();
}
Runtime.MessageCollector.AddExceptionStackTrace(Language.HttpFailedUrlBuild, e.InitializationException);
}
}
private void WBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
if (!(wBrowser is WebBrowser objWebBrowser)) return;
if (!(_wBrowser is WebBrowser objWebBrowser)) return;
// This can only be set once the WebBrowser control is shown, it will throw a COM exception otherwise.
objWebBrowser.AllowWebBrowserDrop = false;
@@ -207,33 +174,18 @@ namespace mRemoteNG.Connection.Protocol.Http
{
if (!(InterfaceControl.Parent is ConnectionTab tabP)) return;
string shortTitle;
if (InterfaceControl.Info.RenderingEngine == RenderingEngine.CEF)
if (((WebBrowser)_wBrowser).DocumentTitle.Length >= 15)
{
if (((TitleChangedEventArgs)e).Title.Length >= 15)
{
shortTitle = ((TitleChangedEventArgs)e).Title.Substring(0, 10) + "...";
}
else
{
shortTitle = ((CefSharp.TitleChangedEventArgs)e).Title;
}
shortTitle = ((WebBrowser)_wBrowser).DocumentTitle.Substring(0, 10) + "...";
}
else
{
if (((WebBrowser)wBrowser).DocumentTitle.Length >= 15)
{
shortTitle = ((WebBrowser)wBrowser).DocumentTitle.Substring(0, 10) + "...";
}
else
{
shortTitle = ((WebBrowser)wBrowser).DocumentTitle;
}
shortTitle = ((WebBrowser)_wBrowser).DocumentTitle;
}
if (!string.IsNullOrEmpty(tabTitle))
if (!string.IsNullOrEmpty(_tabTitle))
{
tabP.TabText = tabTitle + @" - " + shortTitle;
tabP.TabText = _tabTitle + @" - " + shortTitle;
}
else
{
@@ -246,38 +198,6 @@ namespace mRemoteNG.Connection.Protocol.Http
}
}
private void geckoBrowser_DocumentTitleChanged(object sender, EventArgs e)
{
try
{
if (!(InterfaceControl.Parent is ConnectionTab tabP)) return;
string shortTitle;
if (((WebBrowser)wBrowser).DocumentTitle.Length >= 15)
{
shortTitle = ((WebBrowser)wBrowser).DocumentTitle.Substring(0, 10) + "...";
}
else
{
shortTitle = ((WebBrowser)wBrowser).DocumentTitle;
}
if (!string.IsNullOrEmpty(tabTitle))
{
tabP.TabText = tabTitle + @" - " + shortTitle;
}
else
{
tabP.TabText = shortTitle;
}
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.HttpDocumentTileChangeFailed, ex);
}
}
#endregion
#region Enums
@@ -288,7 +208,7 @@ namespace mRemoteNG.Connection.Protocol.Http
IE = 1,
[LocalizedAttributes.LocalizedDescription(nameof(Language.HttpCEF))]
CEF = 2
EdgeChromium = 2
}
#endregion

View File

@@ -1525,7 +1525,7 @@ namespace mRemoteNG.Properties {
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("CEF")]
[global::System.Configuration.DefaultSettingValueAttribute("EdgeChromium")]
public string ConDefaultRenderingEngine {
get {
return ((string)(this["ConDefaultRenderingEngine"]));

View File

@@ -2316,7 +2316,7 @@ namespace mRemoteNG.Resources.Language {
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die CEF (Chromium) ähnelt.
/// Sucht eine lokalisierte Zeichenfolge, die Edge Chromium ähnelt.
/// </summary>
internal static string HttpCEF {
get {
@@ -6082,6 +6082,15 @@ namespace mRemoteNG.Resources.Language {
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die WebView2 creation failed with exception ähnelt.
/// </summary>
internal static string WebView2InitializationFailed {
get {
return ResourceManager.GetString("WebView2InitializationFailed", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Weekly ähnelt.
/// </summary>

View File

@@ -2022,4 +2022,7 @@ Nightly umfasst Alphas, Betas und Release Candidates.</value>
<data name="ExceptionMessage" xml:space="preserve">
<value>Fehlermeldung</value>
</data>
<data name="WebView2InitializationFailed" xml:space="preserve">
<value>WebView2-Erstellung fehlgeschlagen</value>
</data>
</root>

View File

@@ -2133,7 +2133,7 @@ Nightly Channel includes Alphas, Betas &amp; Release Candidates.</value>
<value>Determines whether menus and windows can be displayed with animation effects in the remote session.</value>
</data>
<data name="HttpCEF" xml:space="preserve">
<value>CEF (Chromium)</value>
<value>Edge Chromium</value>
</data>
<data name="HttpFailedUrlBuild" xml:space="preserve">
<value>Failed to contruct the URL to load</value>
@@ -2147,4 +2147,7 @@ Nightly Channel includes Alphas, Betas &amp; Release Candidates.</value>
<data name="StartProgram" xml:space="preserve">
<value>Start Program</value>
</data>
<data name="WebView2InitializationFailed" xml:space="preserve">
<value>WebView2 creation failed with exception</value>
</data>
</root>

View File

@@ -28,8 +28,6 @@ using System.Text;
using System.Windows.Forms;
using mRemoteNG.UI.Panels;
using WeifenLuo.WinFormsUI.Docking;
using CefSharp;
using CefSharp.WinForms;
using mRemoteNG.Resources.Language;
using mRemoteNG.UI.Controls;
using Settings = mRemoteNG.Properties.Settings;
@@ -159,12 +157,6 @@ namespace mRemoteNG.UI.Forms
SetMenuDependencies();
//Monitor parent process exit and close subprocesses if parent process exits first
//This will at some point in the future becomes the default
CefSharpSettings.SubprocessExitIfParentProcessClosed = true;
CefSetup();
var uiLoader = new DockPanelLayoutLoader(this, messageCollector);
uiLoader.LoadPanelsFromXml();
@@ -225,32 +217,6 @@ namespace mRemoteNG.UI.Forms
panelAdder.AddPanel(panelName);
}
private void CefSetup()
{
//For Windows 7 and above, best to include relevant app.manifest entries as well
Cef.EnableHighDPISupport();
string dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Application.ProductName);
if (Runtime.IsPortableEdition) dir = SettingsFileInfo.SettingsPath;
CefSettings settings = new CefSettings()
{
CachePath = Path.Combine(dir, "CEFCache"),
LogFile = Path.Combine(dir, "mRemoteNG_cef.log"),
};
if (Settings.Default.TextLogMessageWriterWriteDebugMsgs)
settings.LogSeverity = LogSeverity.Verbose;
else if (Settings.Default.TextLogMessageWriterWriteInfoMsgs)
settings.LogSeverity = LogSeverity.Info;
else if (Settings.Default.TextLogMessageWriterWriteWarningMsgs)
settings.LogSeverity = LogSeverity.Warning;
else if (Settings.Default.TextLogMessageWriterWriteErrorMsgs)
settings.LogSeverity = LogSeverity.Error;
Cef.Initialize(settings);
}
private void ApplyLanguage()
{
fileMenu.ApplyLanguage();
@@ -490,8 +456,6 @@ namespace mRemoteNG.UI.Forms
Shutdown.Cleanup(_quickConnectToolStrip, _externalToolsToolStrip, _multiSshToolStrip, this);
Cef.Shutdown();
Shutdown.StartUpdate();
Debug.Print("[END] - " + Convert.ToString(DateTime.Now, CultureInfo.InvariantCulture));

View File

@@ -412,7 +412,7 @@
<value />
</setting>
<setting name="ConDefaultRenderingEngine" serializeAs="String">
<value>CEF</value>
<value>EdgeChromium</value>
</setting>
<setting name="InhDefaultRenderingEngine" serializeAs="String">
<value>False</value>

View File

@@ -184,8 +184,6 @@
<Compile Include="Connection\IConnectionInitiator.cs" />
<Compile Include="Connection\IInheritable.cs" />
<Compile Include="Connection\IHasParent.cs" />
<Compile Include="Connection\Protocol\Http\Connection.Protocol.HTTP.DownloadHandler.cs" />
<Compile Include="Connection\Protocol\Http\Connection.Protocol.HTTP.RequestHandler.cs" />
<Compile Include="Connection\Protocol\ProtocolFactory.cs" />
<Compile Include="Connection\Protocol\RDP\AuthenticationLevel.cs" />
<Compile Include="Connection\Protocol\RDP\AzureLoadBalanceInfoEncoder.cs" />
@@ -1319,12 +1317,6 @@
<PackageReference Include="BouncyCastle">
<Version>1.8.9</Version>
</PackageReference>
<PackageReference Include="CefSharp.Common">
<Version>91.1.230</Version>
</PackageReference>
<PackageReference Include="CefSharp.WinForms">
<Version>91.1.230</Version>
</PackageReference>
<PackageReference Include="ConsoleControl">
<Version>1.3.0</Version>
</PackageReference>
@@ -1349,6 +1341,9 @@
<PackageReference Include="log4net">
<Version>2.0.12</Version>
</PackageReference>
<PackageReference Include="Microsoft.Web.WebView2">
<Version>1.0.902.49</Version>
</PackageReference>
<PackageReference Include="MySql.Data">
<Version>8.0.26</Version>
</PackageReference>

File diff suppressed because it is too large Load Diff

View File

@@ -98,7 +98,7 @@ namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers.Csv
UseCredSsp = true,
UseVmId = false,
UseEnhancedMode = false,
RenderingEngine = HTTPBase.RenderingEngine.CEF,
RenderingEngine = HTTPBase.RenderingEngine.EdgeChromium,
RDPAuthenticationLevel = AuthenticationLevel.WarnOnFailedAuth,
Colors = RDPColors.Colors16Bit,
Resolution = RDPResolutions.Res1366x768,

View File

@@ -173,7 +173,7 @@ namespace mRemoteNGTests.Connection
{
var wasCalled = false;
_testAbstractConnectionInfoData.PropertyChanged += (sender, args) => wasCalled = true;
_testAbstractConnectionInfoData.RenderingEngine = HTTPBase.RenderingEngine.CEF;
_testAbstractConnectionInfoData.RenderingEngine = HTTPBase.RenderingEngine.EdgeChromium;
Assert.That(wasCalled, Is.True);
}