Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid Blocking Calls in App and AutoUpdater #474

Merged
merged 16 commits into from
Jan 10, 2021
55 changes: 45 additions & 10 deletions ElectronNET.API/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,27 @@ internal set
/// which will be preferred over name by Electron.
/// </summary>
public string Name
{
[Obsolete("Use the asynchronous version NameAsync instead")]
get
{
return NameAsync.Result;
}
set
{
BridgeConnector.Socket.Emit("appSetName", value);
}
}

/// <summary>
/// A <see cref="string"/> property that indicates the current application's name, which is the name in the
/// application's package.json file.
///
/// Usually the name field of package.json is a short lowercase name, according to the npm modules spec. You
/// should usually also specify a productName field, which is your application's full capitalized name, and
/// which will be preferred over name by Electron.
/// </summary>
public Task<string> NameAsync
{
get
{
Expand All @@ -423,14 +444,11 @@ public string Name
BridgeConnector.Socket.Emit("appGetName");

return taskCompletionSource.Task;
}).Result;
}
set
{
BridgeConnector.Socket.Emit("appSetName", value);
});
}
}


internal App()
{
CommandLine = new CommandLine();
Expand Down Expand Up @@ -1479,6 +1497,27 @@ public void SetAboutPanelOptions(AboutPanelOptions options)
/// is used.
/// </summary>
public string UserAgentFallback
{
[Obsolete("Use the asynchronous version UserAgentFallbackAsync instead")]
get
{
return UserAgentFallbackAsync.Result;
}
set
{
BridgeConnector.Socket.Emit("appSetUserAgentFallback", value);
}
}

/// <summary>
/// A <see cref="string"/> which is the user agent string Electron will use as a global fallback.
/// <para/>
/// This is the user agent that will be used when no user agent is set at the webContents or
/// session level. It is useful for ensuring that your entire app has the same user agent. Set to a
/// custom value as early as possible in your app's initialization to ensure that your overridden value
/// is used.
/// </summary>
public Task<string> UserAgentFallbackAsync
{
get
{
Expand All @@ -1495,11 +1534,7 @@ public string UserAgentFallback
BridgeConnector.Socket.Emit("appGetUserAgentFallback");

return taskCompletionSource.Task;
}).Result;
}
set
{
BridgeConnector.Socket.Emit("appSetUserAgentFallback", value);
});
}
}

Expand Down
124 changes: 120 additions & 4 deletions ElectronNET.API/AutoUpdater.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ElectronNET.API
Expand Down Expand Up @@ -182,11 +185,48 @@ public string UpdateConfigPath
}
}

/// <summary>
/// The current application version
/// </summary>
public Task<SemVer> CurrentVersionAsync
{
get
{
return Task.Run<SemVer>(() =>
{
var taskCompletionSource = new TaskCompletionSource<SemVer>();

BridgeConnector.Socket.On("autoUpdater-currentVersion-get-reply", (result) =>
{
BridgeConnector.Socket.Off("autoUpdater-currentVersion-get-reply");
SemVer version = ((JObject)result).ToObject<SemVer>();
taskCompletionSource.SetResult(version);
});
BridgeConnector.Socket.Emit("autoUpdater-currentVersion-get");

return taskCompletionSource.Task;
});
}
}

/// <summary>
/// Get the update channel. Not applicable for GitHub.
/// Doesn’t return channel from the update configuration, only if was previously set.
/// </summary>
[Obsolete("Use the asynchronous version ChannelAsync instead")]
public string Channel
{
get
{
return ChannelAsync.Result;
}
}

/// <summary>
/// Get the update channel. Not applicable for GitHub.
/// Doesn’t return channel from the update configuration, only if was previously set.
/// </summary>
public Task<string> ChannelAsync
{
get
{
Expand All @@ -199,11 +239,45 @@ public string Channel
BridgeConnector.Socket.Off("autoUpdater-channel-get-reply");
taskCompletionSource.SetResult(result.ToString());
});

BridgeConnector.Socket.Emit("autoUpdater-channel-get");

return taskCompletionSource.Task;
}).Result;
});
}
}



/// <summary>
/// The request headers.
/// </summary>
public Task<Dictionary<string, string>> RequestHeadersAsync
{
get
{
return Task.Run(() =>
{
var taskCompletionSource = new TaskCompletionSource<Dictionary<string, string>>();
BridgeConnector.Socket.On("autoUpdater-requestHeaders-get-reply", (headers) =>
{
BridgeConnector.Socket.Off("autoUpdater-requestHeaders-get-reply");
Dictionary<string, string> result = ((JObject)headers).ToObject<Dictionary<string, string>>();
taskCompletionSource.SetResult(result);
});
BridgeConnector.Socket.Emit("autoUpdater-requestHeaders-get");
return taskCompletionSource.Task;
});
}
}

