Skip to content

Commit 6cd23bb

Browse files
gautamdshethGautam Sheth
andauthored
Fix #4983: open browser in linux (#4984)
Co-authored-by: Gautam Sheth <gautam.sheth@staffbase.com>
1 parent 220985c commit 6cd23bb

File tree

1 file changed

+94
-20
lines changed

1 file changed

+94
-20
lines changed

src/Commands/Utilities/BrowserHelper.cs

Lines changed: 94 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
using System;
1+
using Microsoft.Identity.Client;
2+
using System;
23
using System.Collections.Concurrent;
34
using System.Diagnostics;
5+
using System.IO;
46
using System.Linq;
57
using System.Net;
68
using System.Net.Http;
@@ -165,42 +167,70 @@ internal enum UrlMatchType
165167
}
166168
}
167169

170+
// Using code from MSAL
171+
// https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/blob/main/src/client/Microsoft.Identity.Client/Platforms/netstandard/NetCorePlatformProxy.cs
172+
168173
internal static void OpenBrowserForInteractiveLogin(string url, int port, CancellationTokenSource cancellationTokenSource)
169174
{
170175
// Fixes encoding of scopes and redirect_uri issue on MacOS. It has no negative effects on Windows.
171176
url = WebUtility.UrlDecode(url);
172177

173-
try
178+
if (OperatingSystem.IsWindows())
174179
{
175-
176-
ProcessStartInfo psi = new ProcessStartInfo
180+
try
177181
{
178-
FileName = url,
179-
UseShellExecute = true
180-
};
181-
Process.Start(psi);
182-
183-
}
184-
catch
185-
{
186-
// hack because of this: https://github.com/dotnet/corefx/issues/10361
187-
if (OperatingSystem.IsWindows())
182+
var psi = new ProcessStartInfo
183+
{
184+
FileName = url,
185+
UseShellExecute = true
186+
};
187+
Process.Start(psi);
188+
}
189+
catch
188190
{
191+
// hack because of this: https://github.com/dotnet/corefx/issues/10361
192+
url = url.Replace("&", "^&");
189193
Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true });
190194
}
191-
else if (OperatingSystem.IsLinux())
195+
}
196+
else if (OperatingSystem.IsLinux())
197+
{
198+
string sudoUser = Environment.GetEnvironmentVariable("SUDO_USER");
199+
if (!string.IsNullOrWhiteSpace(sudoUser))
192200
{
193-
Process.Start("xdg-open", url);
201+
throw new MsalClientException(MsalError.LinuxXdgOpen);
194202
}
195-
else if (OperatingSystem.IsMacOS())
203+
try
196204
{
197-
Process.Start("open", url);
205+
bool opened = false;
206+
foreach (string openTool in GetOpenToolsLinux())
207+
{
208+
if (TryGetExecutablePath(openTool, out string openToolPath))
209+
{
210+
OpenLinuxBrowser(openToolPath, url);
211+
opened = true;
212+
break;
213+
}
214+
}
215+
216+
if (!opened)
217+
{
218+
throw new MsalClientException(MsalError.LinuxXdgOpen);
219+
}
198220
}
199-
else
221+
catch
200222
{
201-
throw new PlatformNotSupportedException(RuntimeInformation.OSDescription);
223+
throw new MsalClientException(MsalError.LinuxXdgOpen);
202224
}
203225
}
226+
else if (OperatingSystem.IsMacOS())
227+
{
228+
Process.Start("/usr/bin/open", url);
229+
}
230+
else
231+
{
232+
throw new PlatformNotSupportedException(RuntimeInformation.OSDescription);
233+
}
204234
}
205235

206236
internal static int FindFreeLocalhostRedirectUri()
@@ -216,5 +246,49 @@ internal static int FindFreeLocalhostRedirectUri()
216246
listener?.Stop();
217247
}
218248
}
249+
250+
internal static void OpenLinuxBrowser(string openToolPath, string url)
251+
{
252+
ProcessStartInfo psi = new ProcessStartInfo(openToolPath, url)
253+
{
254+
RedirectStandardOutput = true,
255+
RedirectStandardError = true,
256+
UseShellExecute = false
257+
};
258+
259+
Process.Start(psi);
260+
261+
}
262+
263+
internal static string[] GetOpenToolsLinux()
264+
{
265+
return ["xdg-open", "gnome-open", "kfmclient", "microsoft-edge", "wslview"];
266+
}
267+
268+
/// <summary>
269+
/// Searches through PATH variable to find the path to the specified executable.
270+
/// </summary>
271+
/// <param name="executable">Executable to find the path for.</param>
272+
/// <param name="path">Location of the specified executable.</param>
273+
/// <returns></returns>
274+
internal static bool TryGetExecutablePath(string executable, out string path)
275+
{
276+
string pathEnvVar = Environment.GetEnvironmentVariable("PATH");
277+
if (pathEnvVar != null)
278+
{
279+
var paths = pathEnvVar.Split(':');
280+
foreach (var basePath in paths)
281+
{
282+
path = Path.Combine(basePath, executable);
283+
if (File.Exists(path))
284+
{
285+
return true;
286+
}
287+
}
288+
}
289+
290+
path = null;
291+
return false;
292+
}
219293
}
220294
}

0 commit comments

Comments
 (0)