From 2c0a82b0cc8a7312d5edbe2ef6f46c86c4fc69f9 Mon Sep 17 00:00:00 2001
From: Marek Habersack <grendel@twistedcode.net>
Date: Tue, 3 Jan 2023 11:39:38 +0100
Subject: [PATCH 1/4] Wrap connection exceptions in HttpRequestException

Fixes: https://github.com/xamarin/xamarin-android/issues/7629

Whenever a Java backend connection fails for any reason, we wrap the
thrown exception in `HttpRequestException` as described in the
`HttpClient.SendAsync` documentation.
---
 .../Xamarin.Android.Net/AndroidMessageHandler.cs            | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs b/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs
index b990aa50e4f..c58152dcd7c 100644
--- a/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs
+++ b/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs
@@ -493,7 +493,11 @@ Task ConnectAsync (HttpURLConnection httpConnection, CancellationToken ct)
 						Logger.Log (LogLevel.Info, LOG_APP, $"Exception caught while cancelling connection: {ex}");
 						ct.ThrowIfCancellationRequested ();
 					}
-					throw;
+
+					// All exceptions related to connectivity should be wrapped in HttpRequestException. In theory it is possible that the exception will be
+					// thrown for another reason above, but it's OK to wrap it in HttpRequestException anyway, since we're working in the context of
+					// `ConnectAsync` which, from the end user's point of view, is 100% related to connectivity.
+					throw new HttpRequestException ("Connection failure", ex);
 				}
 			}, ct);
 		}

From e155a5099ddf8cfa670bd15659f52e03662722d6 Mon Sep 17 00:00:00 2001
From: Marek Habersack <grendel@twistedcode.net>
Date: Thu, 26 Jan 2023 09:59:43 +0100
Subject: [PATCH 2/4] Catch an extra exception in tests

---
 .../Xamarin.Android.Net/AndroidMessageHandlerTests.cs       | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs b/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs
index 2f1517d57c6..ce5e15c7ce6 100644
--- a/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs
+++ b/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs
@@ -139,7 +139,11 @@ private async Task AssertRejectsRemoteCertificate (Func<Task> makeRequest)
 				Assert.Fail ("The request wasn't rejected");
 			}
 #if NET
-			catch (System.Net.WebException ex) {}
+			// While technically we should be throwing only HttpRequestException (as per HttpClient.SendAsync docs), in reality
+			// we need to consider legacy code that migrated to .NET and may still expect WebException.  Thus, we throw both
+			// of these and we need to catch both here
+			catch (System.Net.WebException) {}
+			catch (System.Net.HttpRequestException) {}
 #else
 			catch (Java.IO.IOException) {}
 #endif

From a90eaaf7792abd6fd8f1e8028d6276d9d9f23810 Mon Sep 17 00:00:00 2001
From: Marek Habersack <grendel@twistedcode.net>
Date: Thu, 26 Jan 2023 17:19:14 +0100
Subject: [PATCH 3/4] Catch `System.Net.HttpRequestException` in both classic
 and .net

---
 .../Xamarin.Android.Net/AndroidMessageHandlerTests.cs           | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs b/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs
index ce5e15c7ce6..e8a09dbc918 100644
--- a/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs
+++ b/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs
@@ -143,10 +143,10 @@ private async Task AssertRejectsRemoteCertificate (Func<Task> makeRequest)
 			// we need to consider legacy code that migrated to .NET and may still expect WebException.  Thus, we throw both
 			// of these and we need to catch both here
 			catch (System.Net.WebException) {}
-			catch (System.Net.HttpRequestException) {}
 #else
 			catch (Java.IO.IOException) {}
 #endif
+			catch (System.Net.HttpRequestException) {}
 		}
 	}
 }

From 95a410ad96ce71cbd04fd341aebfd0708abbf8e1 Mon Sep 17 00:00:00 2001
From: Marek Habersack <grendel@twistedcode.net>
Date: Thu, 26 Jan 2023 18:16:52 +0100
Subject: [PATCH 4/4] Use correct type name

---
 .../Xamarin.Android.Net/AndroidMessageHandlerTests.cs           | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs b/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs
index e8a09dbc918..c15b8292c36 100644
--- a/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs
+++ b/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs
@@ -146,7 +146,7 @@ private async Task AssertRejectsRemoteCertificate (Func<Task> makeRequest)
 #else
 			catch (Java.IO.IOException) {}
 #endif
-			catch (System.Net.HttpRequestException) {}
+			catch (System.Net.Http.HttpRequestException) {}
 		}
 	}
 }
