From 04827f81da3f1e2a21120d9f8d90f1ea7dd45157 Mon Sep 17 00:00:00 2001
From: Mbucari <37587114+Mbucari@users.noreply.github.com>
Date: Sun, 23 Nov 2025 20:35:04 -0700
Subject: [PATCH] Tweak in-app web browser login
- Use private browsing mode
- Use the Android User-Agent
- Use initial signin cookies
---
.../AudibleUtilities/AudibleUtilities.csproj | 2 +-
.../Dialogs/Login/AvaloniaLoginChoiceEager.cs | 44 ++++++++++++++++---
.../Dialogs/Login/WebLoginDialog.cs | 39 ++++++++++------
.../Dialogs/Login/WinformLoginChoiceEager.cs | 2 +-
4 files changed, 65 insertions(+), 22 deletions(-)
diff --git a/Source/AudibleUtilities/AudibleUtilities.csproj b/Source/AudibleUtilities/AudibleUtilities.csproj
index 248de155..d6738b72 100644
--- a/Source/AudibleUtilities/AudibleUtilities.csproj
+++ b/Source/AudibleUtilities/AudibleUtilities.csproj
@@ -5,7 +5,7 @@
-
+
diff --git a/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginChoiceEager.cs b/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginChoiceEager.cs
index acc8d686..86e7d4fb 100644
--- a/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginChoiceEager.cs
+++ b/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginChoiceEager.cs
@@ -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 BrowserLoginAsync(string url)
+ private async Task BrowserLoginAsync(ChoiceIn shoiceIn)
{
TaskCompletionSource 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)
{
diff --git a/Source/LibationWinForms/Dialogs/Login/WebLoginDialog.cs b/Source/LibationWinForms/Dialogs/Login/WebLoginDialog.cs
index 2eb9ca36..b54b3d5c 100644
--- a/Source/LibationWinForms/Dialogs/Login/WebLoginDialog.cs
+++ b/Source/LibationWinForms/Dialogs/Login/WebLoginDialog.cs
@@ -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));
}
diff --git a/Source/LibationWinForms/Dialogs/Login/WinformLoginChoiceEager.cs b/Source/LibationWinForms/Dialogs/Login/WinformLoginChoiceEager.cs
index e121c483..80842dbb 100644
--- a/Source/LibationWinForms/Dialogs/Login/WinformLoginChoiceEager.cs
+++ b/Source/LibationWinForms/Dialogs/Login/WinformLoginChoiceEager.cs
@@ -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));
}