Skip to content

Commit 22da69c

Browse files
committed
Set parent window handle based on GCM_MODAL_PARENTHWD
Wire up the parent window handle to system prompts and UI helpers.
1 parent 92e1d9e commit 22da69c

File tree

10 files changed

+81
-2
lines changed

10 files changed

+81
-2
lines changed

src/shared/Microsoft.Git.CredentialManager/CommandContext.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ public CommandContext()
109109
Settings = new Settings(Environment, Git, repoPath);
110110
HttpClientFactory = new HttpClientFactory(Trace, Settings, Streams);
111111
IsDesktopSession = PlatformUtils.IsDesktopSession();
112+
113+
// Set the parent window handle/ID
114+
SystemPrompts.ParentWindowId = Settings.ParentWindowId;
112115
}
113116

114117
#region ICommandContext

src/shared/Microsoft.Git.CredentialManager/Constants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public static class EnvironmentVariables
4747
public const string GcmHttpProxy = "GCM_HTTP_PROXY";
4848
public const string GitSslNoVerify = "GIT_SSL_NO_VERIFY";
4949
public const string GcmInteractive = "GCM_INTERACTIVE";
50+
public const string GcmParentWindow = "GCM_MODAL_PARENTHWND";
5051
}
5152

5253
public static class Http
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
using System;
4+
5+
namespace Microsoft.Git.CredentialManager
6+
{
7+
public static class ConvertUtils
8+
{
9+
public static bool TryToInt32(object value, out int i)
10+
{
11+
return TryConvert(Convert.ToInt32, value, out i);
12+
}
13+
14+
public static bool TryConvert<T>(Func<object, T> convert, object value, out T @out)
15+
{
16+
try
17+
{
18+
@out = convert(value);
19+
return true;
20+
}
21+
catch
22+
{
23+
@out = default(T);
24+
return false;
25+
}
26+
}
27+
}
28+
}

src/shared/Microsoft.Git.CredentialManager/ISystemPrompts.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,24 @@
33

44
namespace Microsoft.Git.CredentialManager
55
{
6+
/// <summary>
7+
/// Represents native system UI prompts.
8+
/// </summary>
69
public interface ISystemPrompts
710
{
11+
/// <summary>
12+
/// The parent window handle or ID. Used for correctly positioning and parenting system dialogs.
13+
/// </summary>
14+
/// <remarks>This value is platform specific.</remarks>
15+
object ParentWindowId { get; set; }
16+
17+
/// <summary>
18+
/// Show a basic credential prompt using native system UI.
19+
/// </summary>
20+
/// <param name="resource">The name or URL of the resource to collect credentials for.</param>
21+
/// <param name="userName">Optional pre-filled username.</param>
22+
/// <param name="credential">The captured basic credential.</param>
23+
/// <returns>True if the user completes the dialog, false otherwise.</returns>
824
bool ShowCredentialPrompt(string resource, string userName, out ICredential credential);
925
}
1026
}

