Skip to content

Commit 62cac63

Browse files
committed
Added new callbacks to LifespanHandler: _OnAfterCreated, RunModal,
DoClose, OnBeforeClose. Thanks to Simon Hatt for the patch (Issue 139). Fixed issue with GetApplicationPath() returning wrong directory in some cases. All Python examples have been updated.
1 parent 33d60c7 commit 62cac63

File tree

18 files changed

+396
-156
lines changed

18 files changed

+396
-156
lines changed

cefpython/browser.pyx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,9 @@ cdef class PyBrowser:
229229
# KeyboardHandler
230230
self.allowedClientCallbacks += ["OnPreKeyEvent", "OnKeyEvent"];
231231
# RequestHandler
232-
# Note: "OnCertificateError" and "OnBeforePluginLoad" must be
233-
# set using cefpython.SetGlobalClientCallback()
232+
# NOTE: OnCertificateError and OnBeforePluginLoad are not
233+
# included as they must be set using
234+
# cefpython.SetGlobalClientCallback().
234235
self.allowedClientCallbacks += ["OnBeforeResourceLoad",
235236
"OnResourceRedirect", "GetAuthCredentials",
236237
"OnQuotaRequest", "OnProtocolExecution",
@@ -243,7 +244,10 @@ cdef class PyBrowser:
243244
self.allowedClientCallbacks += ["OnLoadingStateChange",
244245
"OnLoadStart", "OnLoadEnd", "OnLoadError"]
245246
# LifespanHandler
246-
self.allowedClientCallbacks += ["OnBeforePopup"]
247+
# NOTE: OnAfterCreated not included as it must be set using
248+
# cefpython.SetGlobalClientCallback().
249+
self.allowedClientCallbacks += ["OnBeforePopup",
250+
"RunModal", "DoClose", "OnBeforeClose"]
247251
# RenderHandler
248252
self.allowedClientCallbacks += ["GetRootScreenRect",
249253
"GetViewRect", "GetScreenPoint", "GetScreenInfo",

cefpython/cef3/client_handler/client_handler.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ bool ClientHandler::OnBeforePopup(CefRefPtr<CefBrowser> browser,
179179
///
180180
/*--cef()--*/
181181
void ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
182+
REQUIRE_UI_THREAD();
182183
#if defined(OS_WIN)
183184
// High DPI support.
184185
CefString auto_zooming = ApplicationSettings_GetString("auto_zooming");
@@ -188,6 +189,7 @@ void ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
188189
SetBrowserDpiSettings(browser, auto_zooming);
189190
}
190191
#endif
192+
LifespanHandler_OnAfterCreated(browser);
191193
}
192194

193195
///
@@ -197,7 +199,8 @@ void ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
197199
///
198200
/*--cef()--*/
199201
bool ClientHandler::RunModal(CefRefPtr<CefBrowser> browser) {
200-
return false;
202+
REQUIRE_UI_THREAD();
203+
return LifespanHandler_RunModal(browser);
201204
}
202205

203206
///
@@ -260,7 +263,8 @@ bool ClientHandler::RunModal(CefRefPtr<CefBrowser> browser) {
260263
///
261264
/*--cef()--*/
262265
bool ClientHandler::DoClose(CefRefPtr<CefBrowser> browser) {
263-
return false;
266+
REQUIRE_UI_THREAD();
267+
return LifespanHandler_DoClose(browser);
264268
}
265269

266270
///

cefpython/cef3/linux/binaries_32bit/pygtk_.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,26 @@
3030

3131
def GetApplicationPath(file=None):
3232
import re, os, platform
33+
# On Windows after downloading file and calling Browser.GoForward(),
34+
# current working directory is set to %UserProfile%.
35+
# Calling os.path.dirname(os.path.realpath(__file__))
36+
# returns for eg. "C:\Users\user\Downloads". A solution
37+
# is to cache path on first call.
38+
if not hasattr(GetApplicationPath, "dir"):
39+
if hasattr(sys, "frozen"):
40+
dir = os.path.dirname(sys.executable)
41+
elif "__file__" in globals():
42+
dir = os.path.dirname(os.path.realpath(__file__))
43+
else:
44+
dir = os.getcwd()
45+
GetApplicationPath.dir = dir
3346
# If file is None return current directory without trailing slash.
3447
if file is None:
3548
file = ""
3649
# Only when relative path.
3750
if not file.startswith("/") and not file.startswith("\\") and (
3851
not re.search(r"^[\w-]+:", file)):
39-
if hasattr(sys, "frozen"):
40-
path = os.path.dirname(sys.executable)
41-
elif "__file__" in globals():
42-
path = os.path.dirname(os.path.realpath(__file__))
43-
else:
44-
path = os.getcwd()
45-
path = path + os.sep + file
52+
path = GetApplicationPath.dir + os.sep + file
4653
if platform.system() == "Windows":
4754
path = re.sub(r"[/\\]+", re.escape(os.sep), path)
4855
path = re.sub(r"[/\\]+$", "", path)

cefpython/cef3/linux/binaries_32bit/pyqt.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,26 @@
2828

2929
def GetApplicationPath(file=None):
3030
import re, os, platform
31+
# On Windows after downloading file and calling Browser.GoForward(),
32+
# current working directory is set to %UserProfile%.
33+
# Calling os.path.dirname(os.path.realpath(__file__))
34+
# returns for eg. "C:\Users\user\Downloads". A solution
35+
# is to cache path on first call.
36+
if not hasattr(GetApplicationPath, "dir"):
37+
if hasattr(sys, "frozen"):
38+
dir = os.path.dirname(sys.executable)
39+
elif "__file__" in globals():
40+
dir = os.path.dirname(os.path.realpath(__file__))
41+
else:
42+
dir = os.getcwd()
43+
GetApplicationPath.dir = dir
3144
# If file is None return current directory without trailing slash.
3245
if file is None:
3346
file = ""
3447
# Only when relative path.
3548
if not file.startswith("/") and not file.startswith("\\") and (
3649
not re.search(r"^[\w-]+:", file)):
37-
if hasattr(sys, "frozen"):
38-
path = os.path.dirname(sys.executable)
39-
elif "__file__" in globals():
40-
path = os.path.dirname(os.path.realpath(__file__))
41-
else:
42-
path = os.getcwd()
43-
path = path + os.sep + file
50+
path = GetApplicationPath.dir + os.sep + file
4451
if platform.system() == "Windows":
4552
path = re.sub(r"[/\\]+", re.escape(os.sep), path)
4653
path = re.sub(r"[/\\]+$", "", path)

cefpython/cef3/linux/binaries_32bit/wxpython-response.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -276,19 +276,26 @@ def OnRequestComplete(self, webRequest):
276276

277277
def GetApplicationPath(file=None):
278278
import re, os, platform
279+
# On Windows after downloading file and calling Browser.GoForward(),
280+
# current working directory is set to %UserProfile%.
281+
# Calling os.path.dirname(os.path.realpath(__file__))
282+
# returns for eg. "C:\Users\user\Downloads". A solution
283+
# is to cache path on first call.
284+
if not hasattr(GetApplicationPath, "dir"):
285+
if hasattr(sys, "frozen"):
286+
dir = os.path.dirname(sys.executable)
287+
elif "__file__" in globals():
288+
dir = os.path.dirname(os.path.realpath(__file__))
289+
else:
290+
dir = os.getcwd()
291+
GetApplicationPath.dir = dir
279292
# If file is None return current directory without trailing slash.
280293
if file is None:
281294
file = ""
282295
# Only when relative path.
283296
if not file.startswith("/") and not file.startswith("\\") and (
284297
not re.search(r"^[\w-]+:", file)):
285-
if hasattr(sys, "frozen"):
286-
path = os.path.dirname(sys.executable)
287-
elif "__file__" in globals():
288-
path = os.path.dirname(os.path.realpath(__file__))
289-
else:
290-
path = os.getcwd()
291-
path = path + os.sep + file
298+
path = GetApplicationPath.dir + os.sep + file
292299
if platform.system() == "Windows":
293300
path = re.sub(r"[/\\]+", re.escape(os.sep), path)
294301
path = re.sub(r"[/\\]+$", "", path)

cefpython/cef3/linux/binaries_32bit/wxpython.py

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,26 @@
4444

4545
def GetApplicationPath(file=None):
4646
import re, os, platform
47+
# On Windows after downloading file and calling Browser.GoForward(),
48+
# current working directory is set to %UserProfile%.
49+
# Calling os.path.dirname(os.path.realpath(__file__))
50+
# returns for eg. "C:\Users\user\Downloads". A solution
51+
# is to cache path on first call.
52+
if not hasattr(GetApplicationPath, "dir"):
53+
if hasattr(sys, "frozen"):
54+
dir = os.path.dirname(sys.executable)
55+
elif "__file__" in globals():
56+
dir = os.path.dirname(os.path.realpath(__file__))
57+
else:
58+
dir = os.getcwd()
59+
GetApplicationPath.dir = dir
4760
# If file is None return current directory without trailing slash.
4861
if file is None:
4962
file = ""
5063
# Only when relative path.
5164
if not file.startswith("/") and not file.startswith("\\") and (
5265
not re.search(r"^[\w-]+:", file)):
53-
if hasattr(sys, "frozen"):
54-
path = os.path.dirname(sys.executable)
55-
elif "__file__" in globals():
56-
path = os.path.dirname(os.path.realpath(__file__))
57-
else:
58-
path = os.getcwd()
59-
path = path + os.sep + file
66+
path = GetApplicationPath.dir + os.sep + file
6067
if platform.system() == "Windows":
6168
path = re.sub(r"[/\\]+", re.escape(os.sep), path)
6269
path = re.sub(r"[/\\]+$", "", path)
@@ -115,6 +122,15 @@ def __init__(self, url=None):
115122
# all parent panels/controls, if it's deeply embedded.
116123
self.mainPanel = wx.Panel(self, style=wx.WANTS_CHARS)
117124

125+
# Global client callbacks must be set before browser is created.
126+
clientHandler = ClientHandler()
127+
cefpython.SetGlobalClientCallback("OnCertificateError",
128+
clientHandler._OnCertificateError)
129+
cefpython.SetGlobalClientCallback("OnBeforePluginLoad",
130+
clientHandler._OnBeforePluginLoad)
131+
cefpython.SetGlobalClientCallback("OnAfterCreated",
132+
clientHandler._OnAfterCreated)
133+
118134
windowInfo = cefpython.WindowInfo()
119135
windowInfo.SetAsChild(self.mainPanel.GetGtkWidget())
120136
# Linux requires adding "file://" for local files,
@@ -126,12 +142,8 @@ def __init__(self, url=None):
126142
browserSettings=g_browserSettings,
127143
navigateUrl=url)
128144

129-
clientHandler = ClientHandler(self.browser)
145+
clientHandler.mainBrowser = self.browser
130146
self.browser.SetClientHandler(clientHandler)
131-
cefpython.SetGlobalClientCallback("OnCertificateError",
132-
clientHandler._OnCertificateError)
133-
cefpython.SetGlobalClientCallback("OnBeforePluginLoad",
134-
clientHandler._OnBeforePluginLoad)
135147

136148
jsBindings = cefpython.JavascriptBindings(
137149
bindToFrames=False, bindToPopups=True)
@@ -324,10 +336,10 @@ def Visit(self, cookie, count, total, deleteCookie):
324336
return True
325337

326338
class ClientHandler:
327-
mainBrowser = None
339+
mainBrowser = None # May be None for global client callbacks.
328340

329-
def __init__(self, browser):
330-
self.mainBrowser = browser
341+
def __init__(self):
342+
pass
331343

332344
# -------------------------------------------------------------------------
333345
# DisplayHandler
@@ -482,11 +494,12 @@ def OnProtocolExecution(self, browser, url, allowExecutionOut):
482494
allowExecutionOut[0] = True
483495

484496
def _OnBeforePluginLoad(self, browser, url, policyUrl, info):
497+
# This is a global callback set using SetGlobalClientCallback().
485498
# Plugins are loaded on demand, only when website requires it,
486499
# the same plugin may be called multiple times.
487500
# This callback is called on the IO thread, thus print messages
488501
# may not be visible.
489-
print("[wxpython.py] RequestHandler::OnBeforePluginLoad()")
502+
print("[wxpython.py] RequestHandler::_OnBeforePluginLoad()")
490503
print(" url = %s" % url)
491504
print(" policy url = %s" % policyUrl)
492505
print(" info.GetName() = %s" % info.GetName())
@@ -497,7 +510,8 @@ def _OnBeforePluginLoad(self, browser, url, policyUrl, info):
497510
return False
498511

499512
def _OnCertificateError(self, certError, requestUrl, callback):
500-
print("[wxpython.py] RequestHandler::OnCertificateError()")
513+
# This is a global callback set using SetGlobalClientCallback().
514+
print("[wxpython.py] RequestHandler::_OnCertificateError()")
501515
print(" certError = %s" % certError)
502516
print(" requestUrl = %s" % requestUrl)
503517
if requestUrl.startswith(
@@ -573,15 +587,37 @@ def OnLoadError(self, browser, frame, errorCode, errorTextList, failedUrl):
573587
# LifespanHandler
574588
# -------------------------------------------------------------------------
575589

576-
# Empty place-holders: popupFeatures, windowInfo, client, browserSettings.
590+
# ** This callback is executed on the IO thread **
591+
# Empty place-holders: popupFeatures, client.
577592
def OnBeforePopup(self, browser, frame, targetUrl, targetFrameName,\
578593
popupFeatures, windowInfo, client, browserSettings,\
579594
noJavascriptAccess):
580595
print("[wxpython.py] LifespanHandler::OnBeforePopup()")
581596
print(" targetUrl = %s" % targetUrl)
597+
# Custom browser settings for popups:
598+
# > browserSettings[0] = {"plugins_disabled": True}
599+
# Set WindowInfo object:
600+
# > windowInfo[0] = cefpython.WindowInfo()
582601
allowPopups = True
583602
return not allowPopups
584603

604+
def _OnAfterCreated(self, browser):
605+
# This is a global callback set using SetGlobalClientCallback().
606+
print("[wxpython.py] LifespanHandler::_OnAfterCreated()")
607+
print(" browserId=%s" % browser.GetIdentifier())
608+
609+
def RunModal(self, browser):
610+
print("[wxpython.py] LifespanHandler::RunModal()")
611+
print(" browserId=%s" % browser.GetIdentifier())
612+
613+
def DoClose(self, browser):
614+
print("[wxpython.py] LifespanHandler::DoClose()")
615+
print(" browserId=%s" % browser.GetIdentifier())
616+
617+
def OnBeforeClose(self, browser):
618+
print("[wxpython.py] LifespanHandler::OnBeforeClose")
619+
print(" browserId=%s" % browser.GetIdentifier())
620+
585621
# -------------------------------------------------------------------------
586622
# JavascriptDialogHandler
587623
# -------------------------------------------------------------------------

cefpython/cef3/linux/binaries_64bit/pygtk_.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,26 @@
3030

3131
def GetApplicationPath(file=None):
3232
import re, os, platform
33+
# On Windows after downloading file and calling Browser.GoForward(),
34+
# current working directory is set to %UserProfile%.
35+
# Calling os.path.dirname(os.path.realpath(__file__))
36+
# returns for eg. "C:\Users\user\Downloads". A solution
37+
# is to cache path on first call.
38+
if not hasattr(GetApplicationPath, "dir"):
39+
if hasattr(sys, "frozen"):
40+
dir = os.path.dirname(sys.executable)
41+
elif "__file__" in globals():
42+
dir = os.path.dirname(os.path.realpath(__file__))
43+
else:
44+
dir = os.getcwd()
45+
GetApplicationPath.dir = dir
3346
# If file is None return current directory without trailing slash.
3447
if file is None:
3548
file = ""
3649
# Only when relative path.
3750
if not file.startswith("/") and not file.startswith("\\") and (
3851
not re.search(r"^[\w-]+:", file)):
39-
if hasattr(sys, "frozen"):
40-
path = os.path.dirname(sys.executable)
41-
elif "__file__" in globals():
42-
path = os.path.dirname(os.path.realpath(__file__))
43-
else:
44-
path = os.getcwd()
45-
path = path + os.sep + file
52+
path = GetApplicationPath.dir + os.sep + file
4653
if platform.system() == "Windows":
4754
path = re.sub(r"[/\\]+", re.escape(os.sep), path)
4855
path = re.sub(r"[/\\]+$", "", path)

cefpython/cef3/linux/binaries_64bit/pyqt.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,26 @@
2828

2929
def GetApplicationPath(file=None):
3030
import re, os, platform
31+
# On Windows after downloading file and calling Browser.GoForward(),
32+
# current working directory is set to %UserProfile%.
33+
# Calling os.path.dirname(os.path.realpath(__file__))
34+
# returns for eg. "C:\Users\user\Downloads". A solution
35+
# is to cache path on first call.
36+
if not hasattr(GetApplicationPath, "dir"):
37+
if hasattr(sys, "frozen"):
38+
dir = os.path.dirname(sys.executable)
39+
elif "__file__" in globals():
40+
dir = os.path.dirname(os.path.realpath(__file__))
41+
else:
42+
dir = os.getcwd()
43+
GetApplicationPath.dir = dir
3144
# If file is None return current directory without trailing slash.
3245
if file is None:
3346
file = ""
3447
# Only when relative path.
3548
if not file.startswith("/") and not file.startswith("\\") and (
3649
not re.search(r"^[\w-]+:", file)):
37-
if hasattr(sys, "frozen"):
38-
path = os.path.dirname(sys.executable)
39-
elif "__file__" in globals():
40-
path = os.path.dirname(os.path.realpath(__file__))
41-
else:
42-
path = os.getcwd()
43-
path = path + os.sep + file
50+
path = GetApplicationPath.dir + os.sep + file
4451
if platform.system() == "Windows":
4552
path = re.sub(r"[/\\]+", re.escape(os.sep), path)
4653
path = re.sub(r"[/\\]+$", "", path)

0 commit comments

Comments
 (0)