Skip to content

Commit bec06b2

Browse files
authored
Add Fluent DownloadHandler (#3576)
* Core - Add Fluent DownloadHandler implementation and IFrame.DownloadUrlAsync Resolves #3550
1 parent 4ebe7de commit bec06b2

12 files changed

+774
-6
lines changed

CefSharp.Core/CefSharp.Core.csproj

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
33
<Import Project="..\packages\GitLink.3.1.0\build\GitLink.props" Condition="Exists('..\packages\GitLink.3.1.0\build\GitLink.props')" />
44
<Import Project="..\packages\Microsoft.Net.Compilers.2.4.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.2.4.0\build\Microsoft.Net.Compilers.props')" />
@@ -55,6 +55,10 @@
5555
<Compile Include="Cef.cs" />
5656
<Compile Include="CefSettingsBase.cs" />
5757
<Compile Include="DragData.cs" />
58+
<Compile Include="Fluent\DownloadHandler.cs" />
59+
<Compile Include="Fluent\DownloadHandlerBuilder.cs" />
60+
<Compile Include="Fluent\UrlRequestClient.cs" />
61+
<Compile Include="Fluent\UrlRequestClientBuilder.cs" />
5862
<Compile Include="ManagedCefBrowserAdapter.cs" />
5963
<Compile Include="NativeMethodWrapper.cs" />
6064
<Compile Include="PostData.cs" />
@@ -85,4 +89,4 @@
8589
<ItemGroup />
8690
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
8791
<Import Project="..\packages\GitLink.3.1.0\build\GitLink.targets" Condition="Exists('..\packages\GitLink.3.1.0\build\GitLink.targets')" />
88-
</Project>
92+
</Project>
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Copyright © 2021 The CefSharp Authors. All rights reserved.
2+
//
3+
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
4+
5+
using System.IO;
6+
7+
namespace CefSharp.Fluent
8+
{
9+
/// <summary>
10+
/// Called before a download begins.
11+
/// </summary>
12+
/// <param name="chromiumWebBrowser">the ChromiumWebBrowser control</param>
13+
/// <param name="browser">The browser instance</param>
14+
/// <param name="downloadItem">Represents the file being downloaded.</param>
15+
/// <param name="callback">Callback interface used to asynchronously continue a download.</param>
16+
public delegate void OnBeforeDownloadDelegate(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback);
17+
18+
/// <summary>
19+
/// Called when a download's status or progress information has been updated. This may be called multiple times before and after <see cref="OnBeforeDownload"/>.
20+
/// </summary>
21+
/// <param name="chromiumWebBrowser">the ChromiumWebBrowser control</param>
22+
/// <param name="browser">The browser instance</param>
23+
/// <param name="downloadItem">Represents the file being downloaded.</param>
24+
/// <param name="callback">The callback used to Cancel/Pause/Resume the process</param>
25+
public delegate void OnDownloadUpdatedDelegate(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback);
26+
27+
/// <summary>
28+
/// A <see cref="IDownloadHandler"/> implementation used by <see cref="DownloadHandlerBuilder"/>
29+
/// to provide a fluent means of creating a <see cref="IDownloadHandler"/>.
30+
/// </summary>
31+
public class DownloadHandler : Handler.DownloadHandler
32+
{
33+
private OnBeforeDownloadDelegate onBeforeDownload;
34+
private OnDownloadUpdatedDelegate onDownloadUpdated;
35+
36+
/// <summary>
37+
/// Create a new DownloadHandler Builder
38+
/// </summary>
39+
/// <returns>Fluent DownloadHandler Builder</returns>
40+
public static DownloadHandlerBuilder Create()
41+
{
42+
return new DownloadHandlerBuilder();
43+
}
44+
45+
/// <summary>
46+
/// Creates a new <see cref="IDownloadHandler"/> instances
47+
/// where all downloads are automatically downloaded to the specified folder.
48+
/// No dialog is dispolayed to the user.
49+
/// </summary>
50+
/// <param name="folder">folder where files are download.</param>
51+
/// <param name="downloadUpdated">optional delegate for download updates, track progress, completion etc.</param>
52+
/// <returns><see cref="IDownloadHandler"/> instance.</returns>
53+
public static IDownloadHandler UseFolder(string folder, OnDownloadUpdatedDelegate downloadUpdated = null)
54+
{
55+
return Create()
56+
.OnBeforeDownload((chromiumWebBrowser, browser, item, callback) =>
57+
{
58+
using (callback)
59+
{
60+
var path = Path.Combine(folder, item.SuggestedFileName);
61+
62+
callback.Continue(path, showDialog: false);
63+
}
64+
})
65+
.OnDownloadUpdated(downloadUpdated)
66+
.Build();
67+
}
68+
69+
/// <summary>
70+
/// Creates a new <see cref="IDownloadHandler"/> instances
71+
/// where a default "Save As" dialog is displayed to the user.
72+
/// </summary>
73+
/// <param name="downloadUpdated">optional delegate for download updates, track progress, completion etc.</param>
74+
/// <returns><see cref="IDownloadHandler"/> instance.</returns>
75+
public static IDownloadHandler AskUser(OnDownloadUpdatedDelegate downloadUpdated = null)
76+
{
77+
return Create()
78+
.OnBeforeDownload((chromiumWebBrowser, browser, item, callback) =>
79+
{
80+
using (callback)
81+
{
82+
callback.Continue("", showDialog: true);
83+
}
84+
})
85+
.OnDownloadUpdated(downloadUpdated)
86+
.Build();
87+
}
88+
89+
/// <summary>
90+
/// Use <see cref="Create"/> to create a new instance of the fluent builder
91+
/// </summary>
92+
internal DownloadHandler()
93+
{
94+
95+
}
96+
97+
internal void SetOnBeforeDownload(OnBeforeDownloadDelegate action)
98+
{
99+
onBeforeDownload = action;
100+
}
101+
102+
internal void SetOnDownloadUpdated(OnDownloadUpdatedDelegate action)
103+
{
104+
onDownloadUpdated = action;
105+
}
106+
107+
/// <inheritdoc/>
108+
protected override void OnBeforeDownload(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback)
109+
{
110+
onBeforeDownload?.Invoke(chromiumWebBrowser, browser, downloadItem, callback);
111+
}
112+
113+
/// <inheritdoc/>
114+
protected override void OnDownloadUpdated(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback)
115+
{
116+
onDownloadUpdated?.Invoke(chromiumWebBrowser, browser, downloadItem, callback);
117+
}
118+
}
119+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright © 2021 The CefSharp Authors. All rights reserved.
2+
//
3+
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
4+
5+
namespace CefSharp.Fluent
6+
{
7+
/// <summary>
8+
/// Fluent DownloadHandler Builder
9+
/// </summary>
10+
public class DownloadHandlerBuilder
11+
{
12+
private readonly DownloadHandler handler = new DownloadHandler();
13+
14+
/// <summary>
15+
/// See <see cref="IDownloadHandler.OnBeforeDownload(IWebBrowser, IBrowser, DownloadItem, IBeforeDownloadCallback)"/> for details.
16+
/// </summary>
17+
/// <param name="action">Action to be executed when <see cref="IDownloadHandler.OnBeforeDownload(IWebBrowser, IBrowser, DownloadItem, IBeforeDownloadCallback)"/>
18+
/// is called</param>
19+
/// <returns>
20+
/// Fluent Builder, call <see cref="Build"/> to create
21+
/// a new <see cref="IDownloadHandler"/> instance
22+
/// </returns>
23+
public DownloadHandlerBuilder OnBeforeDownload(OnBeforeDownloadDelegate action)
24+
{
25+
handler.SetOnBeforeDownload(action);
26+
27+
return this;
28+
}
29+
30+
/// <summary>
31+
/// See <see cref="IDownloadHandler.OnDownloadUpdated(IWebBrowser, IBrowser, DownloadItem, IDownloadItemCallback)"/> for details.
32+
/// </summary>
33+
/// <param name="action">Action to be executed when <see cref="IDownloadHandler.OnDownloadUpdated(IWebBrowser, IBrowser, DownloadItem, IDownloadItemCallback)"/>
34+
/// is called</param>
35+
/// <returns>
36+
/// Fluent Builder, call <see cref="DownloadHandlerBuilder.Build"/> to create
37+
/// a new <see cref="IDownloadHandler"/> instance
38+
/// </returns>
39+
public DownloadHandlerBuilder OnDownloadUpdated(OnDownloadUpdatedDelegate action)
40+
{
41+
handler.SetOnDownloadUpdated(action);
42+
43+
return this;
44+
}
45+
46+
/// <summary>
47+
/// Create a <see cref="IDownloadHandler"/> instance
48+
/// </summary>
49+
/// <returns> a <see cref="IDownloadHandler"/> instance</returns>
50+
public IDownloadHandler Build()
51+
{
52+
return handler;
53+
}
54+
}
55+
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// Copyright © 2021 The CefSharp Authors. All rights reserved.
2+
//
3+
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
4+
5+
using System.IO;
6+
7+
namespace CefSharp.Fluent
8+
{
9+
/// <summary>
10+
/// Called on the CEF IO thread when the browser needs credentials from the user.
11+
/// This method will only be called for requests initiated from the browser process.
12+
/// </summary>
13+
/// <param name="isProxy">indicates whether the host is a proxy server.</param>
14+
/// <param name="host">the hostname.</param>
15+
/// <param name="port">the port number.</param>
16+
/// <param name="realm">realm</param>
17+
/// <param name="scheme">scheme</param>
18+
/// <param name="callback">is a callback for authentication information</param>
19+
/// <returns>
20+
/// Return true to continue the request and call <see cref="IAuthCallback.Continue(string, string)"/> when the authentication information is available.
21+
/// If the request has an associated browser/frame then returning false will result in a call to <see cref="IRequestHandler.GetAuthCredentials"/>
22+
/// on the <see cref="IRequestHandler"/> associated with that browser, if any.
23+
/// Otherwise, returning false will cancel the request immediately.
24+
/// </returns>
25+
public delegate bool GetAuthCredentialsDelegate(bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback);
26+
27+
/// <summary>
28+
/// Called when some part of the response is read. This method will not be called if the <see cref="UrlRequestFlags.NoDownloadData"/> flag is set on the request.
29+
/// </summary>
30+
/// <param name="request">request</param>
31+
/// <param name="data">A stream containing the bytes received since the last call. Cannot be used outside the scope of this method. </param>
32+
public delegate void OnDownloadDataDelegate(IUrlRequest request, Stream data);
33+
34+
/// <summary>
35+
/// Notifies the client of download progress.
36+
/// </summary>
37+
/// <param name="request">request</param>
38+
/// <param name="current">denotes the number of bytes received up to the call </param>
39+
/// <param name="total">is the expected total size of the response (or -1 if not determined).</param>
40+
public delegate void OnDownloadProgressDelegate(IUrlRequest request, long current, long total);
41+
42+
/// <summary>
43+
/// Notifies the client that the request has completed.
44+
/// Use the <see cref="IUrlRequest.RequestStatus"/> property to determine if the
45+
/// request was successful or not.
46+
/// </summary>
47+
/// <param name="request">request</param>
48+
public delegate void OnRequestCompleteDelegate(IUrlRequest request);
49+
50+
/// <summary>
51+
/// Notifies the client of upload progress.
52+
/// This method will only be called if the UR_FLAG_REPORT_UPLOAD_PROGRESS flag is set on the request.
53+
/// </summary>
54+
/// <param name="request">request</param>
55+
/// <param name="current">denotes the number of bytes sent so far.</param>
56+
/// <param name="total">is the total size of uploading data (or -1 if chunked upload is enabled).</param>
57+
public delegate void OnUploadProgressDelegate(IUrlRequest request, long current, long total);
58+
59+
/// <summary>
60+
/// Fluent UrlRequestClient
61+
/// </summary>
62+
public class UrlRequestClient : CefSharp.UrlRequestClient
63+
{
64+
private GetAuthCredentialsDelegate getAuthCredentials;
65+
private OnDownloadDataDelegate onDownloadData;
66+
private OnDownloadProgressDelegate onDownloadProgress;
67+
private OnRequestCompleteDelegate onRequestComplete;
68+
private OnUploadProgressDelegate onUploadProgress;
69+
70+
/// <summary>
71+
/// Create a new UrlRequestClient Builder
72+
/// </summary>
73+
/// <returns>Fluent UrlRequestClient Builder</returns>
74+
public static UrlRequestClientBuilder Create()
75+
{
76+
return new UrlRequestClientBuilder();
77+
}
78+
79+
/// <summary>
80+
/// Use <see cref="Create"/> to create a new instance of the fluent builder
81+
/// </summary>
82+
internal UrlRequestClient()
83+
{
84+
85+
}
86+
87+
internal void SetGetAuthCredentials(GetAuthCredentialsDelegate func)
88+
{
89+
getAuthCredentials = func;
90+
}
91+
92+
internal void SetOnDownloadData(OnDownloadDataDelegate action)
93+
{
94+
onDownloadData = action;
95+
}
96+
97+
internal void SetOnDownloadProgress(OnDownloadProgressDelegate action)
98+
{
99+
onDownloadProgress = action;
100+
}
101+
102+
internal void SetOnRequestComplete(OnRequestCompleteDelegate action)
103+
{
104+
onRequestComplete = action;
105+
}
106+
107+
internal void SetOnUploadProgress(OnUploadProgressDelegate action)
108+
{
109+
onUploadProgress = action;
110+
}
111+
112+
/// <inheritdoc/>
113+
protected override bool GetAuthCredentials(bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
114+
{
115+
return getAuthCredentials?.Invoke(isProxy, host, port, realm, scheme, callback) ?? false;
116+
}
117+
118+
/// <inheritdoc/>
119+
protected override void OnDownloadData(IUrlRequest request, Stream data)
120+
{
121+
onDownloadData?.Invoke(request, data);
122+
}
123+
124+
/// <inheritdoc/>
125+
protected override void OnDownloadProgress(IUrlRequest request, long current, long total)
126+
{
127+
onDownloadProgress?.Invoke(request, current, total);
128+
}
129+
130+
/// <inheritdoc/>
131+
protected override void OnRequestComplete(IUrlRequest request)
132+
{
133+
onRequestComplete?.Invoke(request);
134+
}
135+
136+
/// <inheritdoc/>
137+
protected override void OnUploadProgress(IUrlRequest request, long current, long total)
138+
{
139+
onUploadProgress?.Invoke(request, current, total);
140+
}
141+
}
142+
}

0 commit comments

Comments
 (0)