Skip to content

Commit 7c2bead

Browse files
committed
add download handler
1 parent cda6ce7 commit 7c2bead

19 files changed

Lines changed: 388 additions & 38 deletions

CefSharp.OutOfProcess.BrowserProcess/BrowserProcessHandler.cs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
using System.Diagnostics;
88
using CefSharp.OutOfProcess.Interface;
99
using System.Threading.Tasks;
10+
using CefSharp.OutOfProcess.BrowserProcess.CallbackProxies;
11+
using CefSharp.OutOfProcess.Interface.Callbacks;
1012

1113
namespace CefSharp.OutOfProcess.BrowserProcess
1214
{
@@ -38,8 +40,22 @@ protected override void OnContextInitialized()
3840
var threadId = Kernel32.GetCurrentThreadId();
3941

4042
_outOfProcessServer.NotifyContextInitialized(threadId, Cef.CefSharpVersion, Cef.CefVersion, Cef.ChromiumVersion);
43+
_outOfProcessServer.BeforeDownloadCallback += _outOfProcessServer_BeforeDownloadCallback;
44+
_outOfProcessServer.DownloadCallback += _outOfProcessServer_DownloadCallback;
4145
}
4246

47+
private void _outOfProcessServer_DownloadCallback(object sender, DownloadCallbackDetails e)
48+
{
49+
((DownloadHandlerProxy)GetBrowser(e.BrowserId).DownloadHandler)?.DownloadCallback(e);
50+
}
51+
52+
private void _outOfProcessServer_BeforeDownloadCallback(object sender, BeforeDownloadCallbackDetails e)
53+
{
54+
((DownloadHandlerProxy)GetBrowser(e.BrowserId).DownloadHandler)?.BeforeDownloadCallback(e);
55+
}
56+
57+
private OutOfProcessChromiumWebBrowser GetBrowser(int id) => _browsers.FirstOrDefault(x => x.Id == id);
58+
4359
protected override void Dispose(bool disposing)
4460
{
4561
base.Dispose(disposing);
@@ -69,9 +85,7 @@ Task IOutOfProcessClientRpc.SendDevToolsMessage(int browserId, string message)
6985
{
7086
return CefThread.ExecuteOnUiThread(() =>
7187
{
72-
var browser = _browsers.FirstOrDefault(x => x.Id == browserId);
73-
74-
browser?.GetBrowserHost().SendDevToolsMessage(message);
88+
GetBrowser(browserId).GetBrowserHost().SendDevToolsMessage(message);
7589

7690
return true;
7791
});
@@ -120,9 +134,7 @@ void IOutOfProcessClientRpc.NotifyMoveOrResizeStarted(int browserId)
120134

121135
void IOutOfProcessClientRpc.SetFocus(int browserId, bool focus)
122136
{
123-
var browser = _browsers.FirstOrDefault(x => x.Id == browserId);
124-
125-
browser?.GetBrowserHost().SetFocus(focus);
137+
GetBrowser(browserId).GetBrowserHost().SetFocus(focus);
126138
}
127139
}
128140
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using CefSharp.OutOfProcess.Interface;
4+
5+
namespace CefSharp.OutOfProcess.BrowserProcess.CallbackProxies
6+
{
7+
internal class CallbackProxyBase<T> : IDisposable
8+
{
9+
private int id = 0;
10+
private readonly Dictionary<int, T> callbacks = new Dictionary<int, T>();
11+
private protected readonly IOutOfProcessHostRpc host;
12+
13+
public CallbackProxyBase(IOutOfProcessHostRpc host)
14+
{
15+
this.host = host ?? throw new ArgumentNullException(nameof(host));
16+
}
17+
18+
protected int CreateCallback(T callback)
19+
{
20+
int lid = id++;
21+
callbacks.Add(lid, callback);
22+
return lid;
23+
}
24+
25+
protected T GetCallback(int id)
26+
{
27+
T cb = callbacks[id];
28+
callbacks.Remove(id);
29+
return cb;
30+
}
31+
32+
public void Dispose()
33+
{
34+
foreach (var cbs in callbacks)
35+
{
36+
if (cbs.Value is IDisposable d)
37+
{
38+
d.Dispose();
39+
}
40+
}
41+
42+
callbacks.Clear();
43+
}
44+
}
45+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
namespace CefSharp.OutOfProcess.BrowserProcess.CallbackProxies
2+
{
3+
using System.Diagnostics;
4+
using CefSharp;
5+
using CefSharp.OutOfProcess.Interface;
6+
using CefSharp.OutOfProcess.Interface.Callbacks;
7+
8+
internal class DownloadHandlerProxy : CallbackProxyBase<object>, IDownloadHandler
9+
{
10+
public DownloadHandlerProxy(IOutOfProcessHostRpc host)
11+
: base(host)
12+
{
13+
}
14+
15+
public void BeforeDownloadCallback(BeforeDownloadCallbackDetails details)
16+
{
17+
Debugger.Launch();
18+
((IBeforeDownloadCallback)GetCallback(details.CallbackId)).Continue(details.DownloadPath, details.ShowDialog);
19+
}
20+
21+
public void DownloadCallback(DownloadCallbackDetails details)
22+
{
23+
var cb = (IDownloadItemCallback)GetCallback(details.CallbackId);
24+
if (details.Cancel)
25+
{
26+
cb.Cancel();
27+
}
28+
else if (details.Pause)
29+
{
30+
cb.Pause();
31+
}
32+
else if (details.Resume)
33+
{
34+
cb.Resume();
35+
}
36+
}
37+
38+
bool IDownloadHandler.CanDownload(IWebBrowser chromiumWebBrowser, IBrowser browser, string url, string requestMethod)
39+
{
40+
return host.OnCanDownloadAsync(((OutOfProcessChromiumWebBrowser)chromiumWebBrowser).Id, url, requestMethod).Result;
41+
}
42+
43+
void IDownloadHandler.OnBeforeDownload(IWebBrowser chromiumWebBrowser, IBrowser browser, CefSharp.DownloadItem downloadItem, IBeforeDownloadCallback callback)
44+
{
45+
host.OnBeforeDownload(((OutOfProcessChromiumWebBrowser)chromiumWebBrowser).Id, Convert(downloadItem), CreateCallback(callback));
46+
}
47+
48+
void IDownloadHandler.OnDownloadUpdated(IWebBrowser chromiumWebBrowser, IBrowser browser, CefSharp.DownloadItem downloadItem, IDownloadItemCallback callback)
49+
{
50+
host.OnDownloadUpdated(((OutOfProcessChromiumWebBrowser)chromiumWebBrowser).Id, Convert(downloadItem), CreateCallback(callback));
51+
}
52+
53+
private static CefSharp.OutOfProcess.Interface.Callbacks.DownloadItem Convert(CefSharp.DownloadItem item) => new CefSharp.OutOfProcess.Interface.Callbacks.DownloadItem()
54+
{
55+
SuggestedFileName = item.SuggestedFileName,
56+
CurrentSpeed = item.CurrentSpeed,
57+
Id = item.Id,
58+
ContentDisposition = item.ContentDisposition,
59+
EndTime = item.EndTime,
60+
FullPath = item.FullPath,
61+
IsCancelled = item.IsCancelled,
62+
IsComplete = item.IsComplete,
63+
IsInProgress = item.IsInProgress,
64+
IsValid = item.IsValid,
65+
MimeType = item.MimeType,
66+
OriginalUrl = item.OriginalUrl,
67+
PercentComplete = item.PercentComplete,
68+
ReceivedBytes = item.ReceivedBytes,
69+
StartTime = item.StartTime,
70+
TotalBytes = item.TotalBytes,
71+
Url = item.Url,
72+
};
73+
}
74+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
namespace CefSharp.OutOfProcess
2+
{
3+
using System;
4+
using CefSharp.OutOfProcess.Internal;
5+
6+
internal class CallbackProxyBase : IDisposable
7+
{
8+
private protected readonly OutOfProcessHost outOfProcessHost;
9+
private protected readonly int callback;
10+
private protected readonly IChromiumWebBrowserInternal chromiumWebBrowser;
11+
private bool disposedValue;
12+
13+
public CallbackProxyBase(OutOfProcessHost outOfProcessHost, int callback, IChromiumWebBrowserInternal chromiumWebBrowser)
14+
{
15+
this.chromiumWebBrowser = chromiumWebBrowser;
16+
this.outOfProcessHost = outOfProcessHost;
17+
this.callback = callback;
18+
}
19+
20+
public bool IsDisposed => disposedValue;
21+
22+
protected virtual void Dispose(bool disposing)
23+
{
24+
if (!disposedValue)
25+
{
26+
if (disposing)
27+
{
28+
// TODO: dispose managed state (managed objects)
29+
}
30+
31+
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
32+
// TODO: set large fields to null
33+
disposedValue = true;
34+
}
35+
}
36+
37+
void IDisposable.Dispose()
38+
{
39+
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
40+
Dispose(disposing: true);
41+
GC.SuppressFinalize(this);
42+
}
43+
}
44+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
namespace CefSharp.OutOfProcess
2+
{
3+
using CefSharp.OutOfProcess.Interface.Callbacks;
4+
using CefSharp.OutOfProcess.Internal;
5+
6+
internal sealed class DownloadCallbackProxy : CallbackProxyBase, IBeforeDownloadCallback, IDownloadItemCallback
7+
{
8+
public DownloadCallbackProxy(OutOfProcessHost outOfProcessHost, int callback, IChromiumWebBrowserInternal chromiumWebBrowser)
9+
: base(outOfProcessHost, callback, chromiumWebBrowser)
10+
{
11+
}
12+
13+
void IDownloadItemCallback.Cancel()
14+
{
15+
outOfProcessHost.InvokeDownloadCallback(new DownloadCallbackDetails()
16+
{
17+
CallbackId = callback,
18+
BrowserId = chromiumWebBrowser.Id,
19+
Cancel = true,
20+
});
21+
}
22+
23+
void IBeforeDownloadCallback.Continue(string downloadPath, bool showDialog)
24+
{
25+
outOfProcessHost.InvokeBeforeDownloadCallback(new BeforeDownloadCallbackDetails()
26+
{
27+
CallbackId = callback,
28+
BrowserId = chromiumWebBrowser.Id,
29+
DownloadPath = downloadPath,
30+
ShowDialog = showDialog,
31+
});
32+
}
33+
34+
void IDownloadItemCallback.Pause()
35+
{
36+
outOfProcessHost.InvokeDownloadCallback(new DownloadCallbackDetails()
37+
{
38+
CallbackId = callback,
39+
BrowserId = chromiumWebBrowser.Id,
40+
Pause = true,
41+
});
42+
}
43+
44+
void IDownloadItemCallback.Resume()
45+
{
46+
outOfProcessHost.InvokeDownloadCallback(new DownloadCallbackDetails()
47+
{
48+
CallbackId = callback,
49+
BrowserId = chromiumWebBrowser.Id,
50+
Resume = true,
51+
});
52+
}
53+
}
54+
}

CefSharp.OutOfProcess.Core/CefSharp.OutOfProcess.Core.csproj

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>netstandard2.0</TargetFramework>
4+
<TargetFramework>net462</TargetFramework>
5+
<PlatformTarget>AnyCPU</PlatformTarget>
56
<RootNamespace>CefSharp.OutOfProcess</RootNamespace>
67
</PropertyGroup>
78

89
<ItemGroup>
910
<PackageReference Include="PInvoke.Kernel32" Version="0.7.104" />
1011
<PackageReference Include="PInvoke.User32" Version="0.7.104" />
1112
<PackageReference Include="StreamJsonRpc" Version="2.11.35" />
13+
<PackageReference Include="CefSharp.Common" Version="109.1.110" />
14+
1215
<ProjectReference Include="..\CefSharp.OutOfProcess.Interface\CefSharp.OutOfProcess.Interface.csproj" />
13-
1416
<ProjectReference Include="..\CefSharp.Dom\lib\PuppeteerSharp\CefSharp.Dom.OutOfProcess.csproj" />
1517
</ItemGroup>
1618

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace CefSharp.OutOfProcess.Handler
2+
{
3+
public interface IDownloadHandler
4+
{
5+
bool CanDownload(IChromiumWebBrowser chromiumWebBrowser, string url, string requestMethod);
6+
7+
void OnBeforeDownload(IChromiumWebBrowser chromiumWebBrowser, CefSharp.OutOfProcess.Interface.Callbacks.DownloadItem downloadItem, IBeforeDownloadCallback callback);
8+
9+
void OnDownloadUpdated(IChromiumWebBrowser chromiumWebBrowser, CefSharp.OutOfProcess.Interface.Callbacks.DownloadItem downloadItem, IDownloadItemCallback callback);
10+
}
11+
}

CefSharp.OutOfProcess.Core/IChromiumWebBrowser.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,5 +203,7 @@ public interface IChromiumWebBrowser : IDisposable
203203
/// the navigation will resolve with the response of the last redirect. If can not go forward, resolves to null.</returns>
204204
/// <param name="options">Navigation parameters.</param>
205205
Task<Response> GoForwardAsync(NavigationOptions options = null);
206+
207+
Handler.IDownloadHandler DownloadHandler { get; set; }
206208
}
207209
}

CefSharp.OutOfProcess.Core/OutOfProcessConnectionTransport.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public class OutOfProcessConnectionTransport : IConnectionTransport
1212

1313
public event EventHandler<MessageReceivedEventArgs> MessageReceived;
1414
public event EventHandler<MessageErrorEventArgs> MessageError;
15+
public event EventHandler Disconnected;
1516

1617
public OutOfProcessConnectionTransport(int browserId, OutOfProcessHost outOfProcessHost)
1718
{

0 commit comments

Comments
 (0)