Skip to content

[ID-3851] fix: windows deeplink write location, warnings #524

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public interface IBrowserCommunicationsManager
#endif
void SetCallTimeout(int ms);
void LaunchAuthURL(string url, string redirectUri);
UniTask<string> Call(string fxName, string data = null, bool ignoreTimeout = false, Nullable<long> timeoutMs = null);
UniTask<string> Call(string fxName, string? data = null, bool ignoreTimeout = false, Nullable<long> timeoutMs = null);
#if (UNITY_IPHONE && !UNITY_EDITOR) || (UNITY_ANDROID && !UNITY_EDITOR)
void ClearCache(bool includeDiskFiles);
void ClearStorage();
Expand All @@ -39,14 +39,14 @@ public class BrowserCommunicationsManager : IBrowserCommunicationsManager

private readonly IDictionary<string, UniTaskCompletionSource<string>> requestTaskMap = new Dictionary<string, UniTaskCompletionSource<string>>();
private readonly IWebBrowserClient webBrowserClient;
public event OnBrowserReadyDelegate OnReady;
public event OnBrowserReadyDelegate? OnReady;

/// <summary>
/// PKCE in some platforms such as iOS and macOS will not trigger a deeplink and a proper callback needs to be
/// setup.
/// </summary>
public event OnUnityPostMessageDelegate OnAuthPostMessage;
public event OnUnityPostMessageErrorDelegate OnPostMessageError;
public event OnUnityPostMessageDelegate? OnAuthPostMessage;
public event OnUnityPostMessageErrorDelegate? OnPostMessageError;

/// <summary>
/// Timeout time for waiting for each call to respond in milliseconds
Expand All @@ -71,31 +71,23 @@ public void SetCallTimeout(int ms)
callTimeout = ms;
}

public UniTask<string> Call(string fxName, string data = null, bool ignoreTimeout = false, Nullable<long> timeoutMs = null)
public UniTask<string> Call(string fxName, string? data = null, bool ignoreTimeout = false, long? timeoutMs = null)
{
var t = new UniTaskCompletionSource<string>();
string requestId = Guid.NewGuid().ToString();
var requestId = Guid.NewGuid().ToString();
// Add task completion source to the map so we can return the response
requestTaskMap.Add(requestId, t);
CallFunction(requestId, fxName, data);
if (ignoreTimeout)
return t.Task;
else
return t.Task.Timeout(TimeSpan.FromMilliseconds(timeoutMs ?? callTimeout));
return ignoreTimeout ? t.Task : t.Task.Timeout(TimeSpan.FromMilliseconds(timeoutMs ?? callTimeout));
}

