Skip to content

Commit bd924c4

Browse files
linesightclaude
andcommitted
docs(linux): correct version-tagged comments with actual upstream history
Three comments in src/cefpython.pyx and src/window_info.pyx carried "CEF 123+" or "CEF 146+" attributions that were imprecise (added by the user during cefpython 123/146 bring-up rather than reflecting an actual upstream behavior change at those versions). Replaced each with a comment grounded in the real upstream commit and the actual mechanism observed. - CreateBrowserSync: CefCurrentlyOn(TID_UI) comment — the public API has always returned false + LOG(WARNING) when no task runner is registered (libcef/common/task_impl.cc:13). Drop the "CEF 146+" tag and explain why cefpython's defer-until-OnContextInitialized flow reaches this code before BrowserThread::UI is established. - CreateBrowserSync: OnContextInitialized defer comment — the wait requirement comes from CEF commit 691c9c2 ("Wait for CefBrowserContext initialization", 2021-04-14, issue #2969), not CEF 123. Symptom is the renderer's first IPC message (blink.mojom.WidgetHost) being rejected before host bindings are wired. Strategy section now documents that Linux skips the manual pump deliberately to keep Initialize() non-blocking — empirical testing on current cefpython shows the pump *does* fire OnContextInitialized in 2-3s on both Ozone X11 and Wayland, so the historical "needs gtk_main()" claim is no longer accurate, but we still skip to avoid the latency. - window_info.pyx: drop the four duplicate "# CEF 123+: must request Alloy runtime" lines and consolidate into one function-level note in SetCefWindowInfo. The runtime_style field on cef_window_info_t actually arrived in CEF commit dca0435d2 ("chrome: Add support for Alloy style browsers and windows", issue #3681, 2024-04-17), first shipping in CEF branch 6422 (~Chromium 125, May 2024) — well after CEF 123, where the field did not exist. The note also explains why Alloy style is required: chrome bootstrap default (since branch 6478) makes windowed parent windows default to Chrome style, which can't be parented via SetAsChild and would change the callback model. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent db13d7d commit bd924c4

2 files changed

Lines changed: 60 additions & 14 deletions

File tree

src/cefpython.pyx

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -676,12 +676,18 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs):
676676
# Use a generous ceiling (30s) for CI environments where utility
677677
# subprocesses (storage service) crash and delay context initialization.
678678
if ret:
679-
# On Linux, skip this pump entirely: the Ozone X11 backend needs
680-
# gtk_main() (a blocking GLib main loop) running before
681-
# OnContextInitialized can fire. The external caller (hello_world.py,
682-
# test harnesses) must enter gtk_main() immediately after Initialize()
683-
# and drive the loop via the GLib timer callback.
684-
# On Windows/macOS, pump up to 30 s as before.
679+
# On Linux, skip this pump entirely. Empirical testing shows manual
680+
# CefDoMessageLoopWork() *does* fire OnContextInitialized within 2-3s
681+
# on both Ozone X11 and Ozone Wayland in the current cefpython
682+
# configuration, so the historical "needs gtk_main()" claim is no
683+
# longer accurate — but we still skip it deliberately to keep
684+
# Initialize() non-blocking on Linux. The user enters
685+
# cef.MessageLoop() (gtk_main on X11, GLib loop on Wayland) right
686+
# after Initialize() returns; OnContextInitialized fires there and
687+
# BrowserProcessHandler_OnContextInitialized drains
688+
# g_pending_browsers. This avoids a 2-3s startup latency hit on
689+
# the common case and a 30s block in edge cases.
690+
# On Windows/macOS, pump up to 30s as before.
685691
IF UNAME_SYSNAME != "Linux":
686692
for _ in range(3000):
687693
with nogil:
@@ -731,11 +737,34 @@ def CreateBrowserSync(windowInfo=None,
731737
# plus its own thread checks internally, so a Python-side assert
732738
# would only catch the same condition with a worse error message.
733739

734-
# Defer browser creation until OnContextInitialized fires inside MessageLoop.
735-
# In CEF 123+, browser creation before OnContextInitialized causes
736-
# blink.mojom.WidgetHost rejection and renderer shows no content.
737-
# Initialize() pumps the loop for up to 30s; if still not initialized
738-
# (e.g. slow CI), pump an additional 30s before giving up.
740+
# Defer browser creation until OnContextInitialized fires.
741+
#
742+
# CefBrowserContext initialization is asynchronous: it is not finished
743+
# when CefInitialize() returns, especially when external_message_pump
744+
# is in use (our default — see _linux_apply_initialize_defaults). The
745+
# OnContextInitialized callback is the documented signal that the
746+
# browser context is ready (see upstream CEF commit 691c9c2 "Wait for
747+
# CefBrowserContext initialization", 2021-04-14, issue #2969 — added
748+
# the explicit wait when Chrome runtime introduced async Profile init).
749+
#
750+
# Calling CefBrowserHost::CreateBrowserSync before that point lets the
751+
# renderer come up before its host bindings are wired, and the
752+
# browser-process side then rejects the renderer's first IPC message
753+
# with a "blink.mojom.WidgetHost" / "Message N rejected by interface"
754+
# mojo error. The visible symptom is a blank page.
755+
#
756+
# Strategy:
757+
# * Windows / macOS: cefpython.Initialize() already pumps up to 30s
758+
# waiting for OnContextInitialized. If a caller reaches
759+
# CreateBrowserSync earlier anyway (slow CI, custom Initialize
760+
# override), pump another 30s here before giving up.
761+
# * Linux (X11 and Wayland Ozone backends): skip the local pump,
762+
# mirroring Initialize(). The deferred path always works: queue
763+
# the request and let BrowserProcessHandler_OnContextInitialized
764+
# drain it once cef.MessageLoop() starts the GLib loop.
765+
# When this falls through still uninitialised, queue the request in
766+
# g_pending_browsers for the OnContextInitialized handler to drain
767+
# once the loop is actually running.
739768
if not g_context_initialized:
740769
Debug("CreateBrowserSync(): OnContextInitialized not yet received,"
741770
" pumping message loop")

src/window_info.pyx

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,26 @@ cdef void SetCefWindowInfo(
88
CefWindowInfo& cefWindowInfo,
99
WindowInfo windowInfo
1010
) except *:
11+
# Note on runtime_style = CEF_RUNTIME_STYLE_ALLOY (set below in every
12+
# windowed branch):
13+
#
14+
# The cef_window_info_t.runtime_style field was added in CEF
15+
# commit dca0435d2 "chrome: Add support for Alloy style browsers
16+
# and windows" (issue #3681, 2024-04-17, first shipping in CEF
17+
# branch 6422 / Chromium 125). See the enum doc in
18+
# include/internal/cef_types_runtime.h: Chrome style provides the
19+
# full Chrome UI; Alloy style provides the content-layer view with
20+
# additional client callbacks and supports windowless rendering.
21+
#
22+
# Since the chrome bootstrap (the default for CEF builds since
23+
# branch 6478 / Chromium 125) makes windowed parent windows default
24+
# to Chrome style, cefpython must opt back into Alloy style
25+
# explicitly. Without it, SetAsChild() would get a Chrome-style
26+
# Views window that can't be parented into the host GTK/Qt window,
27+
# and the LifeSpanHandler / RequestHandler / etc. callbacks
28+
# cefpython exposes would not fire as expected. Off-screen
29+
# rendering is documented to always use Alloy style anyway, but the
30+
# field is harmless to set there too.
1131
if not windowInfo.windowType:
1232
raise Exception("WindowInfo: windowType is not set")
1333

@@ -42,7 +62,6 @@ cdef void SetCefWindowInfo(
4262
cefWindowInfo.SetAsChild(
4363
<CefWindowHandle>windowInfo.parentWindowHandle,
4464
windowRect)
45-
# CEF 123+: must request Alloy runtime for native windowed rendering.
4665
cefWindowInfo.runtime_style = CEF_RUNTIME_STYLE_ALLOY
4766
ELIF UNAME_SYSNAME == "Darwin":
4867
x = int(windowInfo.windowRect[0])
@@ -63,7 +82,6 @@ cdef void SetCefWindowInfo(
6382
cefWindowInfo.SetAsChild(
6483
<CefWindowHandle>windowInfo.parentWindowHandle,
6584
windowRect)
66-
# CEF 123+: must request Alloy runtime for native windowed rendering.
6785
cefWindowInfo.runtime_style = CEF_RUNTIME_STYLE_ALLOY
6886

6987
# POPUP WINDOW - Windows only
@@ -73,7 +91,6 @@ cdef void SetCefWindowInfo(
7391
cefWindowInfo.SetAsPopup(
7492
<CefWindowHandle>windowInfo.parentWindowHandle,
7593
windowName)
76-
# CEF 123+: must request Alloy runtime for native windowed rendering.
7794
cefWindowInfo.runtime_style = CEF_RUNTIME_STYLE_ALLOY
7895

7996
if windowInfo.windowType == "offscreen":

0 commit comments

Comments
 (0)