Summary
Found while adding coverage for native/url_request_client.cpp (a CefURLRequest is explicitly documented as "not associated with a browser instance"). Registering a global CefApp.registerSchemeHandlerFactory() and then using it to serve a standalone CefURLRequest (rather than a browser navigation) crashes the Debug build:
FATAL:native/jni_scoped_helpers.h:639] Check failed: created_handle_.
Root cause
native/scheme_handler_factory.cpp's SchemeHandlerFactory::Create():
ScopedJNIFrame jframe(env, frame);
jframe.SetTemporary();
calls SetTemporary() unconditionally. ScopedJNIObject's constructor only sets created_handle_ = true when its obj (here, frame) is non-null:
if (obj) {
jhandle_ = NewJNIObject(env_, jni_class_name);
if (jhandle_) {
created_handle_ = true;
...
For a standalone CefURLRequest, CEF calls CefSchemeHandlerFactory::Create() with a null frame (there is no real CefFrame -- no browser navigation is involved), so created_handle_ stays false, and the subsequent unconditional jframe.SetTemporary() trips DCHECK(created_handle_) in SetTemporary() itself (jni_scoped_helpers.h:639).
Impact
Debug/ENABLE_COVERAGE-build only (release builds don't compile DCHECKs in, per this fork's usual pattern for this class of bug -- see #9/#20/#21). Any application combining a globally-registered CefSchemeHandlerFactory with a browser-independent CefURLRequest against a matching scheme/domain would hit this in a Debug CEF build.
Suggested fix
Guard both SetTemporary() calls in SchemeHandlerFactory::Create() on whether the corresponding ScopedJNIObject actually got a handle, e.g.:
ScopedJNIFrame jframe(env, frame);
if (frame) jframe.SetTemporary();
(and the same for jrequest, if request can plausibly be null too -- not confirmed either way this session).
Repro
CefURLRequestTest.realCompletionFiresRequestCompleteAndDownloadData() in this fork -- registers a scheme handler factory, then creates a standalone CefURLRequest against a matching URL. Currently @Disabled for the Debug/coverage build; passes cleanly in the Release build (no DCHECKs compiled in), confirmed via repeated full-suite runs.
Summary
Found while adding coverage for
native/url_request_client.cpp(aCefURLRequestis explicitly documented as "not associated with a browser instance"). Registering a globalCefApp.registerSchemeHandlerFactory()and then using it to serve a standaloneCefURLRequest(rather than a browser navigation) crashes the Debug build:Root cause
native/scheme_handler_factory.cpp'sSchemeHandlerFactory::Create():ScopedJNIFrame jframe(env, frame); jframe.SetTemporary();calls
SetTemporary()unconditionally.ScopedJNIObject's constructor only setscreated_handle_ = truewhen itsobj(here,frame) is non-null:For a standalone
CefURLRequest, CEF callsCefSchemeHandlerFactory::Create()with a nullframe(there is no realCefFrame-- no browser navigation is involved), socreated_handle_staysfalse, and the subsequent unconditionaljframe.SetTemporary()tripsDCHECK(created_handle_)inSetTemporary()itself (jni_scoped_helpers.h:639).Impact
Debug/
ENABLE_COVERAGE-build only (release builds don't compileDCHECKs in, per this fork's usual pattern for this class of bug -- see #9/#20/#21). Any application combining a globally-registeredCefSchemeHandlerFactorywith a browser-independentCefURLRequestagainst a matching scheme/domain would hit this in a Debug CEF build.Suggested fix
Guard both
SetTemporary()calls inSchemeHandlerFactory::Create()on whether the correspondingScopedJNIObjectactually got a handle, e.g.:(and the same for
jrequest, ifrequestcan plausibly be null too -- not confirmed either way this session).Repro
CefURLRequestTest.realCompletionFiresRequestCompleteAndDownloadData()in this fork -- registers a scheme handler factory, then creates a standaloneCefURLRequestagainst a matching URL. Currently@Disabledfor the Debug/coverage build; passes cleanly in the Release build (noDCHECKs compiled in), confirmed via repeated full-suite runs.