Tweak in-app web browser login

- Use private browsing mode
- Use the Android User-Agent
- Use initial signin cookies
This commit is contained in:
Mbucari
2025-11-23 20:35:04 -07:00
parent 805f42b1cc
commit 04827f81da
4 changed files with 65 additions and 22 deletions

View File

@@ -5,7 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AudibleApi" Version="10.0.0.1" />
<PackageReference Include="AudibleApi" Version="10.1.0.1" />
<PackageReference Include="Google.Protobuf" Version="3.33.1" />
</ItemGroup>

View File

@@ -1,6 +1,7 @@
using AudibleApi;
using AudibleUtilities;
using Avalonia.Controls;
using Avalonia.Platform;
using Avalonia.Threading;
using LibationFileManager;
using LibationUiBase.Forms;
@@ -28,7 +29,7 @@ namespace LibationAvalonia.Dialogs.Login
{
try
{
if (Configuration.Instance.UseWebView && await BrowserLoginAsync(choiceIn.LoginUrl) is ChoiceOut external)
if (Configuration.Instance.UseWebView && await BrowserLoginAsync(choiceIn) is ChoiceOut external)
return external;
}
catch (Exception ex)
@@ -42,20 +43,19 @@ namespace LibationAvalonia.Dialogs.Login
: null;
}
private async Task<ChoiceOut?> BrowserLoginAsync(string url)
private async Task<ChoiceOut?> BrowserLoginAsync(ChoiceIn shoiceIn)
{
TaskCompletionSource<ChoiceOut?> tcs = new();
NativeWebDialog dialog = new()
{
Title = "Audible Login",
CanUserResize = true,
Source = new Uri(url)
CanUserResize = true
};
dialog.EnvironmentRequested += Dialog_EnvironmentRequested;
dialog.NavigationCompleted += Dialog_NavigationCompleted;
dialog.Closing += (_, _) => tcs.TrySetResult(null);
dialog.NavigationStarted += (_, e) =>
dialog.NavigationStarted += async (_, e) =>
{
if (e.Request?.AbsolutePath.StartsWith("/ap/maplanding") is true)
{
@@ -63,6 +63,16 @@ namespace LibationAvalonia.Dialogs.Login
dialog.Close();
}
};
dialog.AdapterCreated += (s, e) =>
{
if (dialog.TryGetCookieManager() is NativeWebViewCookieManager cookieManager)
{
foreach (System.Net.Cookie c in shoiceIn.SignInCookies)
cookieManager.AddOrUpdateCookie(c);
}
//Set the source only after loading cookies
dialog.Source = new Uri(shoiceIn.LoginUrl);
};
if (!Configuration.IsLinux && App.MainWindow is TopLevel topLevel)
dialog.Show(topLevel);
@@ -70,7 +80,27 @@ namespace LibationAvalonia.Dialogs.Login
dialog.Show();
return await tcs.Task;
}
void Dialog_EnvironmentRequested(object? sender, WebViewEnvironmentRequestedEventArgs e)
{
// Private browsing & user agent setting
switch (e)
{
case WindowsWebView2EnvironmentRequestedEventArgs webView2Args:
webView2Args.IsInPrivateModeEnabled = true;
webView2Args.AdditionalBrowserArguments = "--user-agent=\"" + Resources.User_Agent + "\"";
break;
case AppleWKWebViewEnvironmentRequestedEventArgs appleArgs:
appleArgs.NonPersistentDataStore = true;
appleArgs.ApplicationNameForUserAgent = Resources.User_Agent;
break;
case GtkWebViewEnvironmentRequestedEventArgs gtkArgs:
gtkArgs.EphemeralDataManager = true;
gtkArgs.ApplicationNameForUserAgent = Resources.User_Agent;
break;
}
}
}
private async void Dialog_NavigationCompleted(object? sender, WebViewNavigationCompletedEventArgs e)
{

View File

@@ -1,4 +1,6 @@
using Dinah.Core;
using AudibleApi;
using Dinah.Core;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
using System;
using System.Windows.Forms;
@@ -19,15 +21,32 @@ namespace LibationWinForms.Login
Controls.Add(webView);
webView.NavigationStarting += WebView_NavigationStarting;
webView.CoreWebView2InitializationCompleted += WebView_CoreWebView2InitializationCompleted;
this.SetLibationIcon();
}
}
public WebLoginDialog(string accountID, string loginUrl) : this()
public WebLoginDialog(string accountID, ChoiceIn choiceIn) : this()
{
this.accountID = ArgumentValidator.EnsureNotNullOrWhiteSpace(accountID, nameof(accountID));
webView.Source = new Uri(ArgumentValidator.EnsureNotNullOrWhiteSpace(loginUrl, nameof(loginUrl)));
ArgumentValidator.EnsureNotNullOrWhiteSpace(choiceIn?.LoginUrl, nameof(choiceIn));
this.Load += async (_, _) =>
{
//enable private browsing
var env = await CoreWebView2Environment.CreateAsync();
var options = env.CreateCoreWebView2ControllerOptions();
options.IsInPrivateModeEnabled = true;
await webView.EnsureCoreWebView2Async(env, options);
webView.CoreWebView2.Settings.UserAgent = Resources.User_Agent;
//Load init cookies
foreach (System.Net.Cookie cookie in choiceIn.SignInCookies ?? [])
{
webView.CoreWebView2.CookieManager.AddOrUpdateCookie(webView.CoreWebView2.CookieManager.CreateCookieWithSystemNetCookie(cookie));
}
webView.CoreWebView2.DOMContentLoaded += CoreWebView2_DOMContentLoaded;
Invoke(() => webView.Source = new Uri(choiceIn.LoginUrl));
};
}
private void WebView_NavigationStarting(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationStartingEventArgs e)
@@ -40,13 +59,7 @@ namespace LibationWinForms.Login
}
}
private void WebView_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
{
webView.CoreWebView2.DOMContentLoaded -= CoreWebView2_DOMContentLoaded;
webView.CoreWebView2.DOMContentLoaded += CoreWebView2_DOMContentLoaded;
}
private async void CoreWebView2_DOMContentLoaded(object sender, Microsoft.Web.WebView2.Core.CoreWebView2DOMContentLoadedEventArgs e)
private async void CoreWebView2_DOMContentLoaded(object sender, CoreWebView2DOMContentLoadedEventArgs e)
{
await webView.ExecuteScriptAsync(getScript(accountID));
}

View File

@@ -28,7 +28,7 @@ namespace LibationWinForms.Login
{
try
{
using var weblogin = new WebLoginDialog(_account.AccountId, choiceIn.LoginUrl);
using var weblogin = new WebLoginDialog(_account.AccountId, choiceIn);
if (ShowDialog(weblogin))
return Task.FromResult(ChoiceOut.External(weblogin.ResponseUrl));
}