src/shared/Microsoft.Git.CredentialManager/Interop/MacOS/MacOSSystemPrompts.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ namespace Microsoft.Git.CredentialManager.Interop.MacOS
55
{
66
public class MacOSSystemPrompts : ISystemPrompts
77
{
8+
public object ParentWindowId { get; set; }
9+
810
public bool ShowCredentialPrompt(string resource, string userName, out ICredential credential)
911
{
1012
throw new System.NotImplementedException();

src/shared/Microsoft.Git.CredentialManager/Interop/Windows/WindowsSystemPrompts.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ namespace Microsoft.Git.CredentialManager.Interop.Windows
99
{
1010
public class WindowsSystemPrompts : ISystemPrompts
1111
{
12+
private IntPtr _parentHwd = IntPtr.Zero;
13+
14+
public object ParentWindowId
15+
{
16+
get => _parentHwd.ToString();
17+
set => _parentHwd = ConvertUtils.TryToInt32(value, out int ptr) ? new IntPtr(ptr) : IntPtr.Zero;
18+
}
19+
1220
public bool ShowCredentialPrompt(string resource, string userName, out ICredential credential)
1321
{
1422
EnsureArgument.NotNullOrWhiteSpace(resource, nameof(resource));
@@ -19,7 +27,7 @@ public bool ShowCredentialPrompt(string resource, string userName, out ICredenti
1927
{
2028
BannerArt = IntPtr.Zero,
2129
CaptionText = "Git Credential Manager", // TODO: make this a parameter?
22-
Parent = IntPtr.Zero, // TODO: get the parent window handle
30+
Parent = _parentHwd,
2331
MessageText = message,
2432
Size = Marshal.SizeOf(typeof(CredUi.CredentialUiInfo))
2533
};

src/shared/Microsoft.Git.CredentialManager/Settings.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ public interface ISettings : IDisposable
8787
/// <param name="isDeprecatedConfiguration">True if the proxy configuration method is deprecated, false otherwise.</param>
8888
/// <returns>Proxy setting, or null if not configured.</returns>
8989
Uri GetProxyConfiguration(out bool isDeprecatedConfiguration);
90+
91+
/// <summary>
92+
/// The parent window handle/ID. Used to correctly position and parent dialogs generated by GCM.
93+
/// </summary>
94+
/// <remarks>This value is platform specific.</remarks>
95+
string ParentWindowId { get; }
9096
}
9197

9298
public class Settings : ISettings
@@ -271,6 +277,8 @@ bool TryGetUriSetting(string envarName, string section, string property, out Uri
271277
return null;
272278
}
273279

280+
public string ParentWindowId => _environment.Variables.TryGetValue(Constants.EnvironmentVariables.GcmParentWindow, out string parentWindowId) ? parentWindowId : null;
281+
274282
/// <summary>
275283
/// Try and get the value of a specified setting as specified in the environment and Git configuration,
276284
/// with the environment taking precedence over Git.

src/shared/TestInfrastructure/Objects/TestSettings.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public class TestSettings : ISettings
3030

3131
public bool IsDeprecatedProxyConfiguration { get; set; }
3232

33+
public string ParentWindowId { get; set; }
34+
3335
#region ISettings
3436

3537
public string RepositoryPath { get; set; }
@@ -66,6 +68,8 @@ Uri ISettings.GetProxyConfiguration(out bool isDeprecatedConfiguration)
6668
return ProxyConfiguration;
6769
}
6870

71+
string ISettings.ParentWindowId => ParentWindowId;
72+
6973
#endregion
7074

7175
#region IDisposable

src/shared/TestInfrastructure/Objects/TestSystemPrompts.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ public class TestSystemPrompts : ISystemPrompts
88
{
99
public Func<string, string, ICredential> CredentialPrompt { get; set; } = (resource, user) => null;
1010

11+
public object ParentWindowId { get; set; }
12+
1113
public bool ShowCredentialPrompt(string resource, string userName, out ICredential credential)
1214
{
1315
credential = CredentialPrompt(resource, userName);

src/windows/GitHub.Authentication.Helper.Windows/Program.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ public static void Main(string[] args)
2323
}
2424
else
2525
{
26-
var prompts = new AuthenticationPrompts(gui);
26+
IntPtr parentHwnd = GetParentWindowHandle();
27+
var prompts = new AuthenticationPrompts(gui, parentHwnd);
2728
var resultDict = new Dictionary<string, string>();
2829

2930
if (!TryGetArgument(args, "--prompt", out string promptType))
@@ -66,6 +67,12 @@ public static void Main(string[] args)
6667
}
6768
}
6869

70+
private static IntPtr GetParentWindowHandle()
71+
{
72+
string hwndStr = Environment.GetEnvironmentVariable(Constants.EnvironmentVariables.GcmParentWindow);
73+
return ConvertUtils.TryToInt32(hwndStr, out int ptr) ? new IntPtr(ptr) : IntPtr.Zero;
74+
}
75+
6976
private static bool TryGetArgument(string[] args, string name, out string value)
7077
{
7178
for (var i = 0; i < args.Length; i++)

0 commit comments

Comments
 (0)