diff --git a/CefSharp.OutOfProcess.BrowserProcess/BrowserProcessHandler.cs b/CefSharp.OutOfProcess.BrowserProcess/BrowserProcessHandler.cs index 476650d..2d48a07 100644 --- a/CefSharp.OutOfProcess.BrowserProcess/BrowserProcessHandler.cs +++ b/CefSharp.OutOfProcess.BrowserProcess/BrowserProcessHandler.cs @@ -42,6 +42,7 @@ protected override void OnContextInitialized() _outOfProcessServer.NotifyContextInitialized(threadId, Cef.CefSharpVersion, Cef.CefVersion, Cef.ChromiumVersion); _outOfProcessServer.BeforeDownloadCallback += _outOfProcessServer_BeforeDownloadCallback; _outOfProcessServer.DownloadCallback += _outOfProcessServer_DownloadCallback; + _outOfProcessServer.JsDialogCallback += _outOfProcessServer_JsDialogCallback; } private void _outOfProcessServer_DownloadCallback(object sender, DownloadCallbackDetails e) @@ -54,6 +55,11 @@ private void _outOfProcessServer_BeforeDownloadCallback(object sender, BeforeDow ((DownloadHandlerProxy)GetBrowser(e.BrowserId).DownloadHandler)?.BeforeDownloadCallback(e); } + private void _outOfProcessServer_JsDialogCallback(object sender, JsDialogCallbackDetails e) + { + ((JsDialogHandlerProxy)GetBrowser(e.BrowserId).JsDialogHandler)?.Callback(e); + } + private OutOfProcessChromiumWebBrowser GetBrowser(int id) => _browsers.FirstOrDefault(x => x.Id == id); protected override void Dispose(bool disposing) diff --git a/CefSharp.OutOfProcess.BrowserProcess/CallbackProxies/JsDialogHandlerProxy.cs b/CefSharp.OutOfProcess.BrowserProcess/CallbackProxies/JsDialogHandlerProxy.cs new file mode 100644 index 0000000..bb13baf --- /dev/null +++ b/CefSharp.OutOfProcess.BrowserProcess/CallbackProxies/JsDialogHandlerProxy.cs @@ -0,0 +1,56 @@ +using CefSharp.OutOfProcess.Interface; +using CefSharp.OutOfProcess.Interface.Callbacks; +using System; + +namespace CefSharp.OutOfProcess.BrowserProcess.CallbackProxies +{ + internal sealed class JsDialogHandlerProxy : CallbackProxyBase, IJsDialogHandler + { + public JsDialogHandlerProxy(IOutOfProcessHostRpc host) + : base(host) + { + + } + + public void Callback(JsDialogCallbackDetails details) + { + var cb = (CefSharp.OutOfProcess.Interface.Callbacks.IJsDialogCallback)GetCallback(details.CallbackId); + + if (details.UserInput != string.Empty) + { + cb.Continue(details.Success, details.UserInput); + } + else + { + cb.Continue(details.Success); + } + } + + public bool OnBeforeUnloadDialog(IWebBrowser chromiumWebBrowser, IBrowser browser, string messageText, bool isReload, IJsDialogCallback callback) + { + var result = host.OnBeforeUnloadDialog(((OutOfProcessChromiumWebBrowser)chromiumWebBrowser).Id, messageText, isReload, CreateCallback(callback)); + return result; + } + + public void OnDialogClosed(IWebBrowser chromiumWebBrowser, IBrowser browser) + { + host.OnDialogClosed(((OutOfProcessChromiumWebBrowser)chromiumWebBrowser).Id); + } + + public bool OnJSDialog(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, CefJsDialogType dialogType, string messageText, string defaultPromptText, IJsDialogCallback callback, ref bool suppressMessage) + { + var result = host.OnJSDialog(((OutOfProcessChromiumWebBrowser)chromiumWebBrowser).Id, originUrl, ParseEnum(Enum.GetName(typeof(CefJsDialogType), dialogType)), messageText, defaultPromptText, CreateCallback(callback), ref suppressMessage); + return result; + } + + public void OnResetDialogState(IWebBrowser chromiumWebBrowser, IBrowser browser) + { + host.OnResetDialogState(((OutOfProcessChromiumWebBrowser)chromiumWebBrowser).Id); + } + + public static T ParseEnum(string value) + { + return (T)Enum.Parse(typeof(T), value, true); + } + } +} \ No newline at end of file diff --git a/CefSharp.OutOfProcess.Core/CallbackProxies/JsDialogCallbackProxy.cs b/CefSharp.OutOfProcess.Core/CallbackProxies/JsDialogCallbackProxy.cs new file mode 100644 index 0000000..7af23ac --- /dev/null +++ b/CefSharp.OutOfProcess.Core/CallbackProxies/JsDialogCallbackProxy.cs @@ -0,0 +1,34 @@ +namespace CefSharp.OutOfProcess +{ + using CefSharp.OutOfProcess.Interface.Callbacks; + using CefSharp.OutOfProcess.Internal; + + internal sealed class JsDialogCallbackProxy : CallbackProxyBase, IJsDialogCallback + { + public JsDialogCallbackProxy(OutOfProcessHost outOfProcessHost, int callback, IChromiumWebBrowserInternal chromiumWebBrowser) + : base(outOfProcessHost, callback, chromiumWebBrowser) + { + } + + void IJsDialogCallback.Continue(bool success, string userInput) + { + outOfProcessHost.InvokeJsDialogCallback(new JsDialogCallbackDetails() + { + CallbackId = callback, + BrowserId = chromiumWebBrowser.Id, + Success = success, + UserInput = userInput, + }); + } + + void IJsDialogCallback.Continue(bool success) + { + outOfProcessHost.InvokeJsDialogCallback(new JsDialogCallbackDetails() + { + CallbackId = callback, + BrowserId = chromiumWebBrowser.Id, + Success = success, + }); + } + } +} \ No newline at end of file diff --git a/CefSharp.OutOfProcess.Core/Handler/IJsDialogHandler.cs b/CefSharp.OutOfProcess.Core/Handler/IJsDialogHandler.cs new file mode 100644 index 0000000..b224c67 --- /dev/null +++ b/CefSharp.OutOfProcess.Core/Handler/IJsDialogHandler.cs @@ -0,0 +1,16 @@ +namespace CefSharp.OutOfProcess.Handler +{ + using CefSharp.OutOfProcess.Interface.Callbacks; + + public interface IJsDialogHandler + { + + bool OnJSDialog(IChromiumWebBrowser chromiumWebBrowser, string originUrl, CefJsDialogType dialogType, string messageText, string defaultPromptText, IJsDialogCallback callback, ref bool suppressMessage); + + bool OnBeforeUnloadDialog(IChromiumWebBrowser chromiumWebBrowser, string messageText, bool isReload, IJsDialogCallback callback); + + void OnResetDialogState(IChromiumWebBrowser chromiumWebBrowser); + + void OnDialogClosed(IChromiumWebBrowser chromiumWebBrowser); + } +} \ No newline at end of file diff --git a/CefSharp.OutOfProcess.Core/IChromiumWebBrowser.cs b/CefSharp.OutOfProcess.Core/IChromiumWebBrowser.cs index a3d7d7a..1fb4b18 100644 --- a/CefSharp.OutOfProcess.Core/IChromiumWebBrowser.cs +++ b/CefSharp.OutOfProcess.Core/IChromiumWebBrowser.cs @@ -205,5 +205,7 @@ public interface IChromiumWebBrowser : IDisposable Task GoForwardAsync(NavigationOptions options = null); Handler.IDownloadHandler DownloadHandler { get; set; } + + Handler.IJsDialogHandler JsDialogHandler { get; set; } } } diff --git a/CefSharp.OutOfProcess.Core/OutOfProcessHost.cs b/CefSharp.OutOfProcess.Core/OutOfProcessHost.cs index 8880188..960ca67 100644 --- a/CefSharp.OutOfProcess.Core/OutOfProcessHost.cs +++ b/CefSharp.OutOfProcess.Core/OutOfProcessHost.cs @@ -42,6 +42,8 @@ private OutOfProcessHost(string outOfProcessHostExePath, string cachePath = null public event EventHandler BeforeDownloadCallback; + public event EventHandler JsDialogCallback; + /// /// UI Thread assocuated with this @@ -287,5 +289,43 @@ Task IOutOfProcessHostRpc.OnCanDownloadAsync(int browserId, string url, st internal void InvokeBeforeDownloadCallback(BeforeDownloadCallbackDetails callbackDetails) => BeforeDownloadCallback.Invoke(this, callbackDetails); internal void InvokeDownloadCallback(DownloadCallbackDetails callbackDetails) => DownloadCallback.Invoke(this, callbackDetails); + + internal void InvokeJsDialogCallback(JsDialogCallbackDetails callbackDetails) => JsDialogCallback.Invoke(this, callbackDetails); + + public bool OnBeforeUnloadDialog(int browserId, string messageText, bool isReload, int callback) + { + if (GetBrowser(browserId) is IChromiumWebBrowserInternal chromiumWebBrowser) + { + return chromiumWebBrowser?.JsDialogHandler?.OnBeforeUnloadDialog(chromiumWebBrowser, messageText, isReload, new JsDialogCallbackProxy(this, callback, chromiumWebBrowser)) ?? false; + } + + return false; + } + + public void OnDialogClosed(int browserId) + { + if (GetBrowser(browserId) is IChromiumWebBrowserInternal chromiumWebBrowser) + { + chromiumWebBrowser?.JsDialogHandler?.OnDialogClosed(chromiumWebBrowser); + } + } + + public bool OnJSDialog(int browserId, string originUrl, CefJsDialogType dialogType, string messageText, string defaultPromptText, int callback, ref bool suppressMessage) + { + if (GetBrowser(browserId) is IChromiumWebBrowserInternal chromiumWebBrowser) + { + return chromiumWebBrowser?.JsDialogHandler?.OnJSDialog(chromiumWebBrowser,originUrl, dialogType, messageText,defaultPromptText,new JsDialogCallbackProxy(this, callback,chromiumWebBrowser), ref suppressMessage) ?? false; + } + + return false; + } + + public void OnResetDialogState(int browserId) + { + if (GetBrowser(browserId) is IChromiumWebBrowserInternal chromiumWebBrowser) + { + chromiumWebBrowser?.JsDialogHandler?.OnResetDialogState(chromiumWebBrowser); + } + } } } diff --git a/CefSharp.OutOfProcess.Interface/Callbacks/CefJSDialogType.cs b/CefSharp.OutOfProcess.Interface/Callbacks/CefJSDialogType.cs new file mode 100644 index 0000000..a092c35 --- /dev/null +++ b/CefSharp.OutOfProcess.Interface/Callbacks/CefJSDialogType.cs @@ -0,0 +1,21 @@ +namespace CefSharp.OutOfProcess.Interface.Callbacks +{ + /// + /// Supported JavaScript dialog types. + /// + public enum CefJsDialogType + { + /// + /// Alert Dialog + /// + Alert = 0, + /// + /// Confirm Dialog + /// + Confirm, + /// + /// Prompt Dialog + /// + Prompt + } +} \ No newline at end of file diff --git a/CefSharp.OutOfProcess.Interface/Callbacks/IJsDialogCallback.cs b/CefSharp.OutOfProcess.Interface/Callbacks/IJsDialogCallback.cs new file mode 100644 index 0000000..02f7bcd --- /dev/null +++ b/CefSharp.OutOfProcess.Interface/Callbacks/IJsDialogCallback.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CefSharp.OutOfProcess.Interface.Callbacks +{ + public interface IJsDialogCallback : IDisposable + { + bool IsDisposed { get; } + void Continue(bool success); + void Continue(bool success, string userInput); + } +} diff --git a/CefSharp.OutOfProcess.Interface/Callbacks/JsDialogCallbackDetails.cs b/CefSharp.OutOfProcess.Interface/Callbacks/JsDialogCallbackDetails.cs new file mode 100644 index 0000000..1008dd6 --- /dev/null +++ b/CefSharp.OutOfProcess.Interface/Callbacks/JsDialogCallbackDetails.cs @@ -0,0 +1,9 @@ +namespace CefSharp.OutOfProcess.Interface.Callbacks +{ + public class JsDialogCallbackDetails : CallbackDetails + { + public string UserInput { get; set; } + + public bool Success { get; set; } + } +} \ No newline at end of file diff --git a/CefSharp.OutOfProcess.Interface/IOutOfProcessHostRpc.cs b/CefSharp.OutOfProcess.Interface/IOutOfProcessHostRpc.cs index 8388020..b630a96 100644 --- a/CefSharp.OutOfProcess.Interface/IOutOfProcessHostRpc.cs +++ b/CefSharp.OutOfProcess.Interface/IOutOfProcessHostRpc.cs @@ -89,5 +89,14 @@ public interface IOutOfProcessHostRpc event EventHandler BeforeDownloadCallback; event EventHandler DownloadCallback; + event EventHandler JsDialogCallback; + + bool OnBeforeUnloadDialog(int browserId, string messageText, bool isReload, int callback); + + void OnDialogClosed(int browserId); + + bool OnJSDialog(int browserId, string originUrl, CefJsDialogType dialogType, string messageText, string defaultPromptText, int callback, ref bool suppressMessage); + + void OnResetDialogState(int browserId); } } diff --git a/CefSharp.OutOfProcess.WinForms/ChromiumWebBrowser.cs b/CefSharp.OutOfProcess.WinForms/ChromiumWebBrowser.cs index 282af83..11f1bc6 100644 --- a/CefSharp.OutOfProcess.WinForms/ChromiumWebBrowser.cs +++ b/CefSharp.OutOfProcess.WinForms/ChromiumWebBrowser.cs @@ -123,6 +123,8 @@ public IDevToolsContext DevToolsContext Handler.IDownloadHandler IChromiumWebBrowser.DownloadHandler { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + Handler.IJsDialogHandler IChromiumWebBrowser.JsDialogHandler { get; set; } + /// protected override void OnHandleCreated(EventArgs e) { diff --git a/CefSharp.OutOfProcess.Wpf.HwndHost/ChromiumWebBrowser.cs b/CefSharp.OutOfProcess.Wpf.HwndHost/ChromiumWebBrowser.cs index 58dd793..a2eb2f1 100644 --- a/CefSharp.OutOfProcess.Wpf.HwndHost/ChromiumWebBrowser.cs +++ b/CefSharp.OutOfProcess.Wpf.HwndHost/ChromiumWebBrowser.cs @@ -1066,6 +1066,9 @@ public IChromiumWebBrowser WebBrowser Handler.IDownloadHandler IChromiumWebBrowser.DownloadHandler { get; set; } + + Handler.IJsDialogHandler IChromiumWebBrowser.JsDialogHandler { get; set; } + /// /// The WebBrowser property ///