/// <summary>
/// The request headers.
/// </summary>
public Dictionary<string, string> RequestHeaders
{
set
{
BridgeConnector.Socket.Emit("autoUpdater-requestHeaders-set", JObject.FromObject(value, _jsonSerializer));
}
}

Expand Down Expand Up @@ -416,9 +490,26 @@ public Task<UpdateCheckResult> CheckForUpdatesAsync()
string guid = Guid.NewGuid().ToString();

BridgeConnector.Socket.On("autoUpdaterCheckForUpdatesComplete" + guid, (updateCheckResult) =>
{
try
{
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesComplete" + guid);
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesError" + guid);
taskCompletionSource.SetResult(JObject.Parse(updateCheckResult.ToString()).ToObject<UpdateCheckResult>());
}
catch (Exception ex)
{
taskCompletionSource.SetException(ex);
}
});
BridgeConnector.Socket.On("autoUpdaterCheckForUpdatesError" + guid, (error) =>
{
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesComplete" + guid);
taskCompletionSource.SetResult(JObject.Parse(updateCheckResult.ToString()).ToObject<UpdateCheckResult>());
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesError" + guid);
string message = "An error occurred in CheckForUpdatesAsync";
if (error != null && !string.IsNullOrEmpty(error.ToString()))
message = JsonConvert.SerializeObject(error);
taskCompletionSource.SetException(new Exception(message));
});

BridgeConnector.Socket.Emit("autoUpdaterCheckForUpdates", guid);
Expand All @@ -438,9 +529,29 @@ public Task<UpdateCheckResult> CheckForUpdatesAndNotifyAsync()
string guid = Guid.NewGuid().ToString();

BridgeConnector.Socket.On("autoUpdaterCheckForUpdatesAndNotifyComplete" + guid, (updateCheckResult) =>
{
try
{
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesAndNotifyComplete" + guid);
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesAndNotifyError" + guid);
if (updateCheckResult == null)
taskCompletionSource.SetResult(null);
else
taskCompletionSource.SetResult(JObject.Parse(updateCheckResult.ToString()).ToObject<UpdateCheckResult>());
}
catch (Exception ex)
{
taskCompletionSource.SetException(ex);
}
});
BridgeConnector.Socket.On("autoUpdaterCheckForUpdatesAndNotifyError" + guid, (error) =>
{
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesAndNotifyComplete" + guid);
taskCompletionSource.SetResult(JObject.Parse(updateCheckResult.ToString()).ToObject<UpdateCheckResult>());
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesAndNotifyError" + guid);
string message = "An error occurred in autoUpdaterCheckForUpdatesAndNotify";
if (error != null)
message = JsonConvert.SerializeObject(error);
taskCompletionSource.SetException(new Exception(message));
});

BridgeConnector.Socket.Emit("autoUpdaterCheckForUpdatesAndNotify", guid);
Expand Down Expand Up @@ -501,5 +612,10 @@ public Task<string> GetFeedURLAsync()

return taskCompletionSource.Task;
}

private readonly JsonSerializer _jsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
}
}
59 changes: 59 additions & 0 deletions ElectronNET.API/Entities/SemVer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class SemVer
{
/// <summary>
///
/// </summary>
public string Raw { get; set; }
/// <summary>
///
/// </summary>
public bool Loose { get; set; }
/// <summary>
///
/// </summary>
public SemVerOptions Options { get; set; }
/// <summary>
///
/// </summary>
public int Major { get; set; }
/// <summary>
///
/// </summary>
public int Minor { get; set; }
/// <summary>
///
/// </summary>
public int Patch { get; set; }
/// <summary>
///
/// </summary>
public string Version { get; set; }
/// <summary>
///
/// </summary>
public string[] Build { get; set; }
/// <summary>
///
/// </summary>
public string[] Prerelease { get; set; }
}

/// <summary>
///
/// </summary>
public class SemVerOptions {
/// <summary>
///
/// </summary>
public bool? Loose { get; set; }
/// <summary>
///
/// </summary>
public bool? IncludePrerelease { get; set; }
}
}
23 changes: 19 additions & 4 deletions ElectronNET.Host/api/autoUpdater.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading