Skip to content

CefQueryCallback.success() ignores persistent=true, clears native ref after first call (matches upstream #398) #13

Description

@Thrameos

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):

  1. Register a CefMessageRouterHandler whose onQuery() saves the CefQueryCallback and calls callback.success("first") once for a query sent with persistent: true.
  2. Once the JS onSuccess handler's first invocation is observed (via a title change), call savedCallback.success("second") again from Java.
  3. 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."

Activity

  1. added a commit that references this issue on Aug 29, 2026
  2. Thrameos commented on Aug 31, 2026

    @Thrameos
    OwnerAuthor

    Fixed. native/CefQueryCallback_N.cpp's N_Success unconditionally called ClearSelf() after the first call, regardless of whether the originating query was persistent -- so a second success() call on the same callback silently no-op'd (native ref already torn down).

    Fix: threaded the persistent flag (already available in MessageRouterHandler::OnQuery(), matching CEF's own persistent tracking) through to the Java-side CefQueryCallback_N object via a new package-private setPersistent() call made right after the callback object is constructed, before onQuery() is invoked. success() now passes that flag to N_Success, which only calls ClearSelf() when the query is not persistent. N_Failure is unchanged -- a failure always ends the query regardless of persistent.

    Un-disabled the existing UpstreamIssue398Test regression test (previously @disabled with a confirmed-failing reproduction). Verified failing before the fix and passing after.

  3. added 3 commits that reference this issue on Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions