Skip to content

Commit 985d2ba

Browse files
linesightclaude
andcommitted
Create the browser immediately after Initialize() instead of via OnContextInitialized
Revert the browser-creation-timing workaround. Under cefpython's single-threaded message loop the Chrome runtime initializes the browser context during CefInitialize(), so CreateBrowserSync() can be called immediately after Initialize() returns and runs synchronously. This is the pre-existing pattern and keeps the examples and unit-test harness simple, with no global client callback, no deferred-embed helpers, and no polling. - cefpython.pyx: drop the CreateBrowserSync() guard that required the context callback and drop OnContextInitialized from the SetGlobalClientCallback allow-list. - Remove the now-unused OnContextInitialized wiring entirely: the g_context_initialized flag (cefpython.pyx), the BrowserProcessHandler_OnContextInitialized function (browser_process_handler.pyx), and its call in subprocess/cefpython_app.cpp. - Restore immediate browser creation in all examples and in the main/osr/issue517 unit tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent bc3ae65 commit 985d2ba

27 files changed

Lines changed: 189 additions & 572 deletions

examples/gtk2.py

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,11 @@
3333
MESSAGE_LOOP_CEF = 2 # Pass --message-loop-cef flag to script on Linux
3434
g_message_loop = None
3535

36-
# Under CEF's Chrome runtime the browser context initializes asynchronously,
37-
# so a browser can only be created after OnContextInitialized has fired. These
38-
# module-level helpers coordinate that: embed_browser() defers itself until the
39-
# context is ready, and the callback below runs any deferred embed.
40-
g_context_initialized = False
41-
g_pending_embed = None
42-
43-
44-
def _on_context_initialized():
45-
global g_context_initialized
46-
g_context_initialized = True
47-
if g_pending_embed is not None:
48-
g_pending_embed()
49-
5036

5137
def main():
5238
check_versions()
5339
sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error
5440
configure_message_loop()
55-
# Register before cef.Initialize(); OnContextInitialized may fire during it.
56-
cef.SetGlobalClientCallback("OnContextInitialized",
57-
_on_context_initialized)
5841
cef.Initialize()
5942
gobject.threads_init()
6043
Gtk2Example()
@@ -125,13 +108,6 @@ def __init__(self):
125108
gobject.timeout_add(10, self.on_timer)
126109

127110
def embed_browser(self):
128-
global g_pending_embed
129-
if not g_context_initialized:
130-
# Chrome runtime initializes the browser context asynchronously;
131-
# embed once OnContextInitialized fires (see main()).
132-
g_pending_embed = self.embed_browser
133-
return
134-
g_pending_embed = None
135111
windowInfo = cef.WindowInfo()
136112
size = self.main_window.get_size()
137113
rect = [0, 0, size[0], size[1]]

examples/gtk3.py

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,6 @@
3434
from gi.repository import GdkX11
3535

3636

