Skip to content

Commit c713975

Browse files
committed
Fixes to response reading features.
Added the wxpython-response.py script with tests of the response reading features. The pyqt example added does not work - results in segmentation fault, see the comment at top of the file.
1 parent 875b8b7 commit c713975

8 files changed

Lines changed: 713 additions & 38 deletions

File tree

cefpython/browser.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ cdef class PyBrowser:
208208
self.allowedClientCallbacks += ["OnBeforeResourceLoad",
209209
"OnResourceRedirect", "GetAuthCredentials",
210210
"OnQuotaRequest", "GetCookieManager",
211-
"OnProtocolExecution"]
211+
"OnProtocolExecution", "GetResourceHandler"]
212212
# LoadHandler
213213
self.allowedClientCallbacks += ["OnLoadStart", "OnLoadEnd",
214214
"OnLoadError", "OnRendererProcessTerminated",

cefpython/cef3/client_handler/client_handler.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,7 @@ CefRefPtr<CefResourceHandler> ClientHandler::GetResourceHandler(
375375
CefRefPtr<CefFrame> frame,
376376
CefRefPtr<CefRequest> request) {
377377
REQUIRE_IO_THREAD();
378-
// Not yet implemented.
379-
return NULL;
378+
return RequestHandler_GetResourceHandler(browser, frame, request);
380379
}
381380

382381
///
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset=utf-8>
5+
<title>CEF Python 3 example (utf-8: ąś)</title>
6+
<style>
7+
body { font: 13px Segoe UI, Arial; line-height: 1.4em; }
8+
pre { background: #ddd; font: 12px Consolas, Courier New; }
9+
</style>
10+
</head>
11+
<body>
12+
13+
14+
15+
<p>Use mouse context menu to go Back/Forward in history navigation.</p>
16+
17+
18+
19+
<h3>Google Search</h3>
20+
<a href="https://www.google.com/">https://www.google.com/</a>
21+
22+
23+
24+
<h3>User agent</h3>
25+
<script>document.write(navigator.userAgent)</script>
26+
27+
28+
29+
<h3>Popup</h3>
30+
<a href="javascript:window.open('example.html')">
31+
window.open('example.html')</a>
32+
33+
34+
35+
<h3>HTML5 video and accelerated content</h3>
36+
<a href="http://www.youtube.com/watch?v=siOHh0uzcuY&html5=True">
37+
HTML 5 video</a><br>
38+
<a href="http://mudcu.be/labs/JS1k/BreathingGalaxies.html">
39+
Accelerated canvas</a><br>
40+
<a href="http://www.webkit.org/blog-files/3d-transforms/poster-circle.html">
41+
Accelerated layers</a><br>
42+
43+
44+
45+
<h3>Advanced example</h3>
46+
47+
See the wxpython.py script for an advanced usage of CEF Python 3
48+
features - including javascript bindings, js and python callbacks,
49+
client handlers and others.
50+
51+
52+
<br><br><br><br>
53+
<br><br><br><br>
54+
<br><br><br><br>
55+
<br><br><br><br>
56+
57+
</body>
58+
</html>
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
# This example is throwing segmentation faults when run on Linux,
2+
# the problem seems to be in a call to CreateBrowserSync(),
3+
# the backtrace leads to CefBrowserHostImpl::PlatformCreateWindow().
4+
# Full backtrace:
5+
"""
6+
0x00007ffff1ee52a0 in CefBrowserHostImpl::PlatformCreateWindow() ()
7+
from /home/czarek/cefpython/cefpython/cef3/linux/binaries_64bit/libcef.so
8+
(gdb) backtrace
9+
#0 0x00007ffff1ee52a0 in CefBrowserHostImpl::PlatformCreateWindow() ()
10+
from /home/czarek/cefpython/cefpython/cef3/linux/binaries_64bit/libcef.so
11+
#1 0x00007ffff1e24930 in CefBrowserHostImpl::Create(CefWindowInfo const&, CefStructBase<CefBrowserSettingsTraits> const&, CefRefPtr<CefClient>, content::WebContents*, scoped_refptr<CefBrowserInfo>, _GtkWidget*) ()
12+
from /home/czarek/cefpython/cefpython/cef3/linux/binaries_64bit/libcef.so
13+
#2 0x00007ffff1e251ec in CefBrowserHost::CreateBrowserSync(CefWindowInfo const&, CefRefPtr<CefClient>, CefStringBase<CefStringTraitsUTF16> const&, CefStructBase<CefBrowserSettingsTraits> const&) ()
14+
from /home/czarek/cefpython/cefpython/cef3/linux/binaries_64bit/libcef.so
15+
#3 0x00007ffff1dc9fec in cef_browser_host_create_browser_sync ()
16+
from /home/czarek/cefpython/cefpython/cef3/linux/binaries_64bit/libcef.so
17+
#4 0x00007fffe8136e4f in CefBrowserHost::CreateBrowserSync(CefWindowInfo const&, CefRefPtr<CefClient>, CefStringBase<CefStringTraitsUTF16> const&, CefStructBase<CefBrowserSettingsTraits> const&) ()
18+
from /home/czarek/cefpython/cefpython/cef3/linux/binaries_64bit/cefpython_py27.so
19+
#5 0x00007fffe8111cce in __pyx_pf_14cefpython_py27_16CreateBrowserSync (
20+
__pyx_v_windowInfo=<cefpython_py27.WindowInfo at remote 0xdc7fb0>,
21+
__pyx_v_browserSettings=<optimized out>, __pyx_v_navigateUrl=
22+
'file:///home/czarek/cefpython/cefpython/cef3/linux/binaries_64bit/example.html', __pyx_self=<optimized out>) at cefpython.cpp:65142
23+
#6 0x00007fffe8114ea6 in __pyx_pw_14cefpython_py27_17CreateBrowserSync (
24+
"""
25+
26+
# An example of embedding CEF Python in PyQt4 application.
27+
28+
# On Ubuntu install the "python-qt4" package.
29+
# Tested with version 4.9.1-2ubuntu1.
30+
31+
# Important:
32+
# On Linux importing the cefpython module must be
33+
# the very first in your application. This is because CEF makes
34+
# a global tcmalloc hook for memory allocation/deallocation.
35+
# See Issue 73 that is to provide CEF builds with tcmalloc disabled:
36+
# https://code.google.com/p/cefpython/issues/detail?id=73
37+
38+
import ctypes, os, sys
39+
libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)),\
40+
'libcef.so')
41+
# Import a local module if exists, otherwise import from
42+
# an installed package.
43+
if os.path.exists(libcef_so):
44+
ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL)
45+
if 0x02070000 <= sys.hexversion < 0x03000000:
46+
import cefpython_py27 as cefpython
47+
else:
48+
raise Exception("Unsupported python version: %s" % sys.version)
49+
else:
50+
from cefpython3 import cefpython
51+
52+
from PyQt4 import QtGui
53+
from PyQt4 import QtCore
54+
55+
TEST_RESPONSE_READING = False
56+
57+
def GetApplicationPath(file=None):
58+
import re, os, platform
59+
# If file is None return current directory without trailing slash.
60+
if file is None:
61+
file = ""
62+
# Only when relative path.
63+
if not file.startswith("/") and not file.startswith("\\") and (
64+
not re.search(r"^[\w-]+:", file)):
65+
if hasattr(sys, "frozen"):
66+
path = os.path.dirname(sys.executable)
67+
elif "__file__" in globals():
68+
path = os.path.dirname(os.path.realpath(__file__))
69+
else:
70+
path = os.getcwd()
71+
path = path + os.sep + file
72+
if platform.system() == "Windows":
73+
path = re.sub(r"[/\\]+", re.escape(os.sep), path)
74+
path = re.sub(r"[/\\]+$", "", path)
75+
return path
76+
return str(file)
77+
78+
def ExceptHook(excType, excValue, traceObject):
79+
import traceback, os, time, codecs
80+
# This hook does the following: in case of exception write it to
81+
# the "error.log" file, display it to the console, shutdown CEF
82+
# and exit application immediately by ignoring "finally" (os._exit()).
83+
errorMsg = "\n".join(traceback.format_exception(excType, excValue,
84+
traceObject))
85+
errorFile = GetApplicationPath("error.log")
86+
try:
87+
appEncoding = cefpython.g_applicationSettings["string_encoding"]
88+
except:
89+
appEncoding = "utf-8"
90+
if type(errorMsg) == bytes:
91+
errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace")
92+
try:
93+
with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp:
94+
fp.write("\n[%s] %s\n" % (
95+
time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg))
96+
except:
97+
print("cefpython: WARNING: failed writing to error file: %s" % (
98+
errorFile))
99+
# Convert error message to ascii before printing, otherwise
100+
# you may get error like this:
101+
# | UnicodeEncodeError: 'charmap' codec can't encode characters
102+
errorMsg = errorMsg.encode("ascii", errors="replace")
103+
errorMsg = errorMsg.decode("ascii", errors="replace")
104+
print("\n"+errorMsg+"\n")
105+
cefpython.QuitMessageLoop()
106+
cefpython.Shutdown()
107+
os._exit(1)
108+
109+
class MainWindow(QtGui.QMainWindow):
110+
mainFrame = None
111+
112+
def __init__(self):
113+
super(MainWindow, self).__init__(None)
114+
self.createMenu()
115+
self.mainFrame = MainFrame(self)
116+
self.setCentralWidget(self.mainFrame)
117+
self.resize(1024, 768)
118+
self.setWindowTitle('PyQT CEF 3 example')
119+
self.setFocusPolicy(QtCore.Qt.StrongFocus)
120+
121+
def createMenu(self):
122+
menubar = self.menuBar()
123+
filemenu = menubar.addMenu("&File")
124+
filemenu.addAction(QtGui.QAction("Open", self))
125+
filemenu.addAction(QtGui.QAction("Exit", self))
126+
aboutmenu = menubar.addMenu("&About")
127+
128+
def focusInEvent(self, event):
129+
cefpython.WindowUtils.OnSetFocus(
130+
int(self.centralWidget().winId()), 0, 0, 0)
131+
132+
def closeEvent(self, event):
133+
self.mainFrame.browser.CloseBrowser()
134+
135+
class MainFrame(QtGui.QWidget):
136+
browser = None
137+
138+
def __init__(self, parent=None):
139+
super(MainFrame, self).__init__(parent)
140+
windowInfo = cefpython.WindowInfo()
141+
windowInfo.SetAsChild(int(self.winId()))
142+
# Linux requires adding "file://" for local files,
143+
# otherwise /home/some will be replaced as http://home/some
144+
self.browser = cefpython.CreateBrowserSync(windowInfo,
145+
browserSettings={},
146+
navigateUrl="file://"+GetApplicationPath("example.html"))
147+
self.show()
148+
149+
def moveEvent(self, event):
150+
cefpython.WindowUtils.OnSize(int(self.winId()), 0, 0, 0)
151+
152+
def resizeEvent(self, event):
153+
cefpython.WindowUtils.OnSize(int(self.winId()), 0, 0, 0)
154+
155+
class CefApplication(QtGui.QApplication):
156+
timer = None
157+
158+
def __init__(self, args):
159+
super(CefApplication, self).__init__(args)
160+
self.createTimer()
161+
162+
def createTimer(self):
163+
self.timer = QtCore.QTimer()
164+
self.timer.timeout.connect(self.onTimer)
165+
self.timer.start(10)
166+
167+
def onTimer(self):
168+
# The proper way of doing message loop should be:
169+
# 1. In createTimer() call self.timer.start(0)
170+
# 2. In onTimer() call MessageLoopWork() only when
171+
# QtGui.QApplication.instance()->hasPendingEvents()
172+
# returns False.
173+
# But there is a bug in Qt, hasPendingEvents() returns
174+
# always true.
175+
# (The behavior described above was tested on Windows
176+
# with pyqt 4.8, maybe this is not true anymore,
177+
# test it TODO)
178+
cefpython.MessageLoopWork()
179+
180+
def stopTimer(self):
181+
# Stop the timer after Qt message loop ended, calls to
182+
# MessageLoopWork() should not happen anymore.
183+
self.timer.stop()
184+
185+
if __name__ == '__main__':
186+
print("PyQt version: %s" % QtCore.PYQT_VERSION_STR)
187+
print("QtCore version: %s" % QtCore.qVersion())
188+
189+
sys.excepthook = ExceptHook
190+
cefpython.g_debug = True
191+
cefpython.g_debugFile = GetApplicationPath("debug.log")
192+
193+
settings = {}
194+
settings["log_file"] = GetApplicationPath("debug.log")
195+
settings["log_severity"] = cefpython.LOGSEVERITY_INFO
196+
settings["release_dcheck_enabled"] = True # Enable only when debugging
197+
settings["locales_dir_path"] = cefpython.GetModuleDirectory()+"/locales"
198+
settings["resources_dir_path"] = cefpython.GetModuleDirectory()
199+
settings["browser_subprocess_path"] = "%s/%s" % (
200+
cefpython.GetModuleDirectory(), "subprocess")
201+
202+
cefpython.Initialize(settings)
203+
204+
app = CefApplication(sys.argv)
205+
mainWindow = MainWindow()
206+
mainWindow.show()
207+
app.exec_()
208+
app.stopTimer()
209+
210+
# Need to destroy QApplication(), otherwise Shutdown() fails.
211+
# Unset main window also just to be safe.
212+
del mainWindow
213+
del app
214+
215+
cefpython.Shutdown()

0 commit comments

Comments
 (0)