Skip to content

Commit

Permalink
Smoother OAuth Cancellation Handling + EndSession Prefab_ConnectWalle…
Browse files Browse the repository at this point in the history
…t Option (#187)
  • Loading branch information
0xFirekeeper authored May 17, 2024
1 parent 3c17230 commit 890e617
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 14 deletions.
18 changes: 13 additions & 5 deletions Assets/Thirdweb/Core/Scripts/Browser/AndroidBrowser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ public async Task<BrowserResult> Login(string loginUrl, string customScheme, Can
return new BrowserResult(BrowserStatus.Timeout, null, "The operation timed out.");
}
}
catch (TaskCanceledException)
{
return new BrowserResult(BrowserStatus.UserCanceled, null, "The operation was cancelled.");
}
catch (Exception ex)
{
return new BrowserResult(BrowserStatus.UnknownError, null, $"An error occurred: {ex.Message}");
}
finally
{
Application.deepLinkActivated -= OnDeepLinkActivated;
Expand All @@ -47,17 +55,17 @@ public async Task<BrowserResult> Login(string loginUrl, string customScheme, Can

private void OpenURL(string url)
{
AndroidJavaClass thirdwebActivityClass = new("com.unity3d.player.UnityPlayer");
AndroidJavaObject thirdwebActivity = thirdwebActivityClass.GetStatic<AndroidJavaObject>("currentActivity");
thirdwebActivity.Call("OpenCustomTab", url);
AndroidJavaClass unityPlayer = new("com.unity3d.player.UnityPlayer");
AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
activity.Call("OpenCustomTab", url);
}

private void OnDeepLinkActivated(string url)
{
if (!url.StartsWith(_customScheme))
if (_taskCompletionSource.Task.IsCanceled || !url.StartsWith(_customScheme))
return;

_taskCompletionSource.SetResult(new BrowserResult(BrowserStatus.Success, url));
_taskCompletionSource.TrySetResult(new BrowserResult(BrowserStatus.Success, url));
}
}
}
Expand Down
36 changes: 30 additions & 6 deletions Assets/Thirdweb/Core/Scripts/Browser/StandaloneBrowser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public class StandaloneBrowser : IThirdwebBrowser
{
private TaskCompletionSource<BrowserResult> _taskCompletionSource;

private readonly HttpListener httpListener = new();

private readonly string closePageResponse =
@"
<html>
Expand Down Expand Up @@ -57,14 +59,17 @@ public async Task<BrowserResult> Login(string loginUrl, string redirectUrl, Canc
cancellationToken.Register(() =>
{
_taskCompletionSource?.TrySetCanceled();
StopHttpListener();
});

using var httpListener = new HttpListener();

try
{
redirectUrl = AddForwardSlashIfNecessary(redirectUrl);
httpListener.Prefixes.Add(redirectUrl);
if (httpListener.Prefixes.Count == 0 || !httpListener.Prefixes.Contains(redirectUrl))
{
httpListener.Prefixes.Clear();
httpListener.Prefixes.Add(redirectUrl);
}
httpListener.Start();
httpListener.BeginGetContext(IncomingHttpRequest, httpListener);

Expand All @@ -80,15 +85,35 @@ public async Task<BrowserResult> Login(string loginUrl, string redirectUrl, Canc
return new BrowserResult(BrowserStatus.Timeout, null, "The operation timed out.");
}
}
catch (TaskCanceledException)
{
return new BrowserResult(BrowserStatus.UserCanceled, null, "The operation was cancelled.");
}
catch (Exception ex)
{
return new BrowserResult(BrowserStatus.UnknownError, null, $"An error occurred: {ex.Message}");
}
finally
{
StopHttpListener();
}
}

private void StopHttpListener()
{
if (httpListener != null && httpListener.IsListening)
{
httpListener.Stop();
httpListener.Close();
}
}

private void IncomingHttpRequest(IAsyncResult result)
{
var httpListener = (HttpListener)result.AsyncState;
if (!httpListener.IsListening)
return;

var httpContext = httpListener.EndGetContext(result);
var httpRequest = httpContext.Request;
var httpResponse = httpContext.Response;
Expand All @@ -104,10 +129,9 @@ private void IncomingHttpRequest(IAsyncResult result)

private string AddForwardSlashIfNecessary(string url)
{
string forwardSlash = "/";
if (!url.EndsWith(forwardSlash))
if (!url.EndsWith("/"))
{
url += forwardSlash;
url += "/";
}
return url;
}
Expand Down
30 changes: 28 additions & 2 deletions Assets/Thirdweb/Core/Scripts/WalletsUI/InAppWalletUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using System.Linq;
using System.Collections.Generic;
using UnityEngine.Events;
using System.Threading;

namespace Thirdweb.Wallets
{
Expand All @@ -37,6 +38,7 @@ public class InAppWalletUI : MonoBehaviour
protected Exception _exception;
protected string _callbackUrl;
protected string _customScheme;
protected CancellationTokenSource _cancellationTokenSource;

#endregion

Expand Down Expand Up @@ -141,8 +143,16 @@ public virtual async Task<User> Connect(EmbeddedWallet embeddedWallet, string em
return _user;
}

[ContextMenu("Cancel")]
public virtual void Cancel()
{
if (_cancellationTokenSource != null && !_cancellationTokenSource.IsCancellationRequested)
{
_cancellationTokenSource.Cancel();
_cancellationTokenSource.Dispose();
_cancellationTokenSource = null;
}

_exception = new UnityException("User cancelled");
}

Expand Down Expand Up @@ -285,11 +295,27 @@ public virtual async Task LoginWithOauth(string authProviderStr)

string redirectUrl = Application.isMobilePlatform ? _customScheme : "http://localhost:8789/";
CrossPlatformBrowser browser = new();
var browserResult = await browser.Login(loginUrl, redirectUrl);
if (browserResult.status != BrowserStatus.Success)
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = new CancellationTokenSource();
var browserResult = await browser.Login(loginUrl, redirectUrl, _cancellationTokenSource.Token);

if (browserResult.status == BrowserStatus.UserCanceled)
{
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;
ThirdwebDebug.LogWarning("User cancelled login");
return;
}
else if (browserResult.status != BrowserStatus.Success)
{
_exception = new UnityException($"Failed to login with {authProviderStr}: {browserResult.status} | {browserResult.error}");
return;
}
else
{
_callbackUrl = browserResult.callbackUrl;
}

await new WaitUntil(() => _callbackUrl != null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4788,6 +4788,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
enabledWalletProviders: 07000000000000000100000002000000060000000300000004000000
useSmartWallets: 0
endSessionOnDisconnect: 0
onStart:
m_PersistentCalls:
m_Calls:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ public class WalletProviderUIDictionary : SerializableDictionaryBase<WalletProvi
[Header("Use ERC-4337 (Account Abstraction) compatible smart wallets.\nEnabling this will connect user to the associated smart wallet as per your ThirwebManager settings.")]
public bool useSmartWallets = false;

[Header("End session on disconnect. If enabled, user will have to re-authenticate on next connect.")]
public bool endSessionOnDisconnect = false;

[Header("Events")]
public UnityEvent onStart;
public UnityEvent<WalletConnection> onConnectionRequested;
Expand Down Expand Up @@ -165,7 +168,7 @@ public async void Disconnect()
{
_address = null;
_password = null;
await ThirdwebManager.Instance.SDK.Wallet.Disconnect(endSession: false);
await ThirdwebManager.Instance.SDK.Wallet.Disconnect(endSession: endSessionOnDisconnect);
onDisconnected.Invoke();
}
catch (System.Exception e)
Expand Down

0 comments on commit 890e617

Please sign in to comment.