37-
# Under CEF's Chrome runtime the browser context initializes asynchronously,
38-
# so a browser can only be created after OnContextInitialized has fired. These
39-
# module-level helpers coordinate that: embed_browser() defers itself until the
40-
# context is ready, and the callback below runs any deferred embed.
41-
g_context_initialized = False
42-
g_pending_embed = None
43-
44-
45-
def _on_context_initialized():
46-
global g_context_initialized
47-
g_context_initialized = True
48-
if g_pending_embed is not None:
49-
g_pending_embed()
50-
51-
5237
def main():
5338
print("[gkt3.py] CEF Python {ver}".format(ver=cef.__version__))
5439
print("[gkt3.py] Python {ver} {arch}".format(
@@ -62,9 +47,6 @@ def main():
6247
# > Python[57738:d07] _createMenuRef called with existing principal
6348
# > MenuRef already associated with menu
6449
sys.excepthook = cef.ExceptHook # To shutdown CEF processes on error
65-
# Register before cef.Initialize(); OnContextInitialized may fire during it.
66-
cef.SetGlobalClientCallback("OnContextInitialized",
67-
_on_context_initialized)
6850
cef.Initialize()
6951
app = Gtk3Example()
7052
SystemExit(app.run(sys.argv))
@@ -130,13 +112,6 @@ def on_activate(self, *_):
130112
self.window.resize(*self.window.get_default_size())
131113

132114
def embed_browser(self):
133-
global g_pending_embed
134-
if not g_context_initialized:
135-
# Chrome runtime initializes the browser context asynchronously;
136-
# embed once OnContextInitialized fires (see main()).
137-
g_pending_embed = self.embed_browser
138-
return
139-
g_pending_embed = None
140115
window_info = cef.WindowInfo()
141116
# TODO: on Mac pass rect[x, y, width, height] to SetAsChild
142117
window_info.SetAsChild(self.get_handle())

examples/hello_world.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,9 @@ def main():
1818
check_versions()
1919
sys.excepthook = cef.ExceptHook # shut down all CEF processes on error
2020
settings = {}
21-
22-
def on_context_initialized():
23-
# Under CEF's Chrome runtime the browser context initializes
24-
# asynchronously, so the browser must be created from the
25-
# OnContextInitialized callback rather than immediately after
26-
# cef.Initialize(). This matches CEF's cefsimple sample.
27-
cef.CreateBrowserSync(url="https://www.google.com/",
28-
window_title="Hello World!")
29-
30-
# Register the callback before cef.Initialize(): OnContextInitialized can
31-
# fire during cef.Initialize() itself.
32-
cef.SetGlobalClientCallback("OnContextInitialized",
33-
on_context_initialized)
3421
cef.Initialize(settings=settings)
22+
cef.CreateBrowserSync(url="https://www.google.com/",
23+
window_title="Hello World!")
3524
cef.MessageLoop()
3625
cef.Shutdown()
3726

examples/pysdl2.py

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -104,18 +104,6 @@ def die(msg):
104104
" To install type: pip install pyobjc")
105105

106106

107-
# Under CEF's Chrome runtime the browser context initializes asynchronously,
108-
# so the (off-screen) browser can only be created after OnContextInitialized
109-
# has fired. This flag is set by the callback registered before
110-
# cef.Initialize().
111-
g_context_initialized = False
112-
113-
114-
def _on_context_initialized():
115-
global g_context_initialized
116-
g_context_initialized = True
117-
118-
119107
def main():
120108
"""
121109
Parses input, initializes everything and then runs the main loop of the
@@ -205,9 +193,6 @@ def main():
205193
# Tweaking OSR performance (Issue #240)
206194
"windowless_frame_rate": frameRate
207195
}
208-
# Register before cef.Initialize(); OnContextInitialized may fire during it.
209-
cef.SetGlobalClientCallback("OnContextInitialized",
210-
_on_context_initialized)
211196
cef.Initialize(settings={"windowless_rendering_enabled": True},
212197
switches=switches)
213198

@@ -311,14 +296,6 @@ def _detect_device_scale_factor(window, renderer):
311296
# RenderHandler instances, creating SDL windows for popups lazily.
312297
renderHandler = MetaRenderHandler(renderer, width, height - headerHeight,
313298
deviceScaleFactor, rendererFlags)
314-
# Create the browser instance. Unlike the windowed examples (which embed
315-
# the browser from an event callback), this linear off-screen example
316-
# creates it inline, so ensure the CEF context has finished initializing
317-
# first. On most platforms it already has by this point (it initializes
318-
# during cef.Initialize()); otherwise let the message loop run until
319-
# OnContextInitialized fires.
320-
while not g_context_initialized:
321-
cef.MessageLoopWork()
322299
# Create the browser instance
323300
browser = cef.CreateBrowserSync(window_info,
324301
url="https://www.google.com/",

examples/qt.py

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -74,21 +74,6 @@
7474
HEIGHT = 600
7575

7676

77-
# Under CEF's Chrome runtime the browser context initializes asynchronously,
78-
# so a browser can only be created after OnContextInitialized has fired. These
79-
# module-level helpers coordinate that: embedBrowser() defers itself until the
80-
# context is ready, and the callback below runs any deferred embed.
81-
g_context_initialized = False
82-
g_pending_embed = None
83-
84-
85-
def _on_context_initialized():
86-
global g_context_initialized
87-
g_context_initialized = True
88-
if g_pending_embed is not None:
89-
g_pending_embed()
90-
91-
9277
def main():
9378
check_versions()
9479
sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error
@@ -107,9 +92,6 @@ def main():
10792
"devtools": True,
10893
}
10994

110-
# Register before cef.Initialize(); OnContextInitialized may fire during it.
111-
cef.SetGlobalClientCallback("OnContextInitialized",
112-
_on_context_initialized)
11395
cef.Initialize(settings)
11496
app = CefApplication(sys.argv)
11597
main_window = MainWindow()
@@ -266,13 +248,6 @@ def focusOutEvent(self, event):
266248
self.browser.SetFocus(False)
267249

268250
def embedBrowser(self):
269-
global g_pending_embed
270-
if not g_context_initialized:
271-
# Chrome runtime initializes the browser context asynchronously;
272-
# embed once OnContextInitialized fires (see main()).
273-
g_pending_embed = self.embedBrowser
274-
return
275-
g_pending_embed = None
276251
if LINUX and PYQT5:
277252
# On Linux with PyQt5, QX11EmbedContainer is gone; the Qt-native
278253
# equivalent is to host CEF in a QWindow (hidden_window) wrapped in

examples/screenshot.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,8 @@ def main():
9797
# Tweaking OSR performance (Issue #240)
9898
"windowless_frame_rate": 30, # Default frame rate in CEF is 30
9999
}
100-
def on_context_initialized():
101-
# Under CEF's Chrome runtime the browser context initializes
102-
# asynchronously, so create the browser here rather than right after
103-
# cef.Initialize().
104-
create_browser(browser_settings)
105-
106-
# Register before cef.Initialize(); OnContextInitialized may fire during it.
107-
cef.SetGlobalClientCallback("OnContextInitialized", on_context_initialized)
108100
cef.Initialize(settings=settings, switches=switches)
101+
create_browser(browser_settings)
109102
cef.MessageLoop()
110103
cef.Shutdown()
111104
print("[screenshot.py] Opening screenshot with default application")

examples/snippets/cookies.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,13 @@
77

88

99
def main():
10-
def on_context_initialized():
11-
# Under CEF's Chrome runtime the browser context initializes
12-
# asynchronously, so create the browser here rather than right after
13-
# cef.Initialize().
14-
browser = cef.CreateBrowserSync(
15-
url="https://www.google.com/",
16-
window_title="Cookies")
17-
browser.SetClientHandler(LoadHandler())
18-
19-
# Register before cef.Initialize(); OnContextInitialized may fire during it.
20-
cef.SetGlobalClientCallback("OnContextInitialized", on_context_initialized)
2110
cef.Initialize()
11+
browser = cef.CreateBrowserSync(
12+
url="https://www.google.com/",
13+
window_title="Cookies")
14+
browser.SetClientHandler(LoadHandler())
2215
cef.MessageLoop()
16+
del browser
2317
cef.Shutdown()
2418

2519

examples/snippets/crossdomain_bindings.py

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,24 +37,17 @@
3737

3838
def main():
3939
print(__doc__)
40-
41-
def on_context_initialized():
42-
# Under CEF's Chrome runtime the browser context initializes
43-
# asynchronously, so create the browser here rather than right after
44-
# cef.Initialize().
45-
browser = cef.CreateBrowserSync(
46-
url=TARGET_URL,
47-
window_title="Cross-domain JS binding test")
48-
handler = CrossDomainHandler(browser)
49-
browser.SetClientHandler(handler)
50-
bindings = cef.JavascriptBindings()
51-
bindings.SetFunction("OnTargetPageReady", handler["_OnTargetPageReady"])
52-
browser.SetJavascriptBindings(bindings)
53-
54-
# Register before cef.Initialize(); OnContextInitialized may fire during it.
55-
cef.SetGlobalClientCallback("OnContextInitialized", on_context_initialized)
5640
cef.Initialize()
41+
browser = cef.CreateBrowserSync(url=TARGET_URL,
42+
window_title="Cross-domain JS binding test")
43+
handler = CrossDomainHandler(browser)
44+
browser.SetClientHandler(handler)
45+
bindings = cef.JavascriptBindings()
46+
bindings.SetFunction("OnTargetPageReady", handler["_OnTargetPageReady"])
47+
browser.SetJavascriptBindings(bindings)
5748
cef.MessageLoop()
49+
del handler
50+
del browser
5851
cef.Shutdown()
5952

6053

examples/snippets/javascript_bindings.py

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,16 @@
3838

3939

4040
def main():
41-
def on_context_initialized():
42-
# Under CEF's Chrome runtime the browser context initializes
43-
# asynchronously, so create the browser here rather than right after
44-
# cef.Initialize().
45-
browser = cef.CreateBrowserSync(url=cef.GetDataUrl(g_htmlcode),
46-
window_title="Javascript Bindings")
47-
browser.SetClientHandler(LoadHandler())
48-
bindings = cef.JavascriptBindings()
49-
bindings.SetFunction("py_function", py_function)
50-
bindings.SetFunction("py_callback", py_callback)
51-
browser.SetJavascriptBindings(bindings)
52-
53-
# Register before cef.Initialize(); OnContextInitialized may fire during it.
54-
cef.SetGlobalClientCallback("OnContextInitialized", on_context_initialized)
5541
cef.Initialize()
42+
browser = cef.CreateBrowserSync(url=cef.GetDataUrl(g_htmlcode),
43+
window_title="Javascript Bindings")
44+
browser.SetClientHandler(LoadHandler())
45+
bindings = cef.JavascriptBindings()
46+
bindings.SetFunction("py_function", py_function)
47+
bindings.SetFunction("py_callback", py_callback)
48+
browser.SetJavascriptBindings(bindings)
5649
cef.MessageLoop()
50+
del browser
5751
cef.Shutdown()
5852

5953

examples/snippets/javascript_errors.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,10 @@
4040

4141

4242
def main():
43-
def on_context_initialized():
44-
# Under CEF's Chrome runtime the browser context initializes
45-
# asynchronously, so create the browser here rather than right after
46-
# cef.Initialize().
47-
browser = cef.CreateBrowserSync(url=cef.GetDataUrl(g_htmlcode),
48-
window_title="Javascript Errors")
49-
browser.SetClientHandler(DisplayHandler())
50-
51-
# Register before cef.Initialize(); OnContextInitialized may fire during it.
52-
cef.SetGlobalClientCallback("OnContextInitialized", on_context_initialized)
5343
cef.Initialize()
44+
browser = cef.CreateBrowserSync(url=cef.GetDataUrl(g_htmlcode),
45+
window_title="Javascript Errors")
46+
browser.SetClientHandler(DisplayHandler())
5447
cef.MessageLoop()
5548
cef.Shutdown()
5649

0 commit comments

Comments
 (0)