Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7c35c3e
Merge branch 'dev'
jjw24 Jun 28, 2020
d42d35e
Merge pull request #101 from Flow-Launcher/dev
jjw24 Jul 4, 2020
5f23f3d
Merge pull request #110 from Flow-Launcher/dev
jjw24 Jul 5, 2020
8a9c338
Merge pull request #112 from Flow-Launcher/dev
jjw24 Jul 5, 2020
a8bfe6e
Merge pull request #124 from Flow-Launcher/dev
jjw24 Aug 17, 2020
135f63a
Merge pull request #146 from Flow-Launcher/dev
jjw24 Aug 27, 2020
4ea5dd5
Move Old HttpWebRequest to HttpClient Instance (solve connection time…
taooceros Oct 13, 2020
a16cc5b
Move Old HttpWebRequest to HttpClient Instance (solve connection time…
taooceros Oct 13, 2020
bfd1c9a
Merge branch 'master' of github.com:taooceros/Flow.Launcher into Upda…
taooceros Oct 14, 2020
c55e889
Change Download to HttpClient as well (which change it to async as well)
taooceros Oct 14, 2020
424d757
Add Task.Run due to the change of async download
taooceros Oct 14, 2020
db0b4c1
Merge remote-tracking branch 'upstream/dev' into UpdateHttpMaster
taooceros Dec 21, 2020
85f5766
Optimize a few code
taooceros Dec 21, 2020
96609f7
Change the place of Wait in PluginManifest to make code more elegent
taooceros Dec 21, 2020
5ab8c4f
Update Proxy every time calling a http request method since the proxy…
taooceros Dec 21, 2020
88fa862
Use event triggered update method instead of checking Proxy every tim…
taooceros Dec 21, 2020
d015fce
Merge Upstream
taooceros Dec 29, 2020
8ec781d
Merge branch 'UpdateHttpMaster' of github.com:taooceros/Flow.Launcher…
taooceros Dec 29, 2020
7dc66ea
Merge dev
taooceros Dec 29, 2020
cfa93a2
Add GetStreamAsync method
taooceros Dec 29, 2020
a806f7d
Change exception type
taooceros Dec 29, 2020
4d5119f
Add out of bound exception for pattern matching
taooceros Dec 29, 2020
e364b84
Use auto property
taooceros Dec 29, 2020
0c97db0
1. Change Get method Name to GetAsync
taooceros Dec 29, 2020
efa4908
Change usage of Http in Updater.cs and adding ConfigureAwait(false) f…
taooceros Dec 29, 2020
d4f94c6
Make InstallOrUpdate to async
taooceros Dec 29, 2020
d0743f6
Await Http.Download in Update method
taooceros Dec 29, 2020
c485578
Use CompareTo to check update for InstallOrUpdate method
taooceros Dec 29, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions Flow.Launcher.Core/Updater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using System.Windows;
using JetBrains.Annotations;
using Squirrel;
using Newtonsoft.Json;
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Plugin.SharedCommands;
using Flow.Launcher.Infrastructure;
Expand All @@ -17,6 +16,7 @@
using System.IO;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using System.Text.Json.Serialization;

namespace Flow.Launcher.Core
{
Expand All @@ -29,7 +29,7 @@ public Updater(string gitHubRepository)
GitHubRepository = gitHubRepository;
}

public async Task UpdateApp(IPublicAPI api , bool silentUpdate = true)
public async Task UpdateApp(IPublicAPI api, bool silentUpdate = true)
{
UpdateManager updateManager;
UpdateInfo newUpdateInfo;
Expand All @@ -39,7 +39,7 @@ public async Task UpdateApp(IPublicAPI api , bool silentUpdate = true)

try
{
updateManager = await GitHubUpdateManager(GitHubRepository);
updateManager = await GitHubUpdateManager(GitHubRepository).ConfigureAwait(false);
}
catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException)
{
Expand All @@ -50,7 +50,7 @@ public async Task UpdateApp(IPublicAPI api , bool silentUpdate = true)
try
{
// UpdateApp CheckForUpdate will return value only if the app is squirrel installed
newUpdateInfo = await updateManager.CheckForUpdate().NonNull();
newUpdateInfo = await updateManager.CheckForUpdate().NonNull().ConfigureAwait(false);
}
catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException)
{
Expand Down Expand Up @@ -85,8 +85,8 @@ public async Task UpdateApp(IPublicAPI api , bool silentUpdate = true)
updateManager.Dispose();
return;
}
await updateManager.ApplyReleases(newUpdateInfo);

await updateManager.ApplyReleases(newUpdateInfo).ConfigureAwait(false);

if (DataLocation.PortableDataLocationInUse())
{
Expand All @@ -98,11 +98,11 @@ public async Task UpdateApp(IPublicAPI api , bool silentUpdate = true)
}
else
{
await updateManager.CreateUninstallerRegistryEntry();
await updateManager.CreateUninstallerRegistryEntry().ConfigureAwait(false);
}

var newVersionTips = NewVersinoTips(newReleaseVersion.ToString());

Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}");

// always dispose UpdateManager
Expand All @@ -117,13 +117,13 @@ public async Task UpdateApp(IPublicAPI api , bool silentUpdate = true)
[UsedImplicitly]
private class GithubRelease
{
[JsonProperty("prerelease")]
[JsonPropertyName("prerelease")]
public bool Prerelease { get; [UsedImplicitly] set; }

[JsonProperty("published_at")]
[JsonPropertyName("published_at")]
public DateTime PublishedAt { get; [UsedImplicitly] set; }

[JsonProperty("html_url")]
[JsonPropertyName("html_url")]
public string HtmlUrl { get; [UsedImplicitly] set; }
}

Expand All @@ -133,13 +133,13 @@ private async Task<UpdateManager> GitHubUpdateManager(string repository)
var uri = new Uri(repository);
var api = $"https://api.github.com/repos{uri.AbsolutePath}/releases";

var json = await Http.Get(api);
var jsonStream = await Http.GetStreamAsync(api).ConfigureAwait(false);

var releases = JsonConvert.DeserializeObject<List<GithubRelease>>(json);
var releases = await System.Text.Json.JsonSerializer.DeserializeAsync<List<GithubRelease>>(jsonStream).ConfigureAwait(false);
var latest = releases.Where(r => !r.Prerelease).OrderByDescending(r => r.PublishedAt).First();
var latestUrl = latest.HtmlUrl.Replace("/tag/", "/download/");

var client = new WebClient { Proxy = Http.WebProxy() };
var client = new WebClient { Proxy = Http.WebProxy };
var downloader = new FileDownloader(client);

var manager = new UpdateManager(latestUrl, urlDownloader: downloader);
Expand Down
128 changes: 85 additions & 43 deletions Flow.Launcher.Infrastructure/Http/Http.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,85 +6,127 @@
using JetBrains.Annotations;
using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
using System;
using System.ComponentModel;

namespace Flow.Launcher.Infrastructure.Http
{
public static class Http
{
private const string UserAgent = @"Mozilla/5.0 (Trident/7.0; rv:11.0) like Gecko";

private static HttpClient client;

private static SocketsHttpHandler socketsHttpHandler = new SocketsHttpHandler()
{
UseProxy = true,
Proxy = WebProxy
};

static Http()
{
// need to be added so it would work on a win10 machine
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12;

client = new HttpClient(socketsHttpHandler, false);
client.DefaultRequestHeaders.Add("User-Agent", UserAgent);
}

public static HttpProxy Proxy { private get; set; }
public static IWebProxy WebProxy()
private static HttpProxy proxy;

public static HttpProxy Proxy
{
if (Proxy != null && Proxy.Enabled && !string.IsNullOrEmpty(Proxy.Server))
private get { return proxy; }
set
{
if (string.IsNullOrEmpty(Proxy.UserName) || string.IsNullOrEmpty(Proxy.Password))
{
var webProxy = new WebProxy(Proxy.Server, Proxy.Port);
return webProxy;
}
else
proxy = value;
proxy.PropertyChanged += UpdateProxy;
}
}

public static WebProxy WebProxy { get; } = new WebProxy();

/// <summary>
/// Update the Address of the Proxy to modify the client Proxy
/// </summary>
public static void UpdateProxy(ProxyProperty property)
{
(WebProxy.Address, WebProxy.Credentials) = property switch
{
ProxyProperty.Enabled => Proxy.Enabled switch
{
var webProxy = new WebProxy(Proxy.Server, Proxy.Port)
true => Proxy.UserName switch
{
Credentials = new NetworkCredential(Proxy.UserName, Proxy.Password)
};
return webProxy;
}
var userName when !string.IsNullOrEmpty(userName) =>
(new Uri($"http://{Proxy.Server}:{Proxy.Port}"), null),
_ => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"),
new NetworkCredential(Proxy.UserName, Proxy.Password))
},
false => (null, null)
},
ProxyProperty.Server => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), WebProxy.Credentials),
ProxyProperty.Port => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), WebProxy.Credentials),
ProxyProperty.UserName => (WebProxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)),
ProxyProperty.Password => (WebProxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)),
_ => throw new ArgumentOutOfRangeException()
};
}

