Skip to content

Commit b034d1c

Browse files
committed
Task Callbacks - only call TrySetResultAsync if the callback was never called
Add IsDisposed property to ICompletionCallback, IPrintToPdfCallback, IRegisterCdmCallback, IResolveCallback Should resolve #2349 until the code review can be finished
1 parent a8ff890 commit b034d1c

10 files changed

+103
-39
lines changed

CefSharp/Callback/ICompletionCallback.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,10 @@ public interface ICompletionCallback : IDisposable
1515
/// Method that will be called once the task is complete.
1616
/// </summary>
1717
void OnComplete();
18+
19+
/// <summary>
20+
/// Gets a value indicating whether the callback has been disposed of.
21+
/// </summary>
22+
bool IsDisposed { get; }
1823
}
1924
}

CefSharp/Callback/IPrintToPdfCallback.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,10 @@ public interface IPrintToPdfCallback : IDisposable
1919
/// <param name="ok">Will be true if the printing completed
2020
/// successfully or false otherwise.</param>
2121
void OnPdfPrintFinished(string path, bool ok);
22+
23+
/// <summary>
24+
/// Gets a value indicating whether the callback has been disposed of.
25+
/// </summary>
26+
bool IsDisposed { get; }
2227
}
2328
}

CefSharp/Callback/IRegisterCdmCallback.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,10 @@ public interface IRegisterCdmCallback : IDisposable
1616
/// </summary>
1717
/// <param name="registration">The result of the CDM registration process</param>
1818
void OnRegistrationComplete(CdmRegistration registration);
19+
20+
/// <summary>
21+
/// Gets a value indicating whether the callback has been disposed of.
22+
/// </summary>
23+
bool IsDisposed { get; }
1924
}
2025
}

CefSharp/Callback/IResolveCallback.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
//
33
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
44

5+
using System;
56
using System.Collections.Generic;
67

78
namespace CefSharp
89
{
9-
public interface IResolveCallback
10+
public interface IResolveCallback : IDisposable
1011
{
1112
/// <summary>
1213
/// Called after the ResolveHost request has completed.
@@ -15,5 +16,10 @@ public interface IResolveCallback
1516
/// <param name="resolvedIpAddresses">will be the list of resolved IP addresses or
1617
/// empty if the resolution failed.</param>
1718
void OnResolveCompleted(CefErrorCode result, IList<string> resolvedIpAddresses);
19+
20+
/// <summary>
21+
/// Gets a value indicating whether the callback has been disposed of.
22+
/// </summary>
23+
bool IsDisposed { get; }
1824
}
1925
}

CefSharp/Callback/TaskCompletionCallback.cs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@ namespace CefSharp
1010
{
1111
public class TaskCompletionCallback : ICompletionCallback
1212
{
13-
private readonly TaskCompletionSource<bool> taskCompletionSource;
14-
15-
public TaskCompletionCallback()
16-
{
17-
taskCompletionSource = new TaskCompletionSource<bool>();
18-
}
13+
private readonly TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
14+
private volatile bool isDisposed;
15+
private bool complete; //Only ever accessed on the same CEF thread, so no need for thread safety
1916

2017
void ICompletionCallback.OnComplete()
2118
{
19+
complete = true;
20+
2221
taskCompletionSource.TrySetResultAsync(true);
2322
}
2423

@@ -27,16 +26,23 @@ public Task<bool> Task
2726
get { return taskCompletionSource.Task; }
2827
}
2928

29+
bool ICompletionCallback.IsDisposed
30+
{
31+
get { return isDisposed; }
32+
}
33+
3034
void IDisposable.Dispose()
3135
{
3236
var task = taskCompletionSource.Task;
3337

3438
//If the Task hasn't completed and this is being disposed then
3539
//set the TCS to false
36-
if(task.IsCompleted == false)
40+
if(complete == false && task.IsCompleted == false)
3741
{
3842
taskCompletionSource.TrySetResultAsync(false);
3943
}
44+
45+
isDisposed = true;
4046
}
4147
}
4248
}

CefSharp/Callback/TaskDeleteCookiesCallback.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,14 @@ public class TaskDeleteCookiesCallback : IDeleteCookiesCallback
1515
{
1616
public const int InvalidNoOfCookiesDeleted = -1;
1717

18-
private readonly TaskCompletionSource<int> taskCompletionSource;
18+
private readonly TaskCompletionSource<int> taskCompletionSource = new TaskCompletionSource<int>();
1919
private volatile bool isDisposed;
20-
21-
public TaskDeleteCookiesCallback()
22-
{
23-
taskCompletionSource = new TaskCompletionSource<int>();
24-
}
20+
private bool complete; //Only ever accessed on the same CEF thread, so no need for thread safety
2521

2622
void IDeleteCookiesCallback.OnComplete(int numDeleted)
2723
{
24+
complete = true;
25+
2826
taskCompletionSource.TrySetResultAsync(numDeleted);
2927
}
3028

@@ -38,14 +36,13 @@ bool IDeleteCookiesCallback.IsDisposed
3836
get { return isDisposed; }
3937
}
4038

41-
4239
void IDisposable.Dispose()
4340
{
4441
var task = taskCompletionSource.Task;
4542

4643
//If the Task hasn't completed and this is being disposed then
4744
//set the TCS to InvalidNoOfCookiesDeleted
48-
if (task.IsCompleted == false)
45+
if (complete == false && task.IsCompleted == false)
4946
{
5047
taskCompletionSource.TrySetResultAsync(InvalidNoOfCookiesDeleted);
5148
}

CefSharp/Callback/TaskPrintToPdfCallback.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ namespace CefSharp
1111
public sealed class TaskPrintToPdfCallback : IPrintToPdfCallback
1212
{
1313
private readonly TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
14+
private volatile bool isDisposed;
15+
private bool complete; //Only ever accessed on the same CEF thread, so no need for thread safety
1416

1517
public Task<bool> Task
1618
{
@@ -19,12 +21,28 @@ public Task<bool> Task
1921

2022
void IPrintToPdfCallback.OnPdfPrintFinished(string path, bool ok)
2123
{
24+
complete = true;
25+
2226
taskCompletionSource.TrySetResultAsync(ok);
2327
}
2428

29+
bool IPrintToPdfCallback.IsDisposed
30+
{
31+
get { return isDisposed; }
32+
}
33+
2534
void IDisposable.Dispose()
2635
{
27-
//TODO: Check if this is ever called
36+
var task = taskCompletionSource.Task;
37+
38+
//If the Task hasn't completed and this is being disposed then
39+
//set the TCS to false
40+
if (complete == false && task.IsCompleted == false)
41+
{
42+
taskCompletionSource.TrySetResultAsync(false);
43+
}
44+
45+
isDisposed = true;
2846
}
2947
}
3048
}

CefSharp/Callback/TaskRegisterCdmCallback.cs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,16 @@ namespace CefSharp
1111
/// <summary>
1212
/// Provides a callback implementation of <see cref="IRegisterCdmCallback"/> for use with asynchronous Widevine CDM registration.
1313
/// </summary>
14-
public class TaskRegisterCdmCallback: IRegisterCdmCallback
14+
public class TaskRegisterCdmCallback : IRegisterCdmCallback
1515
{
16-
private readonly TaskCompletionSource<CdmRegistration> taskCompletionSource;
17-
18-
public TaskRegisterCdmCallback()
19-
{
20-
taskCompletionSource = new TaskCompletionSource<CdmRegistration>();
21-
}
16+
private readonly TaskCompletionSource<CdmRegistration> taskCompletionSource = new TaskCompletionSource<CdmRegistration>();
17+
private volatile bool isDisposed;
18+
private bool complete; //Only ever accessed on the same CEF thread, so no need for thread safety
2219

2320
void IRegisterCdmCallback.OnRegistrationComplete(CdmRegistration registration)
2421
{
22+
complete = true;
23+
2524
taskCompletionSource.TrySetResultAsync(registration);
2625
}
2726

@@ -30,16 +29,23 @@ public Task<CdmRegistration> Task
3029
get { return taskCompletionSource.Task; }
3130
}
3231

32+
bool IRegisterCdmCallback.IsDisposed
33+
{
34+
get { return isDisposed; }
35+
}
36+
3337
void IDisposable.Dispose()
3438
{
3539
var task = taskCompletionSource.Task;
3640

3741
//If the Task hasn't completed and this is being disposed then
38-
//set the TCS to false
39-
if (task.IsCompleted == false)
42+
//set the TCS to null
43+
if (complete == false && task.IsCompleted == false)
4044
{
4145
taskCompletionSource.TrySetResultAsync(null);
4246
}
47+
48+
isDisposed = true;
4349
}
4450
}
4551
}

