2323#include " GenericPlatform/GenericPlatformProcess.h"
2424#include " Mac/ImmutableMac.h"
2525#endif
26+ #if PLATFORM_WINDOWS
27+ #include " Immutable/Windows/ImmutablePKCEWindows.h"
28+ #endif
2629
2730#define PASSPORT_SAVE_GAME_SLOT_NAME TEXT (" Immutable" )
2831
@@ -101,10 +104,22 @@ void UImmutablePassport::Connect(bool IsConnectImx, bool TryToRelogin, const FIm
101104 }
102105}
103106
104- #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
107+ #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC | PLATFORM_WINDOWS
105108void UImmutablePassport::ConnectPKCE (bool IsConnectImx, const FImtblPassportResponseDelegate& ResponseDelegate)
106109{
107110 SetStateFlags (IPS_CONNECTING | IPS_PKCE);
111+
112+ #if PLATFORM_WINDOWS
113+ // Verify PKCEData is null before initializing to ensure we're not overriding an active PKCE operation.
114+ // A non-null value indicates another PKCE operation is already in progress.
115+ ensureAlways (!PKCEData);
116+ PKCEData = UImmutablePKCEWindows::Initialise (InitData);
117+ if (PKCEData)
118+ {
119+ PKCEData->DynamicMulticastDelegate_DeepLinkCallback .AddDynamic (this , &ThisClass::OnDeepLinkActivated);
120+ }
121+ #endif
122+
108123 if (IsConnectImx)
109124 {
110125 SetStateFlags (IPS_IMX);
@@ -117,7 +132,16 @@ void UImmutablePassport::ConnectPKCE(bool IsConnectImx, const FImtblPassportResp
117132
118133void UImmutablePassport::Logout (bool DoHardLogout, const FImtblPassportResponseDelegate& ResponseDelegate)
119134{
120- #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
135+ #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC | PLATFORM_WINDOWS
136+ // Verify PKCEData is null before initializing to ensure we're not overriding an active PKCE operation.
137+ // A non-null value indicates another PKCE operation is already in progress.
138+ ensureAlways (!PKCEData);
139+ PKCEData = UImmutablePKCEWindows::Initialise (InitData);
140+ if (PKCEData)
141+ {
142+ PKCEData->DynamicMulticastDelegate_DeepLinkCallback .AddDynamic (this , &ThisClass::OnDeepLinkActivated);
143+ }
144+
121145 if (IsStateFlagsSet (IPS_PKCE))
122146 {
123147 PKCELogoutResponseDelegate = ResponseDelegate;
@@ -392,7 +416,7 @@ TOptional<UImmutablePassport::FImtblPassportResponseDelegate> UImmutablePassport
392416
393417void UImmutablePassport::OnInitializeResponse (FImtblJSResponse Response)
394418{
395- if (auto ResponseDelegate = GetResponseDelegate (Response))
419+ if (TOptional<FImtblPassportResponseDelegate> ResponseDelegate = GetResponseDelegate (Response))
396420 {
397421 FString Error;
398422
@@ -470,43 +494,55 @@ void UImmutablePassport::OnLogoutResponse(FImtblJSResponse Response)
470494
471495 return ;
472496 }
473-
474- FString Url;
475- FString ErrorMessage;
497+
498+ auto Logout = [this ](const FImtblJSResponse& Response)
499+ {
500+ TOptional<FImtblPassportResponseDelegate> ResponseDelegate = GetResponseDelegate (Response);
501+
502+ FString Url;
503+ Response.JsonObject ->TryGetStringField (TEXT (" result" ), Url);
504+
505+ FString ErrorMessage;
506+ FPlatformProcess::LaunchURL (*Url, nullptr , &ErrorMessage);
507+
508+ if (ErrorMessage.Len ())
509+ {
510+ ErrorMessage = " Failed to launch browser: " + ErrorMessage;
511+ IMTBL_ERR (" %s" , *ErrorMessage);
512+ ResponseDelegate->ExecuteIfBound (FImmutablePassportResult{false , ErrorMessage, Response});
513+ }
514+ };
476515
477516 ResetStateFlags (IPS_HARDLOGOUT);
517+
518+ FString Url;
478519 Response.JsonObject ->TryGetStringField (TEXT (" result" ), Url);
520+
479521 if (!Url.IsEmpty ())
480522 {
481- #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
523+ #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC | PLATFORM_WINDOWS
482524 if (IsStateFlagsSet (IPS_PKCE))
483525 {
484- OnHandleDeepLink = FImtblPassportHandleDeepLinkDelegate::CreateUObject (this , &UImmutablePassport::OnDeepLinkActivated);
526+ OnHandleDeepLink. AddUObject (this , &UImmutablePassport::OnDeepLinkActivated);
485527#if PLATFORM_ANDROID
486528 LaunchAndroidUrl (Url);
487529#elif PLATFORM_IOS
488530 [[ImmutableIOS instance] launchUrl:TCHAR_TO_ANSI (*Url)];
489531#elif PLATFORM_MAC
490532 [[ImmutableMac instance] launchUrl:TCHAR_TO_ANSI (*Url) forRedirectUri:TCHAR_TO_ANSI (*InitData.logoutRedirectUri )];
533+ #endif
534+ #if PLATFORM_WINDOWS
535+ Logout (Response);
491536#endif
492537 }
493538 else
494539 {
495540#endif
496- FPlatformProcess::LaunchURL (*Url, nullptr , &ErrorMessage);
497- if (ErrorMessage.Len ())
498- {
499- Message = " Failed to connect to Browser: " + ErrorMessage;
500-
501- IMTBL_ERR (" %s" , *Message);
502- ResponseDelegate->ExecuteIfBound (FImmutablePassportResult{ false , Message, Response });
503-
504- return ;
505- }
541+ Logout (Response);
506542 Analytics->Track (UImmutableAnalytics::EEventName::COMPLETE_LOGOUT);
507543 IMTBL_LOG (" Logged out" )
508544 ResponseDelegate->ExecuteIfBound (FImmutablePassportResult{ Response.success });
509- #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
545+ #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC | PLATFORM_WINDOWS
510546 }
511547#endif
512548 }
@@ -517,7 +553,7 @@ void UImmutablePassport::OnLogoutResponse(FImtblJSResponse Response)
517553 ResetStateFlags (IPS_CONNECTED);
518554}
519555
520- #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
556+ #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC | PLATFORM_WINDOWS
521557void UImmutablePassport::OnGetPKCEAuthUrlResponse (FImtblJSResponse Response)
522558{
523559 if (PKCEResponseDelegate.IsBound ())
@@ -532,7 +568,7 @@ void UImmutablePassport::OnGetPKCEAuthUrlResponse(FImtblJSResponse Response)
532568 else
533569 {
534570 // Handle deeplink calls
535- OnHandleDeepLink = FImtblPassportHandleDeepLinkDelegate::CreateUObject (this , &UImmutablePassport::OnDeepLinkActivated);
571+ OnHandleDeepLink. AddUObject (this , &UImmutablePassport::OnDeepLinkActivated);
536572
537573 Msg = Response.JsonObject ->GetStringField (TEXT (" result" )).Replace (TEXT (" " ), TEXT (" +" ));
538574#if PLATFORM_ANDROID
@@ -542,6 +578,17 @@ void UImmutablePassport::OnGetPKCEAuthUrlResponse(FImtblJSResponse Response)
542578 [[ImmutableIOS instance] launchUrl:TCHAR_TO_ANSI (*Msg)];
543579#elif PLATFORM_MAC
544580 [[ImmutableMac instance] launchUrl:TCHAR_TO_ANSI (*Msg) forRedirectUri:TCHAR_TO_ANSI (*InitData.redirectUri )];
581+ #elif PLATFORM_WINDOWS
582+ FString ErrorMessage;
583+ FPlatformProcess::LaunchURL (*Msg, nullptr , &ErrorMessage);
584+ if (!ErrorMessage.IsEmpty ())
585+ {
586+ ErrorMessage = " Failed to launch browser: " + ErrorMessage;
587+ IMTBL_ERR (" %s" , *ErrorMessage);
588+ PKCEResponseDelegate.ExecuteIfBound (FImmutablePassportResult{false , ErrorMessage});
589+ PKCEResponseDelegate.Unbind ();
590+ ResetStateFlags (IPS_PKCE | IPS_CONNECTING);
591+ }
545592#endif
546593 }
547594 }
@@ -583,7 +630,6 @@ void UImmutablePassport::OnConnectPKCEResponse(FImtblJSResponse Response)
583630 }
584631 ResetStateFlags (IPS_COMPLETING_PKCE);
585632}
586- #endif
587633
588634void UImmutablePassport::OnConfirmCodeResponse (FImtblJSResponse Response)
589635{
@@ -666,11 +712,9 @@ void UImmutablePassport::LoadPassportSettings()
666712 }
667713}
668714
669- #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
670- void UImmutablePassport::OnDeepLinkActivated (FString DeepLink)
715+ void UImmutablePassport::OnDeepLinkActivated (const FString& DeepLink)
671716{
672- IMTBL_LOG_FUNC (" URL : %s" , *DeepLink);
673- OnHandleDeepLink = nullptr ;
717+ OnHandleDeepLink.Clear ();
674718 if (DeepLink.StartsWith (InitData.logoutRedirectUri ))
675719 {
676720 // execute on game thread to prevent call to Passport instance from another thread
@@ -690,6 +734,8 @@ void UImmutablePassport::OnDeepLinkActivated(FString DeepLink)
690734 {
691735 CompleteLoginPKCEFlow (DeepLink);
692736 }
737+
738+ PKCEData = nullptr ;
693739}
694740
695741void UImmutablePassport::CompleteLoginPKCEFlow (FString Url)
@@ -739,30 +785,34 @@ void UImmutablePassport::CompleteLoginPKCEFlow(FString Url)
739785 FImtblJSResponseDelegate::CreateUObject (this , &UImmutablePassport::OnConnectPKCEResponse));
740786 }
741787}
742-
743788#endif
744789
745- #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
746790#if PLATFORM_ANDROID
747791// Called from Android JNI
748792void UImmutablePassport::HandleDeepLink (FString DeepLink) const
749- {
750- #elif PLATFORM_IOS | PLATFORM_MAC
751-
793+ #endif
794+ #if PLATFORM_IOS | PLATFORM_MAC
752795// Called from iOS Objective C
753796void UImmutablePassport::HandleDeepLink (NSString* sDeepLink ) const
797+ #endif
798+ #if PLATFORM_WINDOWS
799+ void UImmutablePassport::HandleDeepLink (FString DeepLink) const
800+ #endif
754801{
802+ #if PLATFORM_IOS | PLATFORM_MAC
755803 FString DeepLink = FString (UTF8_TO_TCHAR ([sDeepLink UTF8String]));
756804 IMTBL_LOG (" Handle Deep Link: %s" , *DeepLink);
757805#endif
758-
759- if (!OnHandleDeepLink. ExecuteIfBound (DeepLink) )
806+ # if PLATFORM_WINDOWS
807+ if (PKCEData )
760808 {
761- IMTBL_WARN ( " OnHandleDeepLink delegate was not called " );
809+ UImmutablePKCEWindows::HandleDeepLink (PKCEData, DeepLink );
762810 }
763- }
764811#endif
765812
813+ OnHandleDeepLink.Broadcast (DeepLink);
814+ }
815+
766816#if PLATFORM_ANDROID
767817void UImmutablePassport::HandleOnLoginPKCEDismissed ()
768818{
0 commit comments