commit 4ebd88606b72b89cae5ed2b7d37b96a84635ff3d
parent dc1c78e9c37aba6ed05a4ec47c4bfcb16f57b51d
Author: Makoto Kato <m_kato@ga2.so-net.ne.jp>
Date: Wed, 8 Oct 2025 06:53:10 +0000
Bug 1989882 - Add about:crashcontentjava to cause uncaught exception in Java. r=geckoview-reviewers,ohall
Actually, we have a native's crash handler and Java's crash handler. Java's
crash handler (`GeckoCrashHandler`) will call `MOZ_CRASH`, but we don't have
this test.
So I would like to add `about:contentcrashjava` to cause uncaught exception.
This is useful to test isolated process.
Differential Revision: https://phabricator.services.mozilla.com/D265736
Diffstat:
6 files changed, 59 insertions(+), 2 deletions(-)
diff --git a/docshell/base/nsAboutRedirector.cpp b/docshell/base/nsAboutRedirector.cpp
@@ -16,6 +16,10 @@
#include "mozilla/dom/RemoteType.h"
#include "mozilla/gfx/GPUProcessManager.h"
+#ifdef MOZ_WIDGET_ANDROID
+# include "mozilla/java/GeckoAppShellWrappers.h"
+#endif
+
#define ABOUT_CONFIG_ENABLED_PREF "general.aboutConfig.enable"
NS_IMPL_ISUPPORTS(nsAboutRedirector, nsIAboutModule)
@@ -49,6 +53,12 @@ class CrashChannel final : public nsBaseChannel {
MOZ_CRASH("Crash via about:crashcontent");
}
+#ifdef MOZ_WIDGET_ANDROID
+ if (spec.EqualsASCII("about:crashcontentjava") && XRE_IsContentProcess()) {
+ mozilla::java::GeckoAppShell::CrashByUncaughtException();
+ }
+#endif
+
if (spec.EqualsASCII("about:crashextensions") && XRE_IsParentProcess()) {
using ContentParent = mozilla::dom::ContentParent;
nsTArray<RefPtr<ContentParent>> toKill;
@@ -222,6 +232,13 @@ static const RedirEntry kRedirMap[] = {
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::URI_CAN_LOAD_IN_CHILD |
nsIAboutModule::URI_MUST_LOAD_IN_CHILD},
+#ifdef MOZ_WIDGET_ANDROID
+ {"crashcontentjava", "about:blank",
+ nsIAboutModule::HIDE_FROM_ABOUTABOUT |
+ nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
+ nsIAboutModule::URI_CAN_LOAD_IN_CHILD |
+ nsIAboutModule::URI_MUST_LOAD_IN_CHILD},
+#endif
{"crashgpu", "about:blank", nsIAboutModule::HIDE_FROM_ABOUTABOUT},
{"crashextensions", "about:blank", nsIAboutModule::HIDE_FROM_ABOUTABOUT}};
static const int kRedirTotal = std::size(kRedirMap);
@@ -241,7 +258,11 @@ nsAboutRedirector::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo,
NS_ENSURE_SUCCESS(rv, rv);
if (path.EqualsASCII("crashparent") || path.EqualsASCII("crashcontent") ||
- path.EqualsASCII("crashgpu") || path.EqualsASCII("crashextensions")) {
+ path.EqualsASCII("crashgpu") || path.EqualsASCII("crashextensions")
+#ifdef MOZ_WIDGET_ANDROID
+ || path.EqualsASCII("crashcontentjava")
+#endif
+ ) {
bool isExternal;
aLoadInfo->GetLoadTriggeredFromExternal(&isExternal);
if (isExternal || !aLoadInfo->TriggeringPrincipal() ||
diff --git a/docshell/build/components.conf b/docshell/build/components.conf
@@ -43,6 +43,7 @@ if buildconfig.substs['MOZ_WIDGET_TOOLKIT'] != 'android':
if buildconfig.substs['MOZ_WIDGET_TOOLKIT'] != 'android':
about_pages.append('translations')
if buildconfig.substs['MOZ_WIDGET_TOOLKIT'] == 'android':
+ about_pages.append('crashcontentjava')
about_pages.append('home')
if buildconfig.substs['MOZ_WIDGET_TOOLKIT'] == 'windows':
about_pages.append('third-party')
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt
@@ -39,6 +39,7 @@ open class BaseSessionTest(
const val CLICK_TO_REPLACE_HTML_PATH = "/assets/www/clickToReplace.html"
const val CLIPBOARD_READ_HTML_PATH = "/assets/www/clipboard_read.html"
const val CONTENT_CRASH_URL = "about:crashcontent"
+ const val CONTENT_CRASH_JAVA_URL = "about:crashcontentjava"
const val DND_HTML_PATH = "/assets/www/dnd.html"
const val DND_XORIGIN_HTML_PATH = "/assets/www/dnd_xorigin.html"
const val DOWNLOAD_HTML_PATH = "/assets/www/download.html"
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentCrashTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentCrashTest.kt
@@ -44,6 +44,24 @@ class ContentCrashTest : BaseSessionTest() {
assertTrue(evalResult.mMsg, evalResult.mResult)
}
+ @IgnoreCrash
+ @Test
+ fun crashContentJava() {
+ // We need the crash reporter for this test
+ assumeTrue(BuildConfig.MOZ_CRASHREPORTER)
+
+ // TODO: bug 1710940
+ assumeThat(sessionRule.env.isIsolatedProcess, Matchers.equalTo(false))
+
+ mainSession.loadUri(CONTENT_CRASH_JAVA_URL)
+ // Default handler will call MOZ_CRASH by GeckoAppShell.reportJavaCrash
+ mainSession.waitUntilCalled(ContentDelegate::class, "onCrash")
+
+ // This test is really slow so we allow double the usual timeout
+ var evalResult = client.getEvalResult(env.defaultTimeoutMillis * 2)
+ assertTrue(evalResult.mMsg, evalResult.mResult)
+ }
+
@After
fun teardown() {
client.disconnect()
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
@@ -1770,6 +1770,18 @@ public class GeckoAppShell {
}
@WrapForJNI
+ private static void crashByUncaughtException() {
+ final Thread crashThread =
+ new Thread("UncaughtExceptionThread") {
+ @Override
+ public void run() {
+ throw new IllegalStateException();
+ }
+ };
+ crashThread.start();
+ }
+
+ @WrapForJNI
public static native boolean isParentProcess();
@WrapForJNI
diff --git a/netwerk/ipc/DocumentChannel.cpp b/netwerk/ipc/DocumentChannel.cpp
@@ -173,7 +173,11 @@ static bool URIUsesDocChannel(nsIURI* aURI) {
}
nsCString spec = aURI->GetSpecOrDefault();
- return !spec.EqualsLiteral("about:crashcontent");
+ return
+#ifdef MOZ_WIDGET_ANDROID
+ !spec.EqualsLiteral("about:crashcontentjava") &&
+#endif
+ !spec.EqualsLiteral("about:crashcontent");
}
bool DocumentChannel::CanUseDocumentChannel(nsIURI* aURI) {