CefSharp/Callback/TaskResolveCallback.cs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//
33
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
44

5+
using System;
56
using System.Collections.Generic;
67
using System.Threading.Tasks;
78
using CefSharp.Internals;
@@ -10,21 +11,39 @@ namespace CefSharp
1011
{
1112
public class TaskResolveCallback : IResolveCallback
1213
{
13-
private readonly TaskCompletionSource<ResolveCallbackResult> taskCompletionSource;
14+
private readonly TaskCompletionSource<ResolveCallbackResult> taskCompletionSource = new TaskCompletionSource<ResolveCallbackResult>();
15+
private volatile bool isDisposed;
16+
private bool complete; //Only ever accessed on the same CEF thread, so no need for thread safety
1417

15-
public TaskResolveCallback()
18+
void IResolveCallback.OnResolveCompleted(CefErrorCode result, IList<string> resolvedIpAddresses)
1619
{
17-
taskCompletionSource = new TaskCompletionSource<ResolveCallbackResult>();
20+
complete = true;
21+
22+
taskCompletionSource.TrySetResultAsync(new ResolveCallbackResult(result, resolvedIpAddresses));
1823
}
1924

20-
public void OnResolveCompleted(CefErrorCode result, IList<string> resolvedIpAddresses)
25+
void IDisposable.Dispose()
2126
{
22-
taskCompletionSource.TrySetResultAsync(new ResolveCallbackResult(result, resolvedIpAddresses));
27+
var task = taskCompletionSource.Task;
28+
29+
//If the Task hasn't completed and this is being disposed then
30+
//set the TCS to null
31+
if (complete == false && task.IsCompleted == false)
32+
{
33+
taskCompletionSource.TrySetResultAsync(new ResolveCallbackResult(CefErrorCode.Unexpected, null));
34+
}
35+
36+
isDisposed = true;
2337
}
2438

2539
public Task<ResolveCallbackResult> Task
2640
{
2741
get { return taskCompletionSource.Task; }
2842
}
43+
44+
bool IResolveCallback.IsDisposed
45+
{
46+
get { return isDisposed; }
47+
}
2948
}
3049
}

CefSharp/Callback/TaskSetCookieCallback.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,14 @@ namespace CefSharp
1313
/// </summary>
1414
public class TaskSetCookieCallback : ISetCookieCallback
1515
{
16-
private readonly TaskCompletionSource<bool> taskCompletionSource;
16+
private readonly TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
1717
private volatile bool isDisposed;
18-
19-
public TaskSetCookieCallback()
20-
{
21-
taskCompletionSource = new TaskCompletionSource<bool>();
22-
}
18+
private bool complete; //Only ever accessed on the same CEF thread, so no need for thread safety
2319

2420
void ISetCookieCallback.OnComplete(bool success)
2521
{
22+
complete = true;
23+
2624
taskCompletionSource.TrySetResultAsync(success);
2725
}
2826

@@ -42,13 +40,12 @@ void IDisposable.Dispose()
4240

4341
//If the Task hasn't completed and this is being disposed then
4442
//set the TCS to false
45-
if (task.IsCompleted == false)
43+
if (complete == false && task.IsCompleted == false)
4644
{
4745
taskCompletionSource.TrySetResultAsync(false);
4846
}
4947

5048
isDisposed = true;
51-
5249
}
5350
}
5451
}

0 commit comments

Comments
 (0)