private void CallFunction(string requestId, string fxName, string data = null)
private void CallFunction(string requestId, string fxName, string? data = null)
{
BrowserRequest request = new BrowserRequest()
{
fxName = fxName,
requestId = requestId,
data = data
};
string requestJson = JsonUtility.ToJson(request).Replace("\\", "\\\\").Replace("\"", "\\\"");
var request = new BrowserRequest(fxName, requestId, data);
var requestJson = JsonUtility.ToJson(request).Replace("\\", "\\\\").Replace("\"", "\\\"");

// Call the function on the JS side
string js = $"callFunction(\"{requestJson}\")";
var js = $"callFunction(\"{requestJson}\")";

if (fxName != PassportAnalytics.TRACK)
{
Expand Down Expand Up @@ -140,25 +132,19 @@ private void InvokeOnUnityPostMessage(string message)
private void InvokeOnAuthPostMessage(string message)
{
PassportLogger.Info($"{TAG} Auth message received: {message}");
if (OnAuthPostMessage != null)
{
OnAuthPostMessage.Invoke(message);
}
OnAuthPostMessage?.Invoke(message);
}

private void InvokeOnPostMessageError(string id, string message)
{
PassportLogger.Info($"{TAG} Error message received ({id}): {message}");
if (OnPostMessageError != null)
{
OnPostMessageError.Invoke(id, message);
}
OnPostMessageError?.Invoke(id, message);
}

private void HandleResponse(string message)
{
PassportLogger.Debug($"{TAG} Handle response message: " + message);
BrowserResponse response = message.OptDeserializeObject<BrowserResponse>();
var response = message.OptDeserializeObject<BrowserResponse>();

// Validate the deserialised response object
if (response == null || string.IsNullOrEmpty(response.responseFor) || string.IsNullOrEmpty(response.requestId))
Expand All @@ -181,10 +167,7 @@ private void HandleResponse(string message)
if (response.responseFor == INIT && response.requestId == INIT_REQUEST_ID)
{
PassportLogger.Info($"{TAG} Browser is ready");
if (OnReady != null)
{
OnReady.Invoke();
}
OnReady?.Invoke();
return;
}

Expand Down Expand Up @@ -230,13 +213,13 @@ private PassportException ParseError(BrowserResponse response)

private void NotifyRequestResult(string requestId, string result)
{
BrowserResponse response = result.OptDeserializeObject<BrowserResponse>();
UniTaskCompletionSource<string> completion = requestTaskMap[requestId] as UniTaskCompletionSource<string>;
var response = result.OptDeserializeObject<BrowserResponse>();
var completion = requestTaskMap[requestId] as UniTaskCompletionSource<string>;
try
{
if (response.success == false || !String.IsNullOrEmpty(response.error))
if (response?.success == false || !string.IsNullOrEmpty(response?.error))
{
PassportException exception = ParseError(response);
var exception = ParseError(response);
if (!completion.TrySetException(exception))
throw new PassportException($"Unable to set exception for for request id {requestId}. Task has already been completed.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ public class BrowserRequest
{
public string fxName;
public string requestId;
public string data;
public string? data;

public BrowserRequest(string fxName, string requestId, string? data)
{
this.fxName = fxName;
this.requestId = requestId;
this.data = data;
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,16 @@ public static class EventName
public const string INIT_PASSPORT = "initialisedPassport";

// Login
public const string START_LOGIN = "startedLogin";
public const string COMPLETE_LOGIN = "performedLogin";
public const string START_LOGIN_PKCE = "startedLoginPkce";
public const string COMPLETE_LOGIN_PKCE = "performedLoginPkce";
public const string COMPLETE_RELOGIN = "performedRelogin";

// Connect
public const string START_CONNECT_IMX = "startedConnectImx";
public const string COMPLETE_CONNECT_IMX = "performedConnectImx";
public const string START_CONNECT_IMX_PKCE = "startedConnectImxPkce";
public const string COMPLETE_CONNECT_IMX_PKCE = "performedConnectImxPkce";
public const string COMPLETE_RECONNECT = "performedReconnect";

// Logout
public const string COMPLETE_LOGOUT = "performedLogout";
public const string COMPLETE_LOGOUT_PKCE = "performedLogoutPkce";
}

Expand All @@ -42,7 +37,7 @@ public static class Properties
}

public async UniTask Track(IBrowserCommunicationsManager communicationsManager, string eventName,
bool? success = null, Dictionary<string, object> properties = null)
bool? success = null, Dictionary<string, object>? properties = null)
{
try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ public static string ToJson(this IDictionary<string, object> dictionary)
[Serializable]
private class Wrapper<T>
{
#pragma warning disable CS8618
public T[] Items;
#pragma warning restore CS8618
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public static class UriExtensions
/// <summary>
/// Gets the specified query parameter from the given URI
/// </summary>
public static string GetQueryParameter(this Uri uri, string key)
public static string? GetQueryParameter(this Uri uri, string key)
{
try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Immutable.Passport.Helpers
{
public class WindowsDeepLink : MonoBehaviour
{
private const string RegistryDeepLinkName = "deeplink";
private const string REGISTRY_DEEP_LINK_NAME = "deeplink";

private static WindowsDeepLink? _instance;
private Action<string>? _callback;
Expand All @@ -28,8 +28,8 @@ public class WindowsDeepLink : MonoBehaviour
private static extern int RegCreateKeyEx(
UIntPtr hKey,
string lpSubKey,
int Reserved,
string lpClass,
int reserved,
string? lpClass,
uint dwOptions,
uint samDesired,
IntPtr lpSecurityAttributes,
Expand All @@ -39,8 +39,8 @@ private static extern int RegCreateKeyEx(
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int RegSetValueEx(
UIntPtr hKey,
string lpValueName,
int Reserved,
string? lpValueName,
int reserved,
uint dwType,
string lpData,
uint cbData);
Expand Down Expand Up @@ -110,7 +110,7 @@ private static void CreateCommandScript(string protocolName)
{
"@echo off",
// Store deeplink URI in registry
$"REG ADD \"HKCU\\Software\\Classes\\{protocolName}\" /v \"{RegistryDeepLinkName}\" /t REG_SZ /d %1 /f >nul 2>&1",
$"REG ADD \"HKCU\\Software\\Classes\\{protocolName}\" /v \"{REGISTRY_DEEP_LINK_NAME}\" /t REG_SZ /d %1 /f >nul 2>&1",
"setlocal",
"",
$"set \"PROJECT_PATH={projectPath}\"",
Expand Down Expand Up @@ -171,7 +171,7 @@ private static void CreateCommandScript(string protocolName)
{
"@echo off",
// Store deeplink URI in registry
$"REG ADD \"HKCU\\Software\\Classes\\{protocolName}\" /v \"{RegistryDeepLinkName}\" /t REG_SZ /d %1 /f >nul 2>&1",
$"REG ADD \"HKCU\\Software\\Classes\\{protocolName}\" /v \"{REGISTRY_DEEP_LINK_NAME}\" /t REG_SZ /d %1 /f >nul 2>&1",
// Check if game is already running
$"tasklist /FI \"IMAGENAME eq {gameExeName}\" 2>NUL | find /I \"{gameExeName}\" >NUL",
"if %ERRORLEVEL%==0 (",
Expand All @@ -198,7 +198,7 @@ private static void RegisterProtocol(string protocolName)
UIntPtr hKey;
uint disposition;
// Create registry key for the protocol
int result = RegCreateKeyEx(
var result = RegCreateKeyEx(
(UIntPtr)HKEY_CURRENT_USER,
$@"Software\Classes\{protocolName}",
0,
Expand All @@ -216,9 +216,9 @@ private static void RegisterProtocol(string protocolName)

// Set the default value for the protocol key to Application.productName
// This is often used by Windows as the display name for the protocol
string appProductName = Application.productName;
uint productNameDataSize = (uint)((appProductName.Length + 1) * Marshal.SystemDefaultCharSize);
int setDefaultResult = RegSetValueEx(hKey, null, 0, REG_SZ, appProductName, productNameDataSize);
var appProductName = Application.productName;
var productNameDataSize = (uint)((appProductName.Length + 1) * Marshal.SystemDefaultCharSize);
var setDefaultResult = RegSetValueEx(hKey, null, 0, REG_SZ, appProductName, productNameDataSize);

if (setDefaultResult != 0)
{
Expand Down Expand Up @@ -268,14 +268,7 @@ private static void RegisterProtocol(string protocolName)
private static string GetGameExecutablePath(string suffix)
{
var exeName = Application.productName + suffix;
#if UNITY_EDITOR_WIN
// Returns the persistent data path in editor
return Path.Combine(Application.persistentDataPath, exeName).Replace("/", "\\");
#else
// Returns game root directory in build
var exePath = Path.Combine(Application.dataPath, "../");
return Path.Combine(exePath, exeName).Replace("/", "\\");
#endif
}

private void OnApplicationFocus(bool hasFocus)
Expand All @@ -289,9 +282,9 @@ private void OnApplicationFocus(bool hasFocus)
private void HandleDeeplink()
{
// Open registry key for the protocol
string registryPath = $@"Software\Classes\{_protocolName}";
var registryPath = $@"Software\Classes\{_protocolName}";
UIntPtr hKey;
int result = RegOpenKeyEx(
var result = RegOpenKeyEx(
(UIntPtr)HKEY_CURRENT_USER,
registryPath,
0,
Expand All @@ -307,7 +300,7 @@ private void HandleDeeplink()
// Get size of deeplink data
uint type = 0;
uint dataSize = 0;
result = RegQueryValueEx(hKey, RegistryDeepLinkName, IntPtr.Zero, ref type, null!, ref dataSize);
result = RegQueryValueEx(hKey, REGISTRY_DEEP_LINK_NAME, IntPtr.Zero, ref type, null!, ref dataSize);

if (result != 0)
{
Expand All @@ -318,7 +311,7 @@ private void HandleDeeplink()

// Read deeplink data
var data = new byte[dataSize];
result = RegQueryValueEx(hKey, RegistryDeepLinkName, IntPtr.Zero, ref type, data, ref dataSize);
result = RegQueryValueEx(hKey, REGISTRY_DEEP_LINK_NAME, IntPtr.Zero, ref type, data, ref dataSize);

var callbackInvoked = false;
if (result == 0 && type == REG_SZ)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,19 @@ public class UnsignedTransferRequest
/**
* The token ID
*/
public string tokenId;
public string? tokenId;

/**
* The token address
*/
public string tokenAddress;
public string? tokenAddress;

public UnsignedTransferRequest(
string type,
string amount,
string receiver,
string tokenId = null,
string tokenAddress = null
string? tokenId = null,
string? tokenAddress = null
)
{
this.type = type;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@ namespace Immutable.Passport
public static class PassportFunction
{
public const string INIT = "init";
public const string INIT_DEVICE_FLOW = "initDeviceFlow";
public const string RELOGIN = "relogin";
public const string RECONNECT = "reconnect";
public const string LOGIN_PKCE = "loginPKCE";
public const string CONNECT_PKCE = "connectPKCE";
public const string GET_PKCE_AUTH_URL = "getPKCEAuthUrl";
public const string LOGIN_CONFIRM_CODE = "loginConfirmCode";
public const string CONNECT_CONFIRM_CODE = "connectConfirmCode";
public const string GET_ACCESS_TOKEN = "getAccessToken";
public const string GET_ID_TOKEN = "getIdToken";
public const string LOGOUT = "logout";
Expand Down
8 changes: 4 additions & 4 deletions src/Packages/Passport/Runtime/Scripts/Private/PassportImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -276,12 +276,12 @@ private async UniTask LaunchAuthUrl()
try
{
var request = new GetPKCEAuthUrlRequest(!_pkceLoginOnly, _directLoginMethod);
string callResponse = await _communicationsManager.Call(PassportFunction.GET_PKCE_AUTH_URL, JsonUtility.ToJson(request));
StringResponse response = callResponse.OptDeserializeObject<StringResponse>();
var callResponse = await _communicationsManager.Call(PassportFunction.GET_PKCE_AUTH_URL, JsonUtility.ToJson(request));
var response = callResponse.OptDeserializeObject<StringResponse>();

if (response != null && response.success == true && response.result != null)
{
string url = response.result.Replace(" ", "+");
var url = response.result.Replace(" ", "+");
#if UNITY_ANDROID && !UNITY_EDITOR
loginPKCEUrl = url;
SendAuthEvent(_pkceLoginOnly ? PassportAuthEvent.LoginPKCELaunchingCustomTabs : PassportAuthEvent.ConnectImxPKCELaunchingCustomTabs);
Expand Down Expand Up @@ -747,7 +747,7 @@ public void ClearStorage()
}
#endif

protected virtual async void Track(string eventName, bool? success = null, Dictionary<string, object> properties = null)
protected virtual async void Track(string eventName, bool? success = null, Dictionary<string, object>? properties = null)
{
await _analytics.Track(_communicationsManager, eventName, success, properties);
}
Expand Down
Loading