|
7 | 7 | using Microsoft.Identity.Client;
|
8 | 8 | using Microsoft.Identity.Client.Extensions.Msal;
|
9 | 9 | using System.Threading;
|
10 |
| -using System.Runtime.InteropServices; |
| 10 | +using Avalonia.Controls; |
| 11 | +using GitCredentialManager.UI; |
| 12 | +using GitCredentialManager.UI.Views; |
11 | 13 |
|
12 | 14 | #if NETFRAMEWORK
|
13 |
| -using System.Drawing; |
14 |
| -using System.Windows.Forms; |
15 | 15 | using Microsoft.Identity.Client.Broker;
|
16 | 16 | #endif
|
17 | 17 |
|
@@ -46,9 +46,7 @@ public class MicrosoftAuthentication : AuthenticationBase, IMicrosoftAuthenticat
|
46 | 46 | "live", "liveconnect", "liveid",
|
47 | 47 | };
|
48 | 48 |
|
49 |
| -#if NETFRAMEWORK |
50 |
| - private DummyWindow _dummyWindow; |
51 |
| -#endif |
| 49 | + private readonly CancellationTokenSource _progressWindowCts = new(); |
52 | 50 |
|
53 | 51 | public MicrosoftAuthentication(ICommandContext context)
|
54 | 52 | : base(context) { }
|
@@ -166,10 +164,8 @@ public async Task<IMicrosoftAuthenticationResult> GetTokenAsync(
|
166 | 164 | }
|
167 | 165 | finally
|
168 | 166 | {
|
169 |
| -#if NETFRAMEWORK |
170 |
| - // If we created a dummy window during authentication we should dispose of it now that we're done |
171 |
| - _dummyWindow?.Dispose(); |
172 |
| -#endif |
| 167 | + // If we created a progress window during authentication we should close it now that we're done |
| 168 | + _progressWindowCts.Cancel(); |
173 | 169 | }
|
174 | 170 | }
|
175 | 171 |
|
@@ -266,11 +262,27 @@ private async Task<IPublicClientApplication> CreatePublicClientApplicationAsync(
|
266 | 262 | }
|
267 | 263 | else if (enableBroker) // Only actually need to set a parent window when using the Windows broker
|
268 | 264 | {
|
269 |
| -#if NETFRAMEWORK |
270 |
| - Context.Trace.WriteLine($"Using dummy parent window for MSAL authentication dialogs."); |
271 |
| - _dummyWindow = new DummyWindow(); |
272 |
| - appBuilder.WithParentActivityOrWindow(_dummyWindow.ShowAndGetHandle); |
273 |
| -#endif |
| 265 | + IntPtr ShowAndGetProgressWindowHandle() |
| 266 | + { |
| 267 | + var windowShown = new TaskCompletionSource<IntPtr>(); |
| 268 | + |
| 269 | + Window CreateWindow() |
| 270 | + { |
| 271 | + var window = new ProgressWindow(); |
| 272 | + window.Loaded += (s, e) => |
| 273 | + windowShown.SetResult(window.PlatformImpl?.Handle.Handle ?? IntPtr.Zero); |
| 274 | + return window; |
| 275 | + } |
| 276 | + |
| 277 | + // Do not wait for the window to be closed, but instead wait for the window to be shown |
| 278 | + // and return the window handle immediately. |
| 279 | + Task _ = AvaloniaUi.ShowWindowAsync(CreateWindow, IntPtr.Zero, _progressWindowCts.Token); |
| 280 | + |
| 281 | + return windowShown.Task.GetAwaiter().GetResult(); |
| 282 | + } |
| 283 | + |
| 284 | + Context.Trace.WriteLine("Using progress window for MSAL authentication dialogs."); |
| 285 | + appBuilder.WithParentActivityOrWindow(ShowAndGetProgressWindowHandle); |
274 | 286 | }
|
275 | 287 | }
|
276 | 288 | }
|
@@ -545,73 +557,5 @@ public MsalResult(AuthenticationResult msalResult)
|
545 | 557 | public string AccessToken => _msalResult.AccessToken;
|
546 | 558 | public string AccountUpn => _msalResult.Account.Username;
|
547 | 559 | }
|
548 |
| - |
549 |
| -#if NETFRAMEWORK |
550 |
| - private class DummyWindow : IDisposable |
551 |
| - { |
552 |
| - private readonly Thread _staThread; |
553 |
| - private readonly ManualResetEventSlim _readyEvent; |
554 |
| - private Form _window; |
555 |
| - private IntPtr _handle; |
556 |
| - |
557 |
| - public DummyWindow() |
558 |
| - { |
559 |
| - _staThread = new Thread(ThreadProc); |
560 |
| - _staThread.SetApartmentState(ApartmentState.STA); |
561 |
| - _readyEvent = new ManualResetEventSlim(); |
562 |
| - } |
563 |
| - |
564 |
| - public IntPtr ShowAndGetHandle() |
565 |
| - { |
566 |
| - _staThread.Start(); |
567 |
| - _readyEvent.Wait(); |
568 |
| - return _handle; |
569 |
| - } |
570 |
| - |
571 |
| - public void Dispose() |
572 |
| - { |
573 |
| - _window?.Invoke(() => _window.Close()); |
574 |
| - |
575 |
| - if (_staThread.IsAlive) |
576 |
| - { |
577 |
| - _staThread.Join(); |
578 |
| - } |
579 |
| - } |
580 |
| - |
581 |
| - private void ThreadProc() |
582 |
| - { |
583 |
| - System.Windows.Forms.Application.EnableVisualStyles(); |
584 |
| - _window = new Form |
585 |
| - { |
586 |
| - TopMost = true, |
587 |
| - ControlBox = false, |
588 |
| - MaximizeBox = false, |
589 |
| - MinimizeBox = false, |
590 |
| - ClientSize = new Size(182, 46), |
591 |
| - FormBorderStyle = FormBorderStyle.None, |
592 |
| - StartPosition = FormStartPosition.CenterScreen, |
593 |
| - }; |
594 |
| - |
595 |
| - var progress = new ProgressBar |
596 |
| - { |
597 |
| - Style = ProgressBarStyle.Marquee, |
598 |
| - Location = new Point(12, 12), |
599 |
| - Size = new Size(158, 23), |
600 |
| - MarqueeAnimationSpeed = 30, |
601 |
| - }; |
602 |
| - |
603 |
| - _window.Controls.Add(progress); |
604 |
| - _window.Shown += (s, e) => |
605 |
| - { |
606 |
| - _handle = _window.Handle; |
607 |
| - _readyEvent.Set(); |
608 |
| - }; |
609 |
| - |
610 |
| - _window.ShowDialog(); |
611 |
| - _window.Dispose(); |
612 |
| - _window = null; |
613 |
| - } |
614 |
| - } |
615 |
| -#endif |
616 | 560 | }
|
617 | 561 | }
|
0 commit comments