public static async Task Download([NotNull] string url, [NotNull] string filePath)
{
using var response = await client.GetAsync(url);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

client.GetAsync crashes the entire app for me when i try to install plugin. Cant see any reason why though, no exception is thrown

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me take a check.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh that's because before the Http.Download is not async, so no await is added there.

if (response.StatusCode == HttpStatusCode.OK)
{
await using var fileStream = new FileStream(filePath, FileMode.CreateNew);
await response.Content.CopyToAsync(fileStream);
}
else
{
return WebRequest.GetSystemWebProxy();
throw new HttpRequestException($"Error code <{response.StatusCode}> returned from <{url}>");
}
}

public static void Download([NotNull] string url, [NotNull] string filePath)
/// <summary>
/// Asynchrously get the result as string from url.
/// When supposing the result is long and large, try using GetStreamAsync to avoid reading as string
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static Task<string> GetAsync([NotNull] string url)
{
var client = new WebClient { Proxy = WebProxy() };
client.Headers.Add("user-agent", UserAgent);
client.DownloadFile(url, filePath);
Log.Debug($"|Http.Get|Url <{url}>");
return GetAsync(new Uri(url.Replace("#", "%23")));
}

public static async Task<string> Get([NotNull] string url, string encoding = "UTF-8")
public static async Task<string> GetAsync([NotNull] Uri url)
{
Log.Debug($"|Http.Get|Url <{url}>");
var request = WebRequest.CreateHttp(url);
request.Method = "GET";
request.Timeout = 6000;
request.Proxy = WebProxy();
request.UserAgent = UserAgent;
var response = await request.GetResponseAsync() as HttpWebResponse;
response = response.NonNull();
var stream = response.GetResponseStream().NonNull();

using var reader = new StreamReader(stream, Encoding.GetEncoding(encoding));
var content = await reader.ReadToEndAsync();
if (response.StatusCode != HttpStatusCode.OK)
throw new HttpRequestException($"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>");

return content;
using var response = await client.GetAsync(url);
var content = await response.Content.ReadAsStringAsync();
if (response.StatusCode == HttpStatusCode.OK)
{
return content;
}
else
{
throw new HttpRequestException(
$"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>");
}
}

