Summary
Confirmed locally, reproduces on this fork's current CEF version (146.0.10+g8219561+chromium-146.0.7680.179): matches upstream chromiumembedded/java-cef#398, still open there, originally reported against CEF 87.1.12 -- still present ~7 major CEF versions later.
The CEF message router's "subscription" style query workflow (JS sets persistent: true in the window.cefQuery() options) is documented to allow CefQueryCallback.success() to be called repeatedly, with each call invoking the JS onSuccess handler again.
native/CefQueryCallback_N.cpp's N_Success unconditionally calls ClearSelf() after the first call, regardless of persistent:
JNIEXPORT void JNICALL
Java_org_cef_callback_CefQueryCallback_1N_N_1Success(JNIEnv* env, jobject obj, jlong self,
jstring response) {
CefRefPtr<CefQueryCallback> callback = GetSelf(self);
if (!callback)
return;
callback->Success(GetJNIString(env, response));
ClearSelf(env, obj); // <-- unconditional, ignores |persistent|
}
ClearSelf() nulls the Java-side native handle field, so a second success() call on the same CefQueryCallback object silently no-ops (GetSelf() returns null, the if (!callback) return; guard swallows it) -- not a crash, just silently broken. The JS onSuccess handler is never invoked a second time no matter how many more times Java calls success().
Repro
Added java/tests/junittests/UpstreamIssue398Test.java (currently @Disabled with a link to this issue, so it doesn't fail the normal suite -- remove @Disabled to re-run it):
- Register a
CefMessageRouterHandler whose onQuery() saves the CefQueryCallback and calls callback.success("first") once for a query sent with persistent: true.
- Once the JS
onSuccess handler's first invocation is observed (via a title change), call savedCallback.success("second") again from Java.
- Expected: JS
onSuccess fires again with "second". Actual: it never fires again -- the test times out waiting for it (confirmed via TestFrame's watchdog cleanly force-closing after 10s, not a real hang).
Fix sketch (not implemented here)
N_Success (and likely N_Failure, though Failure ending a query legitimately should always clear regardless of persistent) needs to know whether the original query was persistent, and skip ClearSelf() in that case -- the native CefMessageRouterBrowserSide::Callback itself is designed to support this (that's what upstream's persistent JS flag threads through to on the C++ side); the bug is specifically in this JNI wrapper discarding that distinction.
Found via
This fork's coverage-expansion effort (tracked in #5), while triaging upstream's issue tracker for bugs that could become regression tests in this fork's suite per the user's explicit direction to "start harvesting the upstream git issues for problematic tests."
Summary
Confirmed locally, reproduces on this fork's current CEF version (146.0.10+g8219561+chromium-146.0.7680.179): matches upstream chromiumembedded/java-cef#398, still open there, originally reported against CEF 87.1.12 -- still present ~7 major CEF versions later.
The CEF message router's "subscription" style query workflow (JS sets
persistent: truein thewindow.cefQuery()options) is documented to allowCefQueryCallback.success()to be called repeatedly, with each call invoking the JSonSuccesshandler again.native/CefQueryCallback_N.cpp'sN_Successunconditionally callsClearSelf()after the first call, regardless ofpersistent:ClearSelf()nulls the Java-side native handle field, so a secondsuccess()call on the sameCefQueryCallbackobject silently no-ops (GetSelf()returns null, theif (!callback) return;guard swallows it) -- not a crash, just silently broken. The JSonSuccesshandler is never invoked a second time no matter how many more times Java callssuccess().Repro
Added
java/tests/junittests/UpstreamIssue398Test.java(currently@Disabledwith a link to this issue, so it doesn't fail the normal suite -- remove@Disabledto re-run it):CefMessageRouterHandlerwhoseonQuery()saves theCefQueryCallbackand callscallback.success("first")once for a query sent withpersistent: true.onSuccesshandler's first invocation is observed (via a title change), callsavedCallback.success("second")again from Java.onSuccessfires again with"second". Actual: it never fires again -- the test times out waiting for it (confirmed viaTestFrame's watchdog cleanly force-closing after 10s, not a real hang).Fix sketch (not implemented here)
N_Success(and likelyN_Failure, thoughFailureending a query legitimately should always clear regardless ofpersistent) needs to know whether the original query was persistent, and skipClearSelf()in that case -- the nativeCefMessageRouterBrowserSide::Callbackitself is designed to support this (that's what upstream'spersistentJS flag threads through to on the C++ side); the bug is specifically in this JNI wrapper discarding that distinction.Found via
This fork's coverage-expansion effort (tracked in #5), while triaging upstream's issue tracker for bugs that could become regression tests in this fork's suite per the user's explicit direction to "start harvesting the upstream git issues for problematic tests."