/// <summary>
/// Asynchrously get the result as stream from url.
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static async Task<Stream> GetStreamAsync([NotNull] string url)
{
Log.Debug($"|Http.Get|Url <{url}>");
var request = WebRequest.CreateHttp(url);
request.Method = "GET";
request.Timeout = 6000;
request.Proxy = WebProxy();
request.UserAgent = UserAgent;
var response = await request.GetResponseAsync() as HttpWebResponse;
response = response.NonNull();
return response.GetResponseStream().NonNull();
var response = await client.GetAsync(url);
return await response.Content.ReadAsStreamAsync();
}
}
}
81 changes: 75 additions & 6 deletions Flow.Launcher.Infrastructure/UserSettings/HttpProxy.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,80 @@
namespace Flow.Launcher.Infrastructure.UserSettings
using System.ComponentModel;

namespace Flow.Launcher.Infrastructure.UserSettings
{
public enum ProxyProperty
{
Enabled,
Server,
Port,
UserName,
Password
}

public class HttpProxy
{
public bool Enabled { get; set; } = false;
public string Server { get; set; }
public int Port { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
private bool _enabled = false;
private string _server;
private int _port;
private string _userName;
private string _password;

public bool Enabled
{
get => _enabled;
set
{
_enabled = value;
OnPropertyChanged(ProxyProperty.Enabled);
}
}

public string Server
{
get => _server;
set
{
_server = value;
OnPropertyChanged(ProxyProperty.Server);
}
}

public int Port
{
get => _port;
set
{
_port = value;
OnPropertyChanged(ProxyProperty.Port);
}
}

public string UserName
{
get => _userName;
set
{
_userName = value;
OnPropertyChanged(ProxyProperty.UserName);
}
}

public string Password
{
get => _password;
set
{
_password = value;
OnPropertyChanged(ProxyProperty.Password);
}
}

public delegate void ProxyPropertyChangedHandler(ProxyProperty property);
public event ProxyPropertyChangedHandler PropertyChanged;

private void OnPropertyChanged(ProxyProperty property)
{
PropertyChanged?.Invoke(property);
}
}
}
2 changes: 1 addition & 1 deletion Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class Main : ISettingProvider, IPlugin, ISavable, IContextMenu, IPluginI1

internal PluginsManager pluginManager;

private DateTime lastUpdateTime;
private DateTime lastUpdateTime = DateTime.MinValue;

public Control CreateSettingPanel()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace Flow.Launcher.Plugin.PluginsManager.Models
internal class PluginsManifest
{
internal List<UserPlugin> UserPlugins { get; private set; }

internal PluginsManifest()
{
Task.Run(async () => await DownloadManifest()).Wait();
Expand All @@ -30,7 +31,6 @@ internal async Task DownloadManifest()

UserPlugins = new List<UserPlugin>();
}

}
}
